We need to make sure all mmio allocation don't overlap any rdm, reserved device memory. Here we just skip all reserved device memory range in mmio space.
Signed-off-by: Tiejun Chen <tiejun.c...@intel.com> --- tools/firmware/hvmloader/pci.c | 54 ++++++++++++++++++++++++++++++++++++++++- tools/firmware/hvmloader/util.c | 9 +++++++ tools/firmware/hvmloader/util.h | 2 ++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/tools/firmware/hvmloader/pci.c b/tools/firmware/hvmloader/pci.c index 4e8d803..fc22ab3 100644 --- a/tools/firmware/hvmloader/pci.c +++ b/tools/firmware/hvmloader/pci.c @@ -38,6 +38,30 @@ 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; +static unsigned int need_skip_rmrr; +extern struct xen_reserved_device_memory *rdm_map; + +static unsigned int +check_reserved_device_memory_map(uint64_t mmio_base, uint64_t mmio_max) +{ + uint32_t i; + uint64_t rdm_start, rdm_end; + unsigned int nr_rdm_entries = hvm_get_reserved_device_memory_map(); + + for ( i = 0; i < nr_rdm_entries; i++ ) + { + rdm_start = (uint64_t)rdm_map[i].start_pfn << PAGE_SHIFT; + rdm_end = rdm_start + ((uint64_t)rdm_map[i].nr_pages << PAGE_SHIFT); + if ( check_rdm_hole_conflict(mmio_base, mmio_max - mmio_base, + rdm_start, rdm_end - rdm_start) ) + { + need_skip_rmrr++; + } + } + + return nr_rdm_entries; +} + void pci_setup(void) { uint8_t is_64bar, using_64bar, bar64_relocate = 0; @@ -59,8 +83,10 @@ void pci_setup(void) uint32_t bar_reg; uint64_t bar_sz; } *bars = (struct bars *)scratch_start; - unsigned int i, nr_bars = 0; + unsigned int i, j, nr_bars = 0; uint64_t mmio_hole_size = 0; + unsigned int nr_rdm_entries; + uint64_t rdm_start, rdm_end; const char *s; /* @@ -338,6 +364,14 @@ void pci_setup(void) io_resource.base = 0xc000; io_resource.max = 0x10000; + /* Check low mmio range. */ + nr_rdm_entries = check_reserved_device_memory_map(mem_resource.base, + mem_resource.max); + /* Check high mmio range. */ + if ( nr_rdm_entries ) + nr_rdm_entries = check_reserved_device_memory_map(high_mem_resource.base, + high_mem_resource.max); + /* Assign iomem and ioport resources in descending order of size. */ for ( i = 0; i < nr_bars; i++ ) { @@ -393,8 +427,26 @@ void pci_setup(void) } base = (resource->base + bar_sz - 1) & ~(uint64_t)(bar_sz - 1); + reallocate_mmio: bar_data |= (uint32_t)base; bar_data_upper = (uint32_t)(base >> 32); + + if ( need_skip_rmrr ) + { + for ( j = 0; j < nr_rdm_entries; j++ ) + { + rdm_start = (uint64_t)rdm_map[j].start_pfn << PAGE_SHIFT; + rdm_end = rdm_start + ((uint64_t)rdm_map[j].nr_pages << PAGE_SHIFT); + if ( check_rdm_hole_conflict(base, bar_sz, + rdm_start, rdm_end - rdm_start) ) + { + base = (rdm_end + bar_sz - 1) & ~(uint64_t)(bar_sz - 1); + need_skip_rmrr--; + goto reallocate_mmio; + } + } + } + base += bar_sz; if ( (base < resource->base) || (base > resource->max) ) diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c index dd81fb6..8767897 100644 --- a/tools/firmware/hvmloader/util.c +++ b/tools/firmware/hvmloader/util.c @@ -887,6 +887,15 @@ unsigned int hvm_get_reserved_device_memory_map(void) return nr_entries; } +int check_rdm_hole_conflict(uint64_t start, uint64_t size, + uint64_t rdm_start, uint64_t rdm_size) +{ + if ( start + size <= rdm_start || start >= rdm_start + rdm_size ) + return 0; + else + return 1; +} + /* * Local variables: * mode: C diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index e4f1851..9b02f95 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -242,6 +242,8 @@ int build_e820_table(struct e820entry *e820, void dump_e820_table(struct e820entry *e820, unsigned int nr); unsigned int hvm_get_reserved_device_memory_map(void); +int check_rdm_hole_conflict(uint64_t start, uint64_t size, + uint64_t rdm_start, uint64_t rdm_size); #ifndef NDEBUG void perform_tests(void); -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel