--- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -53,6 +53,7 @@ struct acpi_info { uint32_t madt_csum_addr; /* 12 - Address of MADT checksum */ uint32_t madt_lapic0_addr; /* 16 - Address of first MADT LAPIC struct */ uint32_t vm_gid_addr; /* 20 - Address of VM generation id buffer */ + uint64_t pci_hi_min, pci_hi_len; /* 24, 32 - PCI I/O hole boundaries */ }; /* Number of processor objects in the chosen DSDT. */ @@ -541,6 +542,11 @@ void acpi_build_tables(struct acpi_confi acpi_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS); acpi_info->pci_min = pci_mem_start; acpi_info->pci_len = pci_mem_end - pci_mem_start; + if ( pci_hi_mem_end > pci_hi_mem_start ) + { + acpi_info->pci_hi_min = pci_hi_mem_start; + acpi_info->pci_hi_len = pci_hi_mem_end - pci_hi_mem_start; + } return; --- a/tools/firmware/hvmloader/acpi/dsdt.asl +++ b/tools/firmware/hvmloader/acpi/dsdt.asl @@ -45,7 +45,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, Scope (\_SB) { /* ACPI_INFO_PHYSICAL_ADDRESS == 0xFC000000 */ - OperationRegion(BIOS, SystemMemory, 0xFC000000, 24) + OperationRegion(BIOS, SystemMemory, 0xFC000000, 40) Field(BIOS, ByteAcc, NoLock, Preserve) { UAR1, 1, UAR2, 1, @@ -56,7 +56,9 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, PLEN, 32, MSUA, 32, /* MADT checksum address */ MAPA, 32, /* MADT LAPIC0 address */ - VGIA, 32 /* VM generation id address */ + VGIA, 32, /* VM generation id address */ + HMIN, 64, + HLEN, 64 } /* Fix HCT test for 0x400 pci memory: @@ -136,7 +138,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, /* reserve memory for pci devices */ DWordMemory( ResourceProducer, PosDecode, MinFixed, MaxFixed, - Cacheable, ReadWrite, + WriteCombining, ReadWrite, 0x00000000, 0x000A0000, 0x000BFFFF, @@ -145,13 +147,24 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, DWordMemory( ResourceProducer, PosDecode, MinFixed, MaxFixed, - Cacheable, ReadWrite, + NonCacheable, ReadWrite, 0x00000000, 0xF0000000, 0xF4FFFFFF, 0x00000000, 0x05000000, ,, _Y01) + + QWordMemory ( + ResourceProducer, PosDecode, MinFixed, MaxFixed, + NonCacheable, ReadWrite, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + ,, _Y02) + }) CreateDWordField(PRT0, \_SB.PCI0._CRS._Y01._MIN, MMIN) @@ -163,6 +176,15 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, Add(MMIN, MLEN, MMAX) Subtract(MMAX, One, MMAX) + CreateQWordField(PRT0, \_SB.PCI0._CRS._Y02._MIN, HMIN) + CreateQWordField(PRT0, \_SB.PCI0._CRS._Y02._MAX, HMAX) + CreateQWordField(PRT0, \_SB.PCI0._CRS._Y02._LEN, HLEN) + + Store(\_SB.HMIN, HMIN) + Store(\_SB.HLEN, HLEN) + Add(HMIN, HLEN, HMAX) + Subtract(HMAX, One, HMAX) + Return (PRT0) } --- a/tools/firmware/hvmloader/cacheattr.c +++ b/tools/firmware/hvmloader/cacheattr.c @@ -97,8 +97,7 @@ void cacheattr_init(void) nr_var_ranges = (uint8_t)mtrr_cap; if ( nr_var_ranges != 0 ) { - unsigned long base = pci_mem_start, size; - int i; + uint64_t base = pci_mem_start, size; for ( i = 0; (base != pci_mem_end) && (i < nr_var_ranges); i++ ) { @@ -109,8 +108,22 @@ void cacheattr_init(void) size >>= 1; wrmsr(MSR_MTRRphysBase(i), base); - wrmsr(MSR_MTRRphysMask(i), - (~(uint64_t)(size-1) & addr_mask) | (1u << 11)); + wrmsr(MSR_MTRRphysMask(i), (~(size - 1) & addr_mask) | (1u << 11)); + + base += size; + } + + for ( base = pci_hi_mem_start; + (base != pci_hi_mem_end) && (i < nr_var_ranges); i++ ) + { + size = PAGE_SIZE; + while ( !(base & size) ) + size <<= 1; + while ( (base + size < base) || (base + size > pci_hi_mem_end) ) + size >>= 1; + + wrmsr(MSR_MTRRphysBase(i), base); + wrmsr(MSR_MTRRphysMask(i), (~(size - 1) & addr_mask) | (1u << 11)); base += size; } --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -57,7 +57,7 @@ extern struct bios_config ovmf_config; #define PCI_MEM_END 0xfc000000 extern unsigned long pci_mem_start, pci_mem_end; - +extern uint64_t pci_hi_mem_start, pci_hi_mem_end; /* Memory map. */ #define SCRATCH_PHYSICAL_ADDRESS 0x00010000 --- 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; +uint64_t pci_hi_mem_start = 0, pci_hi_mem_end = 0; enum virtual_vga virtual_vga = VGA_none; unsigned long igd_opregion_pgbase = 0; @@ -345,9 +346,8 @@ void pci_setup(void) if ( high_mem_resource.base & (bar_sz - 1) ) high_mem_resource.base = high_mem_resource.base - (high_mem_resource.base & (bar_sz - 1)) + bar_sz; - else - high_mem_resource.base = high_mem_resource.base - - (high_mem_resource.base & (bar_sz - 1)); + if ( !pci_hi_mem_start ) + pci_hi_mem_start = high_mem_resource.base; resource = &high_mem_resource; bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK; } @@ -398,6 +398,16 @@ void pci_setup(void) pci_writew(devfn, PCI_COMMAND, cmd); } + if ( pci_hi_mem_start ) + { + /* + * Make end address alignment match the start address one's so that + * fewer variable range MTRRs are needed to cover the range. + */ + pci_hi_mem_end = ((high_mem_resource.base - 1) | + ((pci_hi_mem_start & -pci_hi_mem_start) - 1)) + 1; + } + if ( vga_devfn != 256 ) { /*