All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jean Guyader <jean.guyader@eu.citrix.com>
To: Samuel Thibault <samuel.thibault@eu.citrix.com>,
	Jean Guyader <jean.guyader@eu.citrix.com>,
	xen-devel@lists.xensource.com,
	Ian Pratt <Ian.Pratt@eu.citrix.com>, Keir Fraser <keir.fra>
Subject: Re: [PATCH] Pass-through a graphic card
Date: Fri, 16 May 2008 09:59:17 +0100	[thread overview]
Message-ID: <482D4CE5.2020503@eu.citrix.com> (raw)
In-Reply-To: <482C1BDE.9060107@eu.citrix.com>

[-- Attachment #1: Type: text/plain, Size: 1014 bytes --]


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@eu.citrix.com>

-- 
Jean Guyader

[-- Attachment #2: vga_pt5.patch --]
[-- Type: text/plain, Size: 26540 bytes --]

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:

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

  reply	other threads:[~2008-05-16  8:59 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-09 11:11 [PATCH] Pass-through a graphic card Jean Guyader
2008-05-09 11:18 ` Jean Guyader
2008-05-09 11:32   ` Samuel Thibault
2008-05-09 11:27 ` Samuel Thibault
2008-05-09 13:56 ` Jean Guyader
2008-05-09 14:02   ` Daniel P. Berrange
2008-05-09 14:25   ` Daniel P. Berrange
2008-05-09 15:47     ` Jean Guyader
2008-05-15 10:11 ` Jean Guyader
2008-05-15 11:13   ` Samuel Thibault
2008-05-15 11:17     ` Jean Guyader
2008-05-16  8:59       ` Jean Guyader [this message]
2008-05-16 17:15         ` Samuel Thibault
  -- strict thread matches above, loose matches on Subject: below --
2008-06-13 15:08 mail mark
2008-06-13 15:25 ` Jean Guyader
2008-06-21 17:36   ` mail mark
2008-06-21 19:28     ` Jean Guyader
2008-06-23 13:20       ` mail mark
2008-06-21 17:43   ` Neo Jia

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=482D4CE5.2020503@eu.citrix.com \
    --to=jean.guyader@eu.citrix.com \
    --cc=Ian.Pratt@eu.citrix.com \
    --cc=samuel.thibault@eu.citrix.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.