]> xenbits.xensource.com Git - xen.git/commitdiff
hvmloader: Intel GPU passthrough, reverse OpRegion
authorJean Guyader <jean.guyader@eu.citrix.com>
Thu, 24 Nov 2011 15:43:59 +0000 (15:43 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Thu, 24 Nov 2011 15:43:59 +0000 (15:43 +0000)
The Intel GPU uses a two pages NVS region called OpRegion.
In order to get full support for the driver in the guest
we need to map this region.

This patch reserves 2 pages on the top of the memory in the
reserved area and mark this region as NVS in the e820. Then
we write the address to the config space (offset 0xfc) so the
device model can map the OpRegion at this address in the guest.

Signed-off-by: Jean Guyader <jean.guyader@eu.citrix.com>
Committed-by: Keir Fraser <keir@xen.org>
tools/firmware/hvmloader/config.h
tools/firmware/hvmloader/e820.c
tools/firmware/hvmloader/pci.c
tools/firmware/hvmloader/pci_regs.h

index d911352e82a10ac8f597e68a341818eb07098798..9cac9c10008495fc291614d30cdd1d2fb82f55f5 100644 (file)
@@ -5,6 +5,7 @@
 
 enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };
 extern enum virtual_vga virtual_vga;
+extern unsigned long igd_opregion_pgbase;
 
 struct bios_config {
     const char *name;
index 3b50dd015d9c46d2b03be1312c1a1916affa46fb..0fc0b1c30613ceb99a7a5c1baa8525a509d03158 100644 (file)
@@ -128,11 +128,37 @@ int build_e820_table(struct e820entry *e820,
      * Explicitly reserve space for special pages.
      * This space starts at RESERVED_MEMBASE an extends to cover various
      * fixed hardware mappings (e.g., LAPIC, IOAPIC, default SVGA framebuffer).
+     *
+     * If igd_opregion_pgbase we need to split the RESERVED region in two.
      */
-    e820[nr].addr = RESERVED_MEMBASE;
-    e820[nr].size = (uint32_t)-e820[nr].addr;
-    e820[nr].type = E820_RESERVED;
-    nr++;
+
+    if ( igd_opregion_pgbase )
+    {
+        uint32_t igd_opregion_base = igd_opregion_pgbase << PAGE_SHIFT;
+
+        e820[nr].addr = RESERVED_MEMBASE;
+        e820[nr].size = (uint32_t) igd_opregion_base - RESERVED_MEMBASE;
+        e820[nr].type = E820_RESERVED;
+        nr++;
+
+        e820[nr].addr = igd_opregion_base;
+        e820[nr].size = 2 * PAGE_SIZE;
+        e820[nr].type = E820_NVS;
+        nr++;
+
+        e820[nr].addr = igd_opregion_base + 2 * PAGE_SIZE;
+        e820[nr].size = (uint32_t)-e820[nr].addr;
+        e820[nr].type = E820_RESERVED;
+        nr++;
+    }
+    else
+    {
+        e820[nr].addr = RESERVED_MEMBASE;
+        e820[nr].size = (uint32_t)-e820[nr].addr;
+        e820[nr].type = E820_RESERVED;
+        nr++;
+    }
+
 
     if ( hvm_info->high_mem_pgend )
     {
index 00490f184e7ff3767bb62bcfc4281f83fa60e321..fd56e5087424f8fb3a7e09e339c8a15930b70ede 100644 (file)
@@ -32,6 +32,7 @@ unsigned long pci_mem_start = PCI_MEM_START;
 unsigned long pci_mem_end = PCI_MEM_END;
 
 enum virtual_vga virtual_vga = VGA_none;
+unsigned long igd_opregion_pgbase = 0;
 
 void pci_setup(void)
 {
@@ -95,6 +96,17 @@ void pci_setup(void)
             {
                 vga_devfn = devfn;
                 virtual_vga = VGA_pt;
+                if ( vendor_id == 0x8086 )
+                {
+                    igd_opregion_pgbase = mem_hole_alloc(2);
+                    /*
+                     * Write the the OpRegion offset to give the opregion
+                     * address to the device model. The device model will trap 
+                     * and map the OpRegion at the give address.
+                     */
+                    pci_writel(vga_devfn, PCI_INTEL_OPREGION,
+                               igd_opregion_pgbase << PAGE_SHIFT);
+                }
             }
             break;
         case 0x0680:
index f37affedd0ea238eb3e562ebd79cb53acd699dbd..0803f77a554ade3cf4e29cb70b55fd4b606c4d99 100644 (file)
 #define PCI_MIN_GNT  0x3e /* 8 bits */
 #define PCI_MAX_LAT  0x3f /* 8 bits */
 
+#define PCI_INTEL_OPREGION 0xfc /* 4 bits */
+
 #endif /* __HVMLOADER_PCI_REGS_H__ */
 
 /*