WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>, Jean Guyader <jean.guyader@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx, Ian Pratt <Ian.Pratt@xxxxxxxxxxxxx>, Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Kamala Narasimhan <Kamala.Narasimhan@xxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH] Pass-through a graphic card
From: Jean Guyader <jean.guyader@xxxxxxxxxxxxx>
Date: Fri, 16 May 2008 09:59:17 +0100
Delivery-date: Fri, 16 May 2008 01:59:44 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <482C1BDE.9060107@xxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <48243170.7050706@xxxxxxxxxxxxx> <482C0C3E.6050602@xxxxxxxxxxxxx> <20080515111323.GE5689@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx> <482C1BDE.9060107@xxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla-Thunderbird 2.0.0.12 (X11/20080420)

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