[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hvmloader: Add 64 bits big bar support
# HG changeset patch # User Xiantao Zhang <xiantao.zhang@xxxxxxxxx> # Date 1349118115 -3600 # Node ID ef898f37a560d56e1559e2acb12b49baeb3f25b8 # Parent f242352da553a025920ff72eff54b9d6bc717eaa hvmloader: Add 64 bits big bar support Currently it is assumed PCI device BAR access < 4G memory. If there is such a device whose BAR size is larger than 4G, it must access > 4G memory address. This patch enable the 64bits big BAR support on hvmloader. Signed-off-by: Xiantao Zhang <xiantao.zhang@xxxxxxxxx> Signed-off-by: Xudong Hao <xudong.hao@xxxxxxxxx> Committed-by: Keir Fraser <keir@xxxxxxx> --- diff -r f242352da553 -r ef898f37a560 tools/firmware/hvmloader/cacheattr.c --- a/tools/firmware/hvmloader/cacheattr.c Mon Oct 01 17:54:11 2012 +0100 +++ b/tools/firmware/hvmloader/cacheattr.c Mon Oct 01 20:01:55 2012 +0100 @@ -40,17 +40,10 @@ #define MSR_PAT 0x0277 #define MSR_MTRRdefType 0x02ff -void cacheattr_init(void) +unsigned int cpu_phys_addr(void) { uint32_t eax, ebx, ecx, edx; - uint64_t mtrr_cap, mtrr_def, content, addr_mask; - unsigned int i, nr_var_ranges, phys_bits = 36; - - /* Does the CPU support architectural MTRRs? */ - cpuid(0x00000001, &eax, &ebx, &ecx, &edx); - if ( !(edx & (1u << 12)) ) - return; - + unsigned int phys_bits = 36; /* Find the physical address size for this CPU. */ cpuid(0x80000000, &eax, &ebx, &ecx, &edx); if ( eax >= 0x80000008 ) @@ -59,6 +52,22 @@ void cacheattr_init(void) phys_bits = (uint8_t)eax; } + return phys_bits; +} + +void cacheattr_init(void) +{ + uint32_t eax, ebx, ecx, edx; + uint64_t mtrr_cap, mtrr_def, content, addr_mask; + unsigned int i, nr_var_ranges, phys_bits; + + /* Does the CPU support architectural MTRRs? */ + cpuid(0x00000001, &eax, &ebx, &ecx, &edx); + if ( !(edx & (1u << 12)) ) + return; + + phys_bits = cpu_phys_addr(); + printf("%u-bit phys ... ", phys_bits); addr_mask = ((1ull << phys_bits) - 1) & ~((1ull << 12) - 1); diff -r f242352da553 -r ef898f37a560 tools/firmware/hvmloader/config.h --- a/tools/firmware/hvmloader/config.h Mon Oct 01 17:54:11 2012 +0100 +++ b/tools/firmware/hvmloader/config.h Mon Oct 01 20:01:55 2012 +0100 @@ -53,6 +53,8 @@ extern struct bios_config ovmf_config; /* MMIO hole: Hardcoded defaults, which can be dynamically expanded. */ #define PCI_MEM_START 0xf0000000 #define PCI_MEM_END 0xfc000000 +#define PCI_MIN_BIG_BAR_SIZE 0x20000000 + extern unsigned long pci_mem_start, pci_mem_end; diff -r f242352da553 -r ef898f37a560 tools/firmware/hvmloader/pci.c --- a/tools/firmware/hvmloader/pci.c Mon Oct 01 17:54:11 2012 +0100 +++ b/tools/firmware/hvmloader/pci.c Mon Oct 01 20:01:55 2012 +0100 @@ -36,19 +36,25 @@ unsigned long igd_opregion_pgbase = 0; void pci_setup(void) { - uint32_t base, devfn, bar_reg, bar_data, bar_sz, cmd, mmio_total = 0; + uint8_t is_64bar, using_64bar, bar64_relocate = 0; + uint32_t devfn, bar_reg, cmd, bar_data, bar_data_upper; + uint64_t base, bar_sz, bar_sz_upper, mmio_total = 0; uint32_t vga_devfn = 256; uint16_t class, vendor_id, device_id; unsigned int bar, pin, link, isa_irq; + int64_t mmio_left; /* Resources assignable to PCI devices via BARs. */ struct resource { - uint32_t base, max; - } *resource, mem_resource, io_resource; + uint64_t base, max; + } *resource, mem_resource, high_mem_resource, io_resource; /* Create a list of device BARs in descending order of size. */ struct bars { - uint32_t devfn, bar_reg, bar_sz; + uint32_t is_64bar; + uint32_t devfn; + uint32_t bar_reg; + uint64_t bar_sz; } *bars = (struct bars *)scratch_start; unsigned int i, nr_bars = 0; @@ -133,22 +139,34 @@ void pci_setup(void) /* Map the I/O memory and port resources. */ for ( bar = 0; bar < 7; bar++ ) { + bar_sz_upper = 0; bar_reg = PCI_BASE_ADDRESS_0 + 4*bar; if ( bar == 6 ) bar_reg = PCI_ROM_ADDRESS; bar_data = pci_readl(devfn, bar_reg); + is_64bar = !!((bar_data & (PCI_BASE_ADDRESS_SPACE | + PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == + (PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64)); pci_writel(devfn, bar_reg, ~0); bar_sz = pci_readl(devfn, bar_reg); pci_writel(devfn, bar_reg, bar_data); - if ( bar_sz == 0 ) - continue; bar_sz &= (((bar_data & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) ? PCI_BASE_ADDRESS_MEM_MASK : (PCI_BASE_ADDRESS_IO_MASK & 0xffff)); + if (is_64bar) { + bar_data_upper = pci_readl(devfn, bar_reg + 4); + pci_writel(devfn, bar_reg + 4, ~0); + bar_sz_upper = pci_readl(devfn, bar_reg + 4); + pci_writel(devfn, bar_reg + 4, bar_data_upper); + bar_sz = (bar_sz_upper << 32) | bar_sz; + } bar_sz &= ~(bar_sz - 1); + if ( bar_sz == 0 ) + continue; for ( i = 0; i < nr_bars; i++ ) if ( bars[i].bar_sz < bar_sz ) @@ -157,6 +175,7 @@ void pci_setup(void) if ( i != nr_bars ) memmove(&bars[i+1], &bars[i], (nr_bars-i) * sizeof(*bars)); + bars[i].is_64bar = is_64bar; bars[i].devfn = devfn; bars[i].bar_reg = bar_reg; bars[i].bar_sz = bar_sz; @@ -167,11 +186,8 @@ void pci_setup(void) nr_bars++; - /* Skip the upper-half of the address for a 64-bit BAR. */ - if ( (bar_data & (PCI_BASE_ADDRESS_SPACE | - PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == - (PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_TYPE_64) ) + /*The upper half is already calculated, skip it! */ + if (is_64bar) bar++; } @@ -197,6 +213,9 @@ void pci_setup(void) ((pci_mem_start << 1) != 0) ) pci_mem_start <<= 1; + if ( (pci_mem_start << 1) != 0 ) + bar64_relocate = 1; + /* Relocate RAM that overlaps PCI space (in 64k-page chunks). */ while ( (pci_mem_start >> PAGE_SHIFT) < hvm_info->low_mem_pgend ) { @@ -218,11 +237,15 @@ void pci_setup(void) hvm_info->high_mem_pgend += nr_pages; } + high_mem_resource.base = ((uint64_t)hvm_info->high_mem_pgend) << PAGE_SHIFT; + high_mem_resource.max = 1ull << cpu_phys_addr(); mem_resource.base = pci_mem_start; mem_resource.max = pci_mem_end; io_resource.base = 0xc000; io_resource.max = 0x10000; + mmio_left = pci_mem_end - pci_mem_start; + /* Assign iomem and ioport resources in descending order of size. */ for ( i = 0; i < nr_bars; i++ ) { @@ -230,13 +253,29 @@ void pci_setup(void) bar_reg = bars[i].bar_reg; bar_sz = bars[i].bar_sz; + using_64bar = bars[i].is_64bar && bar64_relocate && (mmio_left < bar_sz); bar_data = pci_readl(devfn, bar_reg); if ( (bar_data & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ) { - resource = &mem_resource; - bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK; + /* Mapping high memory if PCI deivce is 64 bits bar and the bar size + is larger than 512M */ + if (using_64bar && (bar_sz > PCI_MIN_BIG_BAR_SIZE)) { + 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)); + resource = &high_mem_resource; + bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK; + } + else { + resource = &mem_resource; + bar_data &= ~PCI_BASE_ADDRESS_MEM_MASK; + } + mmio_left -= bar_sz; } else { @@ -244,13 +283,14 @@ void pci_setup(void) bar_data &= ~PCI_BASE_ADDRESS_IO_MASK; } - base = (resource->base + bar_sz - 1) & ~(bar_sz - 1); - bar_data |= base; + base = (resource->base + bar_sz - 1) & ~(uint64_t)(bar_sz - 1); + bar_data |= (uint32_t)base; + bar_data_upper = (uint32_t)(base >> 32); base += bar_sz; if ( (base < resource->base) || (base > resource->max) ) { - printf("pci dev %02x:%x bar %02x size %08x: no space for " + printf("pci dev %02x:%x bar %02x size %llx: no space for " "resource!\n", devfn>>3, devfn&7, bar_reg, bar_sz); continue; } @@ -258,8 +298,11 @@ void pci_setup(void) resource->base = base; pci_writel(devfn, bar_reg, bar_data); - printf("pci dev %02x:%x bar %02x size %08x: %08x\n", + if (using_64bar) + pci_writel(devfn, bar_reg + 4, bar_data_upper); + printf("pci dev %02x:%x bar %02x size %llx: %08x\n", devfn>>3, devfn&7, bar_reg, bar_sz, bar_data); + /* Now enable the memory or I/O mapping. */ cmd = pci_readw(devfn, PCI_COMMAND); diff -r f242352da553 -r ef898f37a560 tools/firmware/hvmloader/util.h --- a/tools/firmware/hvmloader/util.h Mon Oct 01 17:54:11 2012 +0100 +++ b/tools/firmware/hvmloader/util.h Mon Oct 01 20:01:55 2012 +0100 @@ -215,6 +215,7 @@ void pci_setup(void); uint32_t rombios_highbios_setup(void); /* Miscellaneous. */ +unsigned int cpu_phys_addr(void); void cacheattr_init(void); unsigned long create_mp_tables(void *table); void hvm_write_smbios_tables( _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |