All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] graphics passthrough with VT-d
@ 2009-08-28  7:54 Han, Weidong
  2009-08-28  8:12 ` Jean Guyader
  2009-08-28  8:45 ` Keir Fraser
  0 siblings, 2 replies; 15+ messages in thread
From: Han, Weidong @ 2009-08-28  7:54 UTC (permalink / raw)
  To: 'xen-devel@lists.xensource.com'
  Cc: Lin, Ben Y, 'bengheng@eecs.umich.edu', Kay, Allen M,
	'Keir.Fraser@eu.citrix.com', 'Jean Guyader'

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

This patch supports basic gfx passthrough on xen side:
  - retrieves VGA bios from host VGA BIOS address (0xC0000), then load it to guest VGA BIOS address (This is the same with XCI).
  - Enlarge guest MMIO range to contain gfx card's large memory 
  - add a config option 'gfx_passthru' for gfx passthrough

Signed-off-by: Ben Lin <ben.y.lin@intel.com>
Signed-off-by: Weidong Han <weidong.han@intel.com>

[-- Attachment #2: xen-gfx-passthrough.patch --]
[-- Type: application/octet-stream, Size: 12565 bytes --]

diff -r 5d7e7a250267 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/firmware/hvmloader/config.h	Thu Aug 27 16:54:24 2009 +0800
@@ -15,7 +15,7 @@
 #define PCI_ISA_IRQ_MASK    0x0c20U /* ISA IRQs 5,10,11 are PCI connected */
 
 /* MMIO hole: Hardcoded defaults, which can be dynamically expanded. */
-#define PCI_MEM_START       0xf0000000
+#define PCI_MEM_START       0xe0000000
 #define PCI_MEM_END         0xfc000000
 extern unsigned long pci_mem_start, pci_mem_end;
 
diff -r 5d7e7a250267 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/firmware/hvmloader/hvmloader.c	Fri Aug 28 14:41:22 2009 +0800
@@ -113,7 +113,7 @@ unsigned long pci_mem_start = PCI_MEM_ST
 unsigned long pci_mem_start = PCI_MEM_START;
 unsigned long pci_mem_end = PCI_MEM_END;
 
-static enum { VGA_none, VGA_std, VGA_cirrus } virtual_vga = VGA_none;
+static enum { VGA_none, VGA_std, VGA_cirrus, VGA_pt } virtual_vga = VGA_none;
 
 static void init_hypercalls(void)
 {
@@ -212,8 +212,10 @@ static void pci_setup(void)
         case 0x0300:
             if ( (vendor_id == 0x1234) && (device_id == 0x1111) )
                 virtual_vga = VGA_std;
-            if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
+            else if ( (vendor_id == 0x1013) && (device_id == 0xb8) )
                 virtual_vga = VGA_cirrus;
+            else
+                virtual_vga = VGA_pt;
             break;
         case 0x0680:
             /* PIIX4 ACPI PM. Special device with special PCI config space. */
@@ -684,6 +686,11 @@ int main(void)
         memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
                vgabios_stdvga, sizeof(vgabios_stdvga));
         vgabios_sz = round_option_rom(sizeof(vgabios_stdvga));
+        break;
+    case VGA_pt:
+        printf("Loading VGABIOS of passthroughed gfx ...\n");
+        vgabios_sz =
+            round_option_rom((*(uint8_t *)(VGABIOS_PHYSICAL_ADDRESS+2)) * 512);
         break;
     default:
         printf("No emulated VGA adaptor ...\n");
diff -r 5d7e7a250267 tools/libxc/ia64/xc_ia64_hvm_build.c
--- a/tools/libxc/ia64/xc_ia64_hvm_build.c	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/libxc/ia64/xc_ia64_hvm_build.c	Thu Aug 27 16:54:24 2009 +0800
@@ -1109,7 +1109,9 @@ int xc_hvm_build_target_mem(int xc_handl
                             uint32_t domid,
                             int memsize,
                             int target,
-                            const char *image_name)
+                            const char *image_name,
+                            int gfx_passthru)
+
 {
     /* XXX:PoD isn't supported yet */
     return xc_hvm_build(xc_handle, domid, target, image_name);
diff -r 5d7e7a250267 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/libxc/xc_hvm_build.c	Thu Aug 27 16:54:24 2009 +0800
@@ -64,6 +64,67 @@ static void build_hvm_info(void *hvm_inf
     for ( i = 0, sum = 0; i < hvm_info->length; i++ )
         sum += ((uint8_t *)hvm_info)[i];
     hvm_info->checksum = -sum;
+}
+
+static int init_vgabios(int xc_handle, uint32_t dom,
+                        unsigned char *buffer, uint32_t bios_size)
+{
+    char *va_bios = NULL;
+    uint32_t va_size = 0;
+
+    va_size = bios_size + bios_size % XC_PAGE_SIZE;
+    va_bios = xc_map_foreign_range(xc_handle, dom, va_size,
+                                   PROT_READ | PROT_WRITE, 0xC0);
+    if ( !va_bios )
+    {
+        IPRINTF("Unable to map vga bios!\n");
+        return -1;
+    }
+
+    if ( buffer != NULL )
+        memcpy(va_bios, buffer, bios_size);
+    else
+        memset(va_bios, 0, bios_size);
+
+    munmap(va_bios, va_size);
+    return 0;
+}
+
+static int setup_vga_pt(int xc_handle, uint32_t dom)
+{
+    int                 rc = 0;
+    unsigned char       *bios = NULL;
+    int                 bios_size = 0;
+    char                *c = NULL;
+    char                checksum = 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__ */
+
+    if (bios_size == 0)
+    {
+        IPRINTF("vga bios size is 0!\n");
+        rc = -1;
+        goto error;
+    }
+
+    /* Adjust the bios checksum */
+    for ( c = (char*)bios; c < ((char*)bios + bios_size); c++ )
+        checksum += *c;
+    if (checksum)
+        bios[bios_size - 1] -= checksum;
+
+    init_vgabios(xc_handle, dom, bios, bios_size);
+error:
+    free(bios);
+    return rc;
 }
 
 static int loadelfimage(
@@ -381,7 +442,8 @@ int xc_hvm_build_target_mem(int xc_handl
                            uint32_t domid,
                            int memsize,
                            int target,
-                           const char *image_name)
+                           const char *image_name,
+                           int gfx_passthru)
 {
     char *image;
     int  sts;
@@ -392,6 +454,11 @@ int xc_hvm_build_target_mem(int xc_handl
         return -1;
 
     sts = xc_hvm_build_internal(xc_handle, domid, memsize, target, image, image_size);
+
+    if ( gfx_passthru )
+        sts |= setup_vga_pt(xc_handle, domid);
+    else
+        sts |= init_vgabios(xc_handle, domid, NULL, 0x800);
 
     free(image);
 
diff -r 5d7e7a250267 tools/libxc/xc_linux.c
--- a/tools/libxc/xc_linux.c	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/libxc/xc_linux.c	Thu Aug 27 16:54:24 2009 +0800
@@ -638,6 +638,56 @@ err:
     return gnt;
 }
 
+int xc_get_vgabios(unsigned char        *buf,
+                   int                  len)
+{
+    int         mem;
+    uint32_t    start, size = 0;
+    uint16_t    magic = 0;
+
+    start = 0xC0000;
+    if (len < size)
+        return 0;
+    if ((mem = open("/dev/mem", O_RDONLY)) < 0)
+        return 0;
+
+    /*
+    ** Check if it a real bios extension.
+    ** The magic number is 0xAA55.
+    */
+    if (start != lseek(mem, start, SEEK_SET))
+        goto out;
+    if (read(mem, &magic, 2) != 2)
+        goto out;
+    if (magic != 0xAA55)
+        goto out;
+    /* Find the size of the rom extension */
+    if (start != lseek(mem, start, SEEK_SET))
+        goto out;
+    if (lseek(mem, 2, SEEK_CUR) != (start + 2))
+        goto out;
+    if (read(mem, &size, 1) != 1)
+        goto out;
+    /* This size is in 512K */
+    size *= 512;
+
+    /*
+    ** Set the file to the begining of the rombios,
+    ** to start the copy.
+    */
+    if (start != lseek(mem, start, SEEK_SET))
+    {
+        size = 0;
+        goto out;
+    }
+    if (size != read(mem, buf, size))
+        size = 0;
+
+out:
+    close(mem);
+    return size;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 5d7e7a250267 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/libxc/xenctrl.h	Thu Aug 27 16:54:24 2009 +0800
@@ -1285,4 +1285,6 @@ int xc_tmem_restore(int xc_handle, int d
 int xc_tmem_restore(int xc_handle, int dom, int fd);
 int xc_tmem_restore_extra(int xc_handle, int dom, int fd);
 
+int xc_get_vgabios(unsigned char *bios, int len);
+
 #endif /* XENCTRL_H */
diff -r 5d7e7a250267 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/libxc/xenguest.h	Thu Aug 27 16:54:24 2009 +0800
@@ -135,7 +135,8 @@ int xc_hvm_build_target_mem(int xc_handl
                             uint32_t domid,
                             int memsize,
                             int target,
-                            const char *image_name);
+                            const char *image_name,
+                            int gfx_passthru);
 
 int xc_hvm_build_mem(int xc_handle,
                      uint32_t domid,
diff -r 5d7e7a250267 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/python/xen/lowlevel/xc/xc.c	Thu Aug 27 16:54:24 2009 +0800
@@ -894,21 +894,21 @@ static PyObject *pyxc_hvm_build(XcObject
     int i;
 #endif
     char *image;
-    int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1;
+    int memsize, target=-1, vcpus = 1, acpi = 0, apic = 1, gfx_passthru = 0;
 
     static char *kwd_list[] = { "domid",
                                 "memsize", "image", "target", "vcpus", "acpi",
-                                "apic", NULL };
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiii", kwd_list,
+                                "apic", "gfx_passthru", NULL };
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|iiiii", kwd_list,
                                       &dom, &memsize, &image, &target, &vcpus,
-                                      &acpi, &apic) )
+                                      &acpi, &apic, &gfx_passthru) )
         return NULL;
 
     if ( target == -1 )
         target = memsize;
 
     if ( xc_hvm_build_target_mem(self->xc_handle, dom, memsize,
-                                 target, image) != 0 )
+                                 target, image, gfx_passthru) != 0 )
         return pyxc_error_to_exception();
 
 #if !defined(__ia64__)
diff -r 5d7e7a250267 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/python/xen/xend/XendConfig.py	Thu Aug 27 16:54:24 2009 +0800
@@ -175,6 +175,7 @@ XENAPI_PLATFORM_CFG_TYPES = {
     'pci_msitranslate': int,
     'pci_power_mgmt': int,
     'xen_platform_pci': int,
+    "gfx_passthru": int,
 }
 
 # Xen API console 'other_config' keys.
diff -r 5d7e7a250267 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/python/xen/xend/image.py	Thu Aug 27 16:54:24 2009 +0800
@@ -786,7 +786,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.gfx_passthru = int(vmConfig['platform'].get('gfx_passthru', 0))
 
     # Return a list of cmd line args to the device models based on the
     # xm config file
@@ -807,7 +807,7 @@ class HVMImageHandler(ImageHandler):
 
         dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
                    'localtime', 'serial', 'stdvga', 'isa',
-                   'acpi', 'usb', 'usbdevice' ]
+                   'acpi', 'usb', 'usbdevice', 'gfx_passthru' ]
 
         for a in dmargs:
             v = vmConfig['platform'].get(a)
@@ -901,6 +901,7 @@ class HVMImageHandler(ImageHandler):
         log.debug("vcpus          = %d", self.vm.getVCpuCount())
         log.debug("acpi           = %d", self.acpi)
         log.debug("apic           = %d", self.apic)
+        log.debug("gfx_passthru   = %d", self.gfx_passthru)
 
         rc = xc.hvm_build(domid          = self.vm.getDomid(),
                           image          = self.loader,
@@ -908,7 +909,8 @@ class HVMImageHandler(ImageHandler):
                           target         = mem_mb,
                           vcpus          = self.vm.getVCpuCount(),
                           acpi           = self.acpi,
-                          apic           = self.apic)
+                          apic           = self.apic,
+                          gfx_passthru   = self.gfx_passthru)
         rc['notes'] = { 'SUSPEND_CANCEL': 1 }
 
         rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
diff -r 5d7e7a250267 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py	Wed Aug 26 18:28:44 2009 +0800
+++ b/tools/python/xen/xm/create.py	Thu Aug 27 16:54:24 2009 +0800
@@ -546,6 +546,10 @@ gopts.var('sdl', val='',
 gopts.var('sdl', val='',
           fn=set_value, default=None,
           use="""Should the device model use SDL?""")
+
+gopts.var('gfx_passthru', val='',
+          fn=set_value, default=None,
+          use="""Passthrough graphics card?""")
 
 gopts.var('opengl', val='',
           fn=set_value, default=None,
@@ -957,7 +961,8 @@ def configure_hvm(config_image, vals):
              'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
              'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check',
              'viridian', 'xen_extended_power_mgmt', 'pci_msitranslate',
-             'vpt_align', 'pci_power_mgmt', 'xen_platform_pci' ]
+             'vpt_align', 'pci_power_mgmt', 'xen_platform_pci',
+             'gfx_passthru' ]
 
     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

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2009-09-20 16:49 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-28  7:54 [PATCH 1/2] graphics passthrough with VT-d Han, Weidong
2009-08-28  8:12 ` Jean Guyader
2009-08-28  8:30   ` Han, Weidong
2009-09-11 15:41   ` Stefano Stabellini
2009-09-16  5:10     ` Han, Weidong
2009-09-16  8:33       ` Jean Guyader
2009-09-16  8:54         ` Han, Weidong
2009-09-16 10:57           ` Stefano Stabellini
2009-09-17 11:11             ` Han, Weidong
2009-09-18  7:42             ` Han, Weidong
2009-09-19  1:15               ` Stefano Stabellini
2009-09-20 12:59                 ` Han, Weidong
2009-09-20 16:49                   ` Stefano Stabellini
2009-08-28  8:45 ` Keir Fraser
2009-08-28  8:46   ` Han, Weidong

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.