diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h index d911352..9cac9c1 100644 --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -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; diff --git a/tools/firmware/hvmloader/e820.c b/tools/firmware/hvmloader/e820.c index 3b50dd0..0fc0b1c 100644 --- a/tools/firmware/hvmloader/e820.c +++ b/tools/firmware/hvmloader/e820.c @@ -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 ) { diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c index 00490f1..2534530 100644 --- a/tools/firmware/hvmloader/pci.c +++ b/tools/firmware/hvmloader/pci.c @@ -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,19 @@ 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: diff --git a/tools/firmware/hvmloader/pci_regs.h b/tools/firmware/hvmloader/pci_regs.h index f37affe..0803f77 100644 --- a/tools/firmware/hvmloader/pci_regs.h +++ b/tools/firmware/hvmloader/pci_regs.h @@ -105,6 +105,8 @@ #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__ */ /*