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

Reply via email to