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: "Daniel P. Berrange" <berrange@xxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH] Pass-through a graphic card
From: Jean Guyader <jean.guyader@xxxxxxxxxxxxx>
Date: Fri, 09 May 2008 16:47:53 +0100
Cc: Ian Pratt <Ian.Pratt@xxxxxxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxx, Keir Fraser <keir.fraser@xxxxxxxxxxxxx>, Kamala Narasimhan <Kamala.Narasimhan@xxxxxxxxxx>
Delivery-date: Fri, 09 May 2008 08:49:04 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <20080509142543.GC2265@xxxxxxxxxx>
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> <4824581F.7050904@xxxxxxxxxxxxx> <20080509142543.GC2265@xxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla-Thunderbird 2.0.0.9 (X11/20080110)

Thanks for the feedbacks.

Here a new version of this patch with more error handling.

--
Jean Guyader
diff -r 810d8c3ac992 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/config.h Fri May 09 16:47:04 2008 +0100
@@ -23,7 +23,7 @@
 /* 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
diff -r 810d8c3ac992 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/hvmloader.c      Fri May 09 16:47:04 2008 +0100
@@ -464,7 +464,16 @@ int main(void)
     if ( (get_vcpu_nr() > 1) || get_apic_mode() )
         create_mp_tables();
 
-    if ( cirrus_check() )
+    if ( get_vga_pt_enabled() )
+    {
+        printf("Loading dom0 VGABIOS ...\n");
+        printf("  - 0x%x (0x%x)\n", get_vga_pt_bios_paddr(), 
get_vga_pt_bios_size());
+        memcpy((void*)VGABIOS_PHYSICAL_ADDRESS,
+               (void*)get_vga_pt_bios_paddr(), 
+               get_vga_pt_bios_size());
+        vgabios_sz = get_vga_pt_bios_size();
+    }
+    else if ( cirrus_check() )
     {
         printf("Loading Cirrus VGABIOS ...\n");
         memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.c   Fri May 09 16:47:04 2008 +0100
@@ -594,6 +594,24 @@ int get_vcpu_nr(void)
     return (t ? t->nr_vcpus : 1);
 }
 
+int get_vga_pt_enabled(void)
+{
+    struct hvm_info_table *t = get_hvm_info_table();
+    return (t && t->vga_bios_paddr > 0);
+}
+
+int get_vga_pt_bios_paddr(void)
+{
+    struct hvm_info_table *t = get_hvm_info_table();
+    return (t ? t->vga_bios_paddr : 0);
+}
+
+int get_vga_pt_bios_size(void)
+{
+    struct hvm_info_table *t = get_hvm_info_table();
+    return (t ? t->vga_bios_size : -1);
+}
+
 int get_acpi_enabled(void)
 {
     struct hvm_info_table *t = get_hvm_info_table();
diff -r 810d8c3ac992 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Thu May 08 16:58:33 2008 +0100
+++ b/tools/firmware/hvmloader/util.h   Fri May 09 16:47:04 2008 +0100
@@ -106,6 +106,9 @@ int get_vcpu_nr(void);
 int get_vcpu_nr(void);
 int get_acpi_enabled(void);
 int get_apic_mode(void);
+int get_vga_pt_enabled(void);
+int get_vga_pt_bios_paddr(void);
+int get_vga_pt_bios_size(void);
 
 /* String and memory functions */
 int strcmp(const char *cs, const char *ct);
diff -r 810d8c3ac992 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target       Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/Makefile.target       Fri May 09 16:47:04 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 810d8c3ac992 tools/ioemu/dom0_driver.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/dom0_driver.c Fri May 09 16:47:04 2008 +0100
@@ -0,0 +1,172 @@
+/*
+ * 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>
+
+#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 */
+                if (event[i].value == 1)
+                    kbd_put_keycode(event[i].code | 0x80);
+                else
+                    kbd_put_keycode(event[i].code & 0x7f);
+            }
+        }
+
+        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 810d8c3ac992 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/hw/pc.c       Fri May 09 16:47:04 2008 +0100
@@ -814,6 +814,19 @@ static void pc_init1(uint64_t ram_size, 
     CPUState *env;
     NICInfo *nd;
     int rc;
+#ifdef CONFIG_DM
+    unsigned long vga_pt_enabled = 0;
+#endif /* CONFIG_DM */
+
+#ifdef CONFIG_DM
+    if (xc_get_hvm_param(xc_handle, domid,
+                         HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled))
+    {
+        fprintf(stderr, "vga passthrough : xc_get_hvm_param failed\n");
+        exit(1);
+    }
+
+#endif /* CONFIG_DM */
 
     linux_boot = (kernel_filename != NULL);
 
@@ -862,12 +875,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 +944,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 810d8c3ac992 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.c  Fri May 09 16:47:04 2008 +0100
@@ -179,6 +179,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;
@@ -7823,12 +7836,18 @@ int main(int argc, char **argv)
     init_ioports();
 
     /* terminal init */
+
 #ifdef CONFIG_STUBDOM
     if (xenfb_pv_display_init(ds) == 0) {
     } 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 810d8c3ac992 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Thu May 08 16:58:33 2008 +0100
+++ b/tools/ioemu/vl.h  Fri May 09 16:47:04 2008 +0100
@@ -997,6 +997,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 810d8c3ac992 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c        Fri May 09 16:47:04 2008 +0100
@@ -152,9 +152,134 @@ static int loadelfimage(
     return rc;
 }
 
+static int linux_get_vgabios(int               xc_handle,
+                             unsigned char     *buf,
+                             int               len)
+{
+    char        buff[1024];
+    FILE        *fd;
+    int         mem;
+    char        *end_ptr;
+    uint32_t    start, end, size;
+
+    if (!(fd = fopen("/proc/iomem", "r")))
+        return 0;
+
+    while (fgets(buff, 1024, fd))
+        if (strstr(buff, "Video ROM"))
+            break;
+
+    if (feof(fd) || ferror(fd))
+    {
+        fclose(fd);
+        return 0; 
+    }
+
+    fclose(fd);
+    start = strtol(buff, &end_ptr, 16);
+    end = strtol(end_ptr + 1, NULL, 16);
+    size = end - start + 1;
+
+    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;
+} 
+
+static int  linux_map_vga_ioport(int            xc_handler,
+                                 uint32_t       dom)
+{
+    FILE        *fd = NULL;
+    char        buff[256];
+    uint32_t    start, end;
+    char        *buff_end = NULL;
+    
+    if (!(fd = fopen("/proc/ioports", "r")))
+        return -1;
+    
+    while (fgets(buff, 256, fd))
+        if (strstr(buff, "vga"))
+            break;
+    
+    if (feof(fd) || ferror(fd))
+    {
+        fclose(fd);
+        return -1;
+    }
+
+    fclose(fd);
+    
+    start = strtol(buff, &buff_end, 16);
+    end = strtol(buff_end + 1, NULL, 16);
+
+    return xc_domain_ioport_mapping(xc_handler, dom,
+                                    start, start, end - start + 1, 1);
+}
+
+static int  setup_vga_pt(int                    xc_handle,
+                         uint32_t               dom,
+                         uint32_t               paddr,
+                         struct hvm_info_table  *hvm_info)
+{
+    int                 rc = 0;
+    unsigned char       *bios = NULL;
+    int                 bios_size = 0;
+    char                *va_bios = NULL;
+    uint32_t            pfn = 0;
+    
+    /* Allocated 128K for the vga bios */
+    if (!(bios = malloc(128 * 1024)))
+        return -1;
+
+    /* Align paddr on the first next page */
+    pfn = (paddr >> XC_PAGE_SHIFT) + 1; 
+
+    bios_size = linux_get_vgabios(xc_handle, bios, 128 * 1024);
+    if (bios_size == 0)
+    {
+        rc = -1;
+        goto error;
+    }
+   
+    va_bios = xc_map_foreign_range(xc_handle, dom,
+                                   bios_size + bios_size % XC_PAGE_SIZE,
+                                   PROT_READ | PROT_WRITE, pfn);
+    if (!va_bios)
+    {
+        rc = -1;
+        goto error;
+    }
+
+    memcpy(va_bios, bios, bios_size);
+    hvm_info->vga_bios_paddr = pfn << XC_PAGE_SHIFT; 
+    hvm_info->vga_bios_size = bios_size;
+    munmap(va_bios, bios_size + bios_size % XC_PAGE_SIZE);
+    
+    rc |= xc_domain_memory_mapping(xc_handle, dom,
+                                   0xa0000 >> XC_PAGE_SHIFT,
+                                   0xa0000 >> XC_PAGE_SHIFT,
+                                   (0xc0000 - 0xa0000) >> XC_PAGE_SHIFT,
+                                   1);
+    rc |= linux_map_vga_ioport(xc_handle, dom);
+
+error:
+    free(bios);
+    return rc;
+}
+
 static int setup_guest(int xc_handle,
                        uint32_t dom, int memsize,
-                       char *image, unsigned long image_size)
+                       char *image, unsigned long image_size,
+                       struct hvm_info_table *hvm_info)
 {
     xen_pfn_t *page_array = NULL;
     unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
@@ -167,6 +292,7 @@ static int setup_guest(int xc_handle,
     uint64_t v_start, v_end;
     int rc;
     xen_capabilities_info_t caps;
+    unsigned long vga_pt_enabled = 0;
 
     /* An HVM guest must be initialised with at least 2MB memory. */
     if ( memsize < 2 )
@@ -314,6 +440,14 @@ static int setup_guest(int xc_handle,
     }
 
     free(page_array);
+
+    /* Setup VGA pass through */
+    if ( xc_get_hvm_param(xc_handle, dom,
+                          HVM_PARAM_VGA_PT_ENABLED, &vga_pt_enabled) )
+        return -1;
+    if ( vga_pt_enabled )
+        return setup_vga_pt(xc_handle, dom, elf.pend, hvm_info);
+
     return 0;
 
  error_out:
@@ -325,7 +459,8 @@ static int xc_hvm_build_internal(int xc_
                                  uint32_t domid,
                                  int memsize,
                                  char *image,
-                                 unsigned long image_size)
+                                 unsigned long image_size,
+                                 struct hvm_info_table *hvm_info)
 {
     if ( (image == NULL) || (image_size == 0) )
     {
@@ -333,7 +468,7 @@ static int xc_hvm_build_internal(int xc_
         return -1;
     }
 
-    return setup_guest(xc_handle, domid, memsize, image, image_size);
+    return setup_guest(xc_handle, domid, memsize, image, image_size, hvm_info);
 }
 
 static inline int is_loadable_phdr(Elf32_Phdr *phdr)
@@ -348,7 +483,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,
+                 struct hvm_info_table *hvm_info)
 {
     char *image;
     int  sts;
@@ -358,7 +494,8 @@ int xc_hvm_build(int xc_handle,
          ((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, hvm_info);
 
     free(image);
 
@@ -372,7 +509,8 @@ int xc_hvm_build_mem(int xc_handle,
                      uint32_t domid,
                      int memsize,
                      const char *image_buffer,
-                     unsigned long image_size)
+                     unsigned long image_size,
+                     struct hvm_info_table *hvm_info)
 {
     int           sts;
     unsigned long img_len;
@@ -394,7 +532,7 @@ int xc_hvm_build_mem(int xc_handle,
     }
 
     sts = xc_hvm_build_internal(xc_handle, domid, memsize,
-                                img, img_len);
+                                img, img_len, hvm_info);
 
     /* xc_inflate_buffer may return the original buffer pointer (for
        for already inflated buffers), so exercise some care in freeing */
diff -r 810d8c3ac992 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenctrl.h     Fri May 09 16:47:04 2008 +0100
@@ -30,6 +30,7 @@
 #include <xen/xsm/acm.h>
 #include <xen/xsm/acm_ops.h>
 #include <xen/xsm/flask_op.h>
+#include <xen/hvm/params.h>
 
 #ifdef __ia64__
 #define XC_PAGE_SHIFT           14
diff -r 810d8c3ac992 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xenguest.h    Fri May 09 16:47:04 2008 +0100
@@ -6,6 +6,8 @@
  * Copyright (c) 2003-2004, K A Fraser.
  */
 
+#include <xen/hvm/hvm_info_table.h>
+
 #ifndef XENGUEST_H
 #define XENGUEST_H
 
@@ -13,7 +15,6 @@
 #define XCFLAGS_DEBUG     2
 #define XCFLAGS_HVM       4
 #define XCFLAGS_STDVGA    8
-
 
 /**
  * This function will save a running domain.
@@ -128,12 +129,14 @@ 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,
+                 struct hvm_info_table *hvm_info);
 
 int xc_hvm_build_mem(int xc_handle,
                      uint32_t domid,
                      int memsize,
                      const char *image_buffer,
-                     unsigned long image_size);
+                     unsigned long image_size,
+                     struct hvm_info_table *hvm_info);
 
 #endif /* XENGUEST_H */
diff -r 810d8c3ac992 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Thu May 08 16:58:33 2008 +0100
+++ b/tools/libxc/xg_private.c  Fri May 09 16:47:04 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,
+                     struct hvm_info_table *hvm_info)
 {
     errno = ENOSYS;
     return -1;
diff -r 810d8c3ac992 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri May 09 16:47:04 2008 +0100
@@ -721,22 +721,28 @@ static PyObject *pyxc_hvm_build(XcObject
 {
     uint32_t dom;
 #if !defined(__ia64__)
+    struct hvm_info_table hvm_info;
     struct hvm_info_table *va_hvm;
     uint8_t *va_map, sum;
     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_set_hvm_param(self->xc_handle, dom,
+                          HVM_PARAM_VGA_PT_ENABLED, vga_pt) )
+         return pyxc_error_to_exception();
+
+    memset(&hvm_info, 0, sizeof(hvm_info));
+    if ( xc_hvm_build(self->xc_handle, dom, memsize, image, &hvm_info) != 0 )
         return pyxc_error_to_exception();
 
 #if !defined(__ia64__)
@@ -747,7 +753,7 @@ static PyObject *pyxc_hvm_build(XcObject
     if ( va_map == NULL )
         return PyErr_SetFromErrno(xc_error_obj);
     va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
-    memset(va_hvm, 0, sizeof(*va_hvm));
+    memcpy(va_hvm, &hvm_info, sizeof (*va_hvm));
     strncpy(va_hvm->signature, "HVM INFO", 8);
     va_hvm->length       = sizeof(struct hvm_info_table);
     va_hvm->acpi_enabled = acpi;
diff -r 810d8c3ac992 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Fri May 09 16:47:04 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 810d8c3ac992 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xend/image.py    Fri May 09 16:47:04 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
            
@@ -661,6 +668,7 @@ class HVMImageHandler(ImageHandler):
 
         mem_mb = self.getRequiredInitialReservation() / 1024
 
+        log.debug(self.vmConfig)
         log.debug("domid          = %d", self.vm.getDomid())
         log.debug("image          = %s", self.loader)
         log.debug("store_evtchn   = %d", store_evtchn)
@@ -668,13 +676,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 810d8c3ac992 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu May 08 16:58:33 2008 +0100
+++ b/tools/python/xen/xm/create.py     Fri May 09 16:47:04 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.
     """
@@ -763,7 +767,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:
diff -r 810d8c3ac992 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu May 08 16:58:33 2008 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Fri May 09 16:47:04 2008 +0100
@@ -310,7 +310,8 @@ int hvm_domain_initialise(struct domain 
     if ( rc != 0 )
         goto fail1;
 
-    stdvga_init(d);
+    if ( !d->arch.hvm_domain.params[HVM_PARAM_VGA_PT_ENABLED] )
+        stdvga_init(d);
 
     hvm_init_ioreq_page(d, &d->arch.hvm_domain.ioreq);
     hvm_init_ioreq_page(d, &d->arch.hvm_domain.buf_ioreq);
diff -r 810d8c3ac992 xen/include/public/hvm/hvm_info_table.h
--- a/xen/include/public/hvm/hvm_info_table.h   Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/hvm_info_table.h   Fri May 09 16:47:04 2008 +0100
@@ -36,6 +36,9 @@ struct hvm_info_table {
     uint8_t     acpi_enabled;
     uint8_t     apic_mode;
     uint32_t    nr_vcpus;
+    uint32_t    vga_bios_paddr;
+    uint32_t    vga_bios_size;
+
 };
 
 #endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */
diff -r 810d8c3ac992 xen/include/public/hvm/params.h
--- a/xen/include/public/hvm/params.h   Thu May 08 16:58:33 2008 +0100
+++ b/xen/include/public/hvm/params.h   Fri May 09 16:47:04 2008 +0100
@@ -90,6 +90,9 @@
 /* Device Model domain, defaults to 0. */
 #define HVM_PARAM_DM_DOMAIN    13
 
-#define HVM_NR_PARAMS          14
+/* Boolean : VGA passthrough */
+#define HVM_PARAM_VGA_PT_ENABLED 14
+
+#define HVM_NR_PARAMS          15
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel