[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] Pass-through a graphic card




I new version (again). Here the change for this version :
  - No more modification of the hvm_info_table.
  - Creatation of a SCRATCH zone for hvmloader : 0x1000.
- Copy directly the VGABIOS at the right place (0xC0000) into the guest memory.
  - Detect which graphic card are present in pci_setup().
  - Remove the function cirrus_check
  - Add the support for some special keys for the dom0 driver.

---

This patch is for pass-through the principal graphic card to a hvm guest.

This is what is done inside :
- We map the VGA frame buffer into the guest's memory (0xa0000 -> 0xbffff) - We get the vga bios address into the guest memory. Etherboot has been moved to 0xD0000 to let enough space to load the dom0 vgabios (it could be pretty big).
  - Map the vga ioport 0x03c0 -> 0x03df.
- Then we start qemu with the new option -dom0-driver to have the dom0's keyboard and the mouse redirected into the guest.

  Signed-off-by: Jean Guyader <jean.guyader@xxxxxxxxxxxxx>

--
Jean Guyader
diff -r f65906f262f9 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 16 09:35:12 2008 +0100
@@ -23,11 +23,12 @@
 /* Memory map. */
 #define HYPERCALL_PHYSICAL_ADDRESS    0x00080000
 #define VGABIOS_PHYSICAL_ADDRESS      0x000C0000
-#define ETHERBOOT_PHYSICAL_ADDRESS    0x000C8000
+#define ETHERBOOT_PHYSICAL_ADDRESS    0x000D0000
 #define EXTBOOT_PHYSICAL_ADDRESS      0x000DF800
 #define SMBIOS_PHYSICAL_ADDRESS       0x000E9000
 #define SMBIOS_MAXIMUM_SIZE           0x00001000
 #define ACPI_PHYSICAL_ADDRESS         0x000EA000
 #define ROMBIOS_PHYSICAL_ADDRESS      0x000F0000
+#define SCRATCH_PHYSICAL_ADDRESS      0x00010000
 
 #endif /* __HVMLOADER_CONFIG_H__ */
diff -r f65906f262f9 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c      Fri May 16 09:35:12 2008 +0100
@@ -103,12 +103,8 @@ void create_mp_tables(void);
 void create_mp_tables(void);
 int hvm_write_smbios_tables(void);
 
-static int
-cirrus_check(void)
-{
-    outw(0x3C4, 0x9206);
-    return inb(0x3C5) == 0x12;
-}
+static int cirrus_checked = 0;
+static int stdvga_checked = 0;
 
 static void
 init_hypercalls(void)
@@ -165,7 +161,7 @@ static void pci_setup(void)
     /* Create a list of device BARs in descending order of size. */
     struct bars {
         uint32_t devfn, bar_reg, bar_sz;
-    } *bars = (struct bars *)0xc0000;
+    } *bars = (struct bars *)SCRATCH_PHYSICAL_ADDRESS;
     unsigned int i, nr_bars = 0;
 
     /* Program PCI-ISA bridge with appropriate link routes. */
@@ -190,6 +186,15 @@ static void pci_setup(void)
         device_id = pci_readw(devfn, PCI_DEVICE_ID);
         if ( (vendor_id == 0xffff) && (device_id == 0xffff) )
             continue;
+
+        /* Detect emulated graphic card */
+        if ( class == 0x300 )
+        {
+            if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
+                cirrus_checked = 1;
+            if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
+                stdvga_checked = 1;
+        }
 
         ASSERT((devfn != PCI_ISA_DEVFN) ||
                ((vendor_id == 0x8086) && (device_id == 0x7000)));
@@ -464,20 +469,22 @@ int main(void)
     if ( (get_vcpu_nr() > 1) || get_apic_mode() )
         create_mp_tables();
 
-    if ( cirrus_check() )
+    if ( cirrus_checked )
     {
         printf("Loading Cirrus VGABIOS ...\n");
         memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
                vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
         vgabios_sz = sizeof(vgabios_cirrusvga);
     }
-    else
+    else if ( stdvga_checked )
     {
         printf("Loading Standard VGABIOS ...\n");
         memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
                vgabios_stdvga, sizeof(vgabios_stdvga));
         vgabios_sz = sizeof(vgabios_stdvga);
     }
+    else
+        printf("VGABIOS must already be there ...\n");
 
     etherboot_sz = scan_etherboot_nic((void*)ETHERBOOT_PHYSICAL_ADDRESS);
 
diff -r f65906f262f9 tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/firmware/hvmloader/smbios.c Fri May 16 09:35:12 2008 +0100
@@ -217,15 +217,16 @@ hvm_write_smbios_tables(void)
 
     xen_version_str[sizeof(xen_version_str)-1] = '\0';
 
-    /* NB. 0xC0000 is a safe large memory area for scratch. */
-    len = write_smbios_tables((void *)0xC0000,
+    /* SCRATCH_PHYSICAL_ADDRESS is a safe large memory area for scratch. */
+    len = write_smbios_tables((void *)SCRATCH_PHYSICAL_ADDRESS,
                               get_vcpu_nr(), get_memsize(),
                               uuid, xen_version_str,
                               xen_major_version, xen_minor_version);
     if ( len > SMBIOS_MAXIMUM_SIZE )
         goto error_out;
     /* Okay, not too large: copy out of scratch to final location. */
-    memcpy((void *)SMBIOS_PHYSICAL_ADDRESS, (void *)0xC0000, len);
+    memcpy((void *)SMBIOS_PHYSICAL_ADDRESS,
+           (void *)SCRATCH_PHYSICAL_ADDRESS, len);
 
     return len;
 
diff -r f65906f262f9 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/Makefile.target       Fri May 16 09:35:12 2008 +0100
@@ -499,6 +499,9 @@ COCOA_LIBS+=-framework CoreAudio
 COCOA_LIBS+=-framework CoreAudio
 endif
 endif
+
+VL_OBJS+=dom0_driver.o
+
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
diff -r f65906f262f9 tools/ioemu/dom0_driver.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 16 09:35:12 2008 +0100
@@ -0,0 +1,204 @@
+/*
+ * QEMU dom0 /dev/input driver
+ * 
+ * Copyright (c) 2008 Citrix Systems
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+#include <sys/types.h>
+#include <linux/input.h>
+#include <linux/kd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define EVENT_PATH      "/dev/input/event"
+
+struct dom0_driver 
+{
+    int *event_fds;
+    int event_nb;
+    int mouse_button_state;
+};
+
+static struct dom0_driver driver;
+
+static void dom0_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dom0_resize(DisplayState *ds, int w, int h, int linesize)
+{
+}
+
+static void dom0_refresh(DisplayState *ds)
+{
+}
+
+static void dom0_read(void *opaque)
+{
+    struct input_event  event[5];
+    int                 i = 0;
+    int                 read_sz = 0;
+    int                 fd = *(int *)opaque;
+
+    read_sz = read(fd, event, sizeof (event));
+    for (i = 0; i < read_sz / (sizeof (struct input_event)); i++)
+    {
+        if (event[i].type == EV_KEY)
+        {
+            if (event[i].code >= BTN_MOUSE)
+            {
+                /* Mouse Key */
+                int     type = 0;
+                
+                switch(event[i].code)
+                {
+                    case BTN_LEFT: type = MOUSE_EVENT_LBUTTON; break;
+                    case BTN_RIGHT: type = MOUSE_EVENT_RBUTTON; break;
+                }
+
+                if (event[i].value)
+                    driver.mouse_button_state |= type;
+                else
+                    driver.mouse_button_state &= ~type;
+                kbd_mouse_event(0, 0, 0, driver.mouse_button_state);
+            }
+            else
+            {
+                /* Keyboard key */
+                int     code[2] = { event[i].code, -1 };
+                int     i = 0;
+
+                switch (event[i].code)
+                {
+                    case KEY_F11:       *code = 0X57; break; /* F11 */
+                    case KEY_F12:       *code = 0X58; break; /* F12 */
+                    case KEY_INSERT:    *code = 0X52; break;
+                    case KEY_HOME:      *code = 0X47; break;
+                    case KEY_PAGEUP:    *code = 0X49; break;
+                    case KEY_DELETE:    *code = 0X53; break;
+                    case KEY_END:       *code = 0X4F; break;
+                    case KEY_PAGEDOWN:  *code = 0X51; break;
+                    case KEY_UP:        *code = 0X48; break;
+                    case KEY_LEFT:      *code = 0X4B; break;
+                    case KEY_DOWN:      *code = 0X50; break;
+                    case KEY_RIGHT:     *code = 0X4D; break;
+                    case KEY_RIGHTALT:  *code = 0xE0; code[1] = 0x38; break;
+                }
+
+                for ( i = 0; i < 2; i++ )
+                    if (code[i] != -1)
+                        switch (event[i].value)
+                        {
+                            case 0:
+                                kbd_put_keycode(code[i] & 0x7f);
+                                break;
+                            case 1:
+                                kbd_put_keycode(code[i] | 0x80);
+                                break;
+                            case 2:
+                                kbd_put_keycode(code[i] | 0x80);
+                                kbd_put_keycode(code[i] & 0x7f);
+                                break;
+                        }
+            }
+        }
+
+        if (event[i].type == EV_REL)
+        {
+            /* Mouse motion */
+            int x = 0, y = 0, z = 0;
+
+            switch (event[i].code)
+            {
+                case REL_X : x = event[i].value; break;
+                case REL_Y : y = event[i].value; break;
+                case REL_WHEEL : z = -event[i].value; break;
+            }
+
+            kbd_mouse_event(x, y, z, driver.mouse_button_state);
+        }
+    }
+}
+
+static void dom0_driver_event_init()
+{
+    char                dev_name[strlen(EVENT_PATH) + 3];
+    int                 fd = -1;
+    int                 i = 0;
+
+    do
+    {
+        snprintf(dev_name, sizeof (dev_name), "%s%d", EVENT_PATH, i++);
+        if ((fd = open(dev_name, O_RDONLY)) == -1)
+            return;
+        printf("Using %s\n", dev_name);
+        
+        if (ioctl(fd, EVIOCGRAB, 1) == -1)
+        {
+            close(fd);
+            continue;
+        }
+
+        if (!(driver.event_fds = realloc(driver.event_fds,
+                                         (driver.event_nb + 1) * sizeof 
(int))))
+        {
+            fprintf(stderr, "dom0_driver: memory allocation failed\n");
+            exit(1);
+        }
+
+        driver.event_fds[driver.event_nb] = fd;
+        qemu_set_fd_handler(fd, dom0_read, NULL,
+                            &driver.event_fds[driver.event_nb]);
+        driver.event_nb++;
+    }
+    while (1);
+}
+
+static void dom0_driver_cleanup(void)
+{
+    free(driver.event_fds);
+}
+
+void dom0_driver_init(DisplayState *ds)
+{
+    memset(&driver, 0, sizeof (driver));
+
+    dom0_driver_event_init();
+
+    ds->data = NULL;
+    ds->linesize = 0;
+    ds->depth = 0;
+    ds->dpy_update = dom0_update;
+    ds->dpy_resize = dom0_resize;
+    ds->dpy_colourdepth = NULL;
+    ds->dpy_refresh = dom0_refresh;
+
+    atexit(dom0_driver_cleanup);
+}
diff -r f65906f262f9 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/hw/pc.c       Fri May 16 09:35:12 2008 +0100
@@ -43,6 +43,10 @@ static IOAPICState *ioapic;
 static IOAPICState *ioapic;
 #endif /* !CONFIG_DM */
 static PCIDevice *i440fx_state;
+
+#ifdef CONFIG_DM
+extern int dom0_input;
+#endif /* CONFIG_DM */
 
 static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
 {
@@ -814,6 +818,9 @@ static void pc_init1(uint64_t ram_size, 
     CPUState *env;
     NICInfo *nd;
     int rc;
+#ifdef CONFIG_DM
+    unsigned long vga_pt_enabled = dom0_input;
+#endif /* CONFIG_DM */
 
     linux_boot = (kernel_filename != NULL);
 
@@ -862,12 +869,18 @@ static void pc_init1(uint64_t ram_size, 
     }
 
     /* VGA BIOS load */
-    if (cirrus_vga_enabled) {
-        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
-    } else {
-        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+#ifdef CONFIG_DM
+    if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+    {
+        fprintf(stderr, "Load qemu pci vga\n");
+        if (cirrus_vga_enabled) {
+            snprintf(buf, sizeof(buf), "%s/%s", bios_dir, 
VGABIOS_CIRRUS_FILENAME);
+        } else {
+            snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+        }
+        ret = load_image(buf, phys_ram_base + vga_bios_offset);
     }
-    ret = load_image(buf, phys_ram_base + vga_bios_offset);
 #endif /* !NOBIOS */
     
     /* setup basic memory access */
@@ -925,22 +938,27 @@ static void pc_init1(uint64_t ram_size, 
 
     register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
 
-    if (cirrus_vga_enabled) {
-        if (pci_enabled) {
-            pci_cirrus_vga_init(pci_bus, 
-                                ds, NULL, ram_size, 
-                                vga_ram_size);
+#ifdef CONFIG_DM
+    if (!vga_pt_enabled)
+#endif /* CONFIG_DM */
+    {
+        if (cirrus_vga_enabled) {
+            if (pci_enabled) {
+                pci_cirrus_vga_init(pci_bus, 
+                                    ds, NULL, ram_size, 
+                                    vga_ram_size);
+            } else {
+                isa_cirrus_vga_init(ds, NULL, ram_size, 
+                                    vga_ram_size);
+            }
         } else {
-            isa_cirrus_vga_init(ds, NULL, ram_size, 
-                                vga_ram_size);
-        }
-    } else {
-        if (pci_enabled) {
-            pci_vga_init(pci_bus, ds, NULL, ram_size, 
-                         vga_ram_size, 0, 0);
-        } else {
-            isa_vga_init(ds, NULL, ram_size, 
-                         vga_ram_size);
+            if (pci_enabled) {
+                pci_vga_init(pci_bus, ds, NULL, ram_size, 
+                             vga_ram_size, 0, 0);
+            } else {
+                isa_vga_init(ds, NULL, ram_size, 
+                             vga_ram_size);
+            }
         }
     }
 
diff -r f65906f262f9 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/vl.c  Fri May 16 09:35:12 2008 +0100
@@ -177,6 +177,9 @@ int opengl_enabled = 1;
 #else
 int opengl_enabled = 0;
 #endif
+#ifdef CONFIG_DM
+int dom0_input = 0;
+#endif /* CONFIG_DM */
 int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -6486,8 +6489,9 @@ void help(void)
            "-no-quit        disable SDL window close capability\n"
 #endif
 #ifdef CONFIG_OPENGL
-           "-disable-opengl disable OpenGL rendering, using SDL"
-#endif
+           "-disable-opengl disable OpenGL rendering, using SDL\n"
+#endif
+           "-dom0-input     enable dom0 controling qemu\n"
 #ifdef TARGET_I386
            "-no-fd-bootchk  disable boot signature checking for floppy disks\n"
 #endif
@@ -6667,6 +6671,9 @@ enum {
     QEMU_OPTION_full_screen,
     QEMU_OPTION_no_quit,
     QEMU_OPTION_disable_opengl,
+#ifdef CONFIG_DM
+    QEMU_OPTION_dom0_input,
+#endif /* CONFIG_DM */
     QEMU_OPTION_pidfile,
     QEMU_OPTION_no_kqemu,
     QEMU_OPTION_kernel_kqemu,
@@ -6765,6 +6772,7 @@ const QEMUOption qemu_options[] = {
     { "no-quit", 0, QEMU_OPTION_no_quit },
 #endif
     { "disable-opengl", 0, QEMU_OPTION_disable_opengl },
+    { "dom0-input", 0, QEMU_OPTION_dom0_input },
     { "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
     { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
     { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice },
@@ -7516,6 +7524,11 @@ int main(int argc, char **argv)
             case QEMU_OPTION_disable_opengl:
                 opengl_enabled = 0;
                 break;
+#ifdef CONFIG_DM
+            case QEMU_OPTION_dom0_input:
+                dom0_input = 1;
+                break;
+#endif /* CONFIG_DM */
             case QEMU_OPTION_pidfile:
                 create_pidfile(optarg);
                 break;
@@ -7828,7 +7841,12 @@ int main(int argc, char **argv)
     } else
 #endif
     if (nographic) {
+#ifdef CONFIG_DM
+        if (dom0_input == 1)
+            dom0_driver_init(ds);
+#else
         dumb_display_init(ds);
+#endif /* CONFIG_DM */
     } else if (vnc_display != NULL || vncunused != 0) {
        int vnc_display_port;
        char password[20];
diff -r f65906f262f9 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Fri May 16 09:31:03 2008 +0100
+++ b/tools/ioemu/vl.h  Fri May 16 09:35:13 2008 +0100
@@ -1001,6 +1001,9 @@ void do_info_vnc(void);
 void do_info_vnc(void);
 int vnc_start_viewer(int port);
 
+/* dom0_driver.c */
+void dom0_driver_init(DisplayState *ds);
+
 /* x_keymap.c */
 extern uint8_t _translate_keycode(const int key);
 
diff -r f65906f262f9 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c        Fri May 16 09:35:13 2008 +0100
@@ -152,6 +152,52 @@ static int loadelfimage(
     if ( entries )
         free(entries);
 
+    return rc;
+}
+
+static int  setup_vga_pt(int            xc_handle,
+                         uint32_t       dom)
+{
+    int                 rc = 0;
+    unsigned char       *bios = NULL;
+    int                 bios_size = 0;
+    char                *va_bios = NULL;
+    uint32_t            va_size = 0;
+    
+    /* Allocated 64K for the vga bios */
+    if (!(bios = malloc(64 * 1024)))
+        return -1;
+
+#ifdef __linux__
+    bios_size = xc_get_vgabios(bios, 64 * 1024);
+#else
+    bios_size = 0;
+#endif /* __linux__ */
+
+    va_size = bios_size + bios_size % XC_PAGE_SIZE;
+    if (bios_size == 0)
+    {
+        rc = -1;
+        goto error;
+    }
+    va_bios = xc_map_foreign_range(xc_handle, dom, va_size,
+                                   PROT_READ | PROT_WRITE, 0xC0);
+    if (!va_bios)
+    {
+        rc = -1;
+        goto error;
+    }
+
+    memcpy(va_bios, bios, bios_size);
+    munmap(va_bios, va_size);
+    rc |= xc_domain_memory_mapping(xc_handle, dom,
+                                   0xa0000 >> XC_PAGE_SHIFT,
+                                   0xa0000 >> XC_PAGE_SHIFT,
+                                   (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT, 1);
+    rc |= xc_domain_ioport_mapping(xc_handle, dom,
+                                   0x3C0, 0x3C0, 32, 1);
+error:
+    free(bios);
     return rc;
 }
 
@@ -388,17 +434,20 @@ int xc_hvm_build(int xc_handle,
 int xc_hvm_build(int xc_handle,
                  uint32_t domid,
                  int memsize,
-                 const char *image_name)
+                 const char *image_name,
+                 int vga_pt_enabled)
 {
     char *image;
-    int  sts;
+    int  sts = 0;
     unsigned long image_size;
 
     if ( (image_name == NULL) ||
          ((image = xc_read_image(image_name, &image_size)) == NULL) )
         return -1;
 
-    sts = xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+    sts |= xc_hvm_build_internal(xc_handle, domid, memsize, image, image_size);
+    if ( vga_pt_enabled )
+        sts |= setup_vga_pt(xc_handle, domid);
 
     free(image);
 
diff -r f65906f262f9 tools/libxc/xc_linux.c
--- a/tools/libxc/xc_linux.c    Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xc_linux.c    Fri May 16 09:35:13 2008 +0100
@@ -518,6 +518,30 @@ int xc_gnttab_set_max_grants(int xcg_han
     return 0;
 }
 
+int xc_get_vgabios(unsigned char        *buf,
+                   int                  len)
+{
+    int         mem;
+    uint32_t    start, end, size;
+
+    start = 0xC0000;
+    end = 0xCAFFF;
+    size = end - start + 1;
+    if (len < size)
+        return 0;
+    if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+        return 0;
+    if (start != lseek(mem, start, SEEK_SET))
+    {
+        close(mem);
+        return 0;
+    }
+    if (size != read(mem, buf, size))
+        size = 0;
+    close(mem);
+    return size;
+} 
+
 /*
  * Local variables:
  * mode: C
diff -r f65906f262f9 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xenctrl.h     Fri May 16 09:35:13 2008 +0100
@@ -138,6 +138,10 @@ int xc_waitdomain(
     int domain,
     int *status,
     int options);
+
+int xc_get_vgabios(
+    unsigned char       *bios,
+    int                 len);
 
 #endif /* __linux__ */
 
diff -r f65906f262f9 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xenguest.h    Fri May 16 09:35:13 2008 +0100
@@ -128,7 +128,8 @@ int xc_hvm_build(int xc_handle,
 int xc_hvm_build(int xc_handle,
                  uint32_t domid,
                  int memsize,
-                 const char *image_name);
+                 const char *image_name,
+                 int vga_pt_enabled);
 
 int xc_hvm_build_mem(int xc_handle,
                      uint32_t domid,
diff -r f65906f262f9 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Fri May 16 09:31:03 2008 +0100
+++ b/tools/libxc/xg_private.c  Fri May 16 09:35:13 2008 +0100
@@ -193,7 +193,8 @@ __attribute__((weak))
     int xc_hvm_build(int xc_handle,
                      uint32_t domid,
                      int memsize,
-                     const char *image_name)
+                     const char *image_name,
+                     int vga_pt_enabled)
 {
     errno = ENOSYS;
     return -1;
diff -r f65906f262f9 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 16 09:35:13 2008 +0100
@@ -726,17 +726,17 @@ static PyObject *pyxc_hvm_build(XcObject
     int i;
 #endif
     char *image;
-    int memsize, vcpus = 1, acpi = 0, apic = 1;
+    int memsize, vcpus = 1, acpi = 0, apic = 1, vga_pt = 0;
 
     static char *kwd_list[] = { "domid",
                                "memsize", "image", "vcpus", "acpi",
-                               "apic", NULL };
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iii", kwd_list,
+                               "apic", "vga_pt", NULL };
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
                                       &dom, &memsize,
-                                      &image, &vcpus, &acpi, &apic) )
+                                      &image, &vcpus, &acpi, &apic, &vga_pt) )
         return NULL;
 
-    if ( xc_hvm_build(self->xc_handle, dom, memsize, image) != 0 )
+    if ( xc_hvm_build(self->xc_handle, dom, memsize, image, vga_pt) != 0 )
         return pyxc_error_to_exception();
 
 #if !defined(__ia64__)
diff -r f65906f262f9 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Fri May 16 09:35:13 2008 +0100
@@ -160,6 +160,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
     'vhpt': int,
     'guest_os_type': str,
     'hap': int,
+    'vga_passthrough' : int,
 }
 
 # Xen API console 'other_config' keys.
diff -r f65906f262f9 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xend/image.py    Fri May 16 09:35:13 2008 +0100
@@ -240,6 +240,8 @@ class ImageHandler:
         vnc_config = {}
         has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
         has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+        has_vga_passthrough = int(vmConfig['platform'].get('vga_passthrough', 
0)) != 0;
+
         opengl = 1
         for dev_uuid in vmConfig['console_refs']:
             dev_type, dev_info = vmConfig['devices'][dev_uuid]
@@ -260,7 +262,7 @@ class ImageHandler:
             ret.append("-k")
             ret.append(keymap)
 
-        if has_vnc:
+        if has_vnc and not has_vga_passthrough:
             if not vnc_config:
                 for key in ('vncunused', 'vnclisten', 'vncdisplay',
                             'vncpasswd'):
@@ -310,6 +312,10 @@ class ImageHandler:
 
         if int(vmConfig['platform'].get('monitor', 0)) != 0:
             ret = ret + ['-monitor', 'vc']
+
+        if has_vga_passthrough:
+            ret.append('-dom0-input');
+
         return ret
 
     def getDeviceModelArgs(self, restore = False):
@@ -536,6 +542,7 @@ class HVMImageHandler(ImageHandler):
         self.apic = int(vmConfig['platform'].get('apic', 0))
         self.acpi = int(vmConfig['platform'].get('acpi', 0))
         self.guest_os_type = vmConfig['platform'].get('guest_os_type')
+        self.vga_pt = int(vmConfig['platform'].get('vga_passthrough', 0))
 
         self.vmConfig = vmConfig
            
@@ -668,13 +675,15 @@ class HVMImageHandler(ImageHandler):
         log.debug("vcpus          = %d", self.vm.getVCpuCount())
         log.debug("acpi           = %d", self.acpi)
         log.debug("apic           = %d", self.apic)
+        log.debug("vga_pt         = %d", self.vga_pt)
 
         rc = xc.hvm_build(domid          = self.vm.getDomid(),
                           image          = self.loader,
                           memsize        = mem_mb,
                           vcpus          = self.vm.getVCpuCount(),
                           acpi           = self.acpi,
-                          apic           = self.apic)
+                          apic           = self.apic,
+                          vga_pt         = self.vga_pt)
         rc['notes'] = { 'SUSPEND_CANCEL': 1 }
 
         rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r f65906f262f9 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Fri May 16 09:31:03 2008 +0100
+++ b/tools/python/xen/xm/create.py     Fri May 16 09:35:13 2008 +0100
@@ -557,6 +557,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:e
           fn=append_value, default=[],
           use="""Cpuid check description.""")
 
+gopts.var('vga_passthrough', val='VGA_PT',
+          fn=set_int, default=None,
+          use="Enable the passthrough for the graphic card.")
+
 def err(msg):
     """Print an error to stderr and exit.
     """
@@ -765,7 +769,8 @@ def configure_hvm(config_image, vals):
              'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
              'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
              'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
-             'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
+             'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
+             'vga_passthrough' ]
 
     for a in args:
         if a in vals.__dict__ and vals.__dict__[a] is not None:
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.