]> xenbits.xensource.com Git - qemu-xen-4.5-testing.git/commitdiff
passthrough: enabling IGD passthrough for Calpella and Sandybridge
authorIan Jackson <ian.jackson@eu.citrix.com>
Thu, 2 Sep 2010 18:08:58 +0000 (19:08 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Thu, 2 Sep 2010 18:08:58 +0000 (19:08 +0100)
This patch enables IGD passthrough for Calpella and Sandybridge
platforms.  To minimize impact of these changes, it checks for
vendor_id of 0x8086 before creating another PCH device in the virtual
platform.  For opregion, it checks both vendor_ID of 0x8086 and a
non-zero PCI opregion value on device 0:2.0 before mapping the
opregion.

Signed-off-by: Allen Kay <allen.m.kay@intel.com>
hw/pc.c
hw/pt-graphics.c

diff --git a/hw/pc.c b/hw/pc.c
index 4c9a1641c9092f4767e21dfe707534580deecfb9..7aa91f28e1cb2136c4a2958c09bc1a78bb3739f2 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -982,6 +982,10 @@ vga_bios_error:
         pci_bus = NULL;
     }
 
+#ifdef CONFIG_PASSTHROUGH
+    intel_pch_init(pci_bus);
+#endif
+
     /* init basic PC hardware */
     register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
 
index ce0c4a60f9438dc034e369b70051892d24ce94bc..5dfcca26383736d4612debecef580b92db52fc37 100644 (file)
@@ -31,8 +31,9 @@ void intel_pch_init(PCIBus *bus)
     did = pt_pci_host_read(0, 0x1f, 0, 2, 2);
     rid = pt_pci_host_read(0, 0x1f, 0, 8, 1);
 
-    pci_bridge_init(bus, PCI_DEVFN(0x1f, 0), vid, did, rid,
-                    pch_map_irq, "intel_bridge_1f");
+    if ( vid == 0x8086 ) 
+        pci_bridge_init(bus, PCI_DEVFN(0x1f, 0), vid, did, rid,
+                        pch_map_irq, "intel_bridge_1f");
 }
 
 void igd_pci_write(PCIDevice *pci_dev, int config_addr, uint32_t val, int len)
@@ -92,6 +93,7 @@ uint32_t igd_pci_read(PCIDevice *pci_dev, int config_addr, int len)
  */
 int register_vga_regions(struct pt_dev *real_device)
 {
+    u32 vendor_id, igd_opregion;
     int ret = 0;
 
     if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
@@ -109,6 +111,19 @@ int register_vga_regions(struct pt_dev *real_device)
             0x20,
             DPCI_ADD_MAPPING);
 
+    /* 1:1 map ASL Storage register value */
+    vendor_id = pt_pci_host_read(0, 2, 0, 0, 2);
+    igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4);
+    if ( (vendor_id == 0x8086) && igd_opregion )
+    {
+        ret |= xc_domain_memory_mapping(xc_handle, domid,
+                igd_opregion >> XC_PAGE_SHIFT,
+                igd_opregion >> XC_PAGE_SHIFT,
+                2,
+                DPCI_ADD_MAPPING);
+        PT_LOG("register_vga: igd_opregion = %x\n", igd_opregion);
+    }
+
     if ( ret != 0 )
         PT_LOG("VGA region mapping failed\n");
 
@@ -120,7 +135,7 @@ int register_vga_regions(struct pt_dev *real_device)
  */
 int unregister_vga_regions(struct pt_dev *real_device)
 {
-    u32 igd_opregion, igd_bsm;
+    u32 vendor_id, igd_opregion;
     int ret = 0;
 
     if ( !gfx_passthru || real_device->pci_dev->device_class != 0x0300 )
@@ -138,12 +153,16 @@ int unregister_vga_regions(struct pt_dev *real_device)
             20,
             DPCI_REMOVE_MAPPING);
 
+    vendor_id = pt_pci_host_read(0, 2, 0, 0, 2);
     igd_opregion = pt_pci_host_read(0, 2, 0, 0xfc, 4);
-    ret |= xc_domain_memory_mapping(xc_handle, domid,
-            igd_opregion >> XC_PAGE_SHIFT,
-            igd_opregion >> XC_PAGE_SHIFT,
-            2,
-            DPCI_REMOVE_MAPPING);
+    if ( (vendor_id == 0x8086) && igd_opregion )
+    {
+        ret |= xc_domain_memory_mapping(xc_handle, domid,
+                igd_opregion >> XC_PAGE_SHIFT,
+                igd_opregion >> XC_PAGE_SHIFT,
+                2,
+                DPCI_REMOVE_MAPPING);
+    }
 
     if ( ret != 0 )
         PT_LOG("VGA region unmapping failed\n");