@@ -88,6 +88,9 @@ static int __init device_tree_get_meminfo(const void *fdt, int node,
for ( i = 0; i < banks && mem->nr_banks < NR_MEM_BANKS; i++ )
{
device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+ if ( mem == &bootinfo.reserved_mem &&
+ check_reserved_regions_overlap(start, size) )
+ return -EINVAL;
/* Some DT may describe empty bank, ignore them */
if ( !size )
continue;
@@ -482,7 +485,9 @@ static int __init process_shm_node(const void *fdt, int node,
return -EINVAL;
}
- if ( (end <= mem->bank[i].start) || (paddr >= bank_end) )
+ if ( check_reserved_regions_overlap(paddr, size) )
+ return -EINVAL;
+ else
{
if ( strcmp(shm_id, mem->bank[i].shm_id) != 0 )
continue;
@@ -493,12 +498,6 @@ static int __init process_shm_node(const void *fdt, int node,
return -EINVAL;
}
}
- else
- {
- printk("fdt: shared memory region overlap with an existing entry %#"PRIpaddr" - %#"PRIpaddr"\n",
- mem->bank[i].start, bank_end);
- return -EINVAL;
- }
}
}
@@ -143,6 +143,8 @@ void fw_unreserved_regions(paddr_t s, paddr_t e,
size_t boot_fdt_info(const void *fdt, paddr_t paddr);
const char *boot_fdt_cmdline(const void *fdt);
+bool check_reserved_regions_overlap(paddr_t region_start, paddr_t region_size);
+
struct bootmodule *add_boot_module(bootmodule_kind kind,
paddr_t start, paddr_t size, bool domU);
struct bootmodule *boot_module_find_by_kind(bootmodule_kind kind);
@@ -261,6 +261,36 @@ static void __init dt_unreserved_regions(paddr_t s, paddr_t e,
cb(s, e);
}
+/*
+ * TODO: '*_end' could be 0 if the bank/region is at the end of the physical
+ * address space. This is for now not handled as it requires more rework.
+ */
+static bool __init meminfo_overlap_check(struct meminfo *meminfo,
+ paddr_t region_start,
+ paddr_t region_size)
+{
+ paddr_t bank_start = INVALID_PADDR, bank_end = 0;
+ paddr_t region_end = region_start + region_size;
+ unsigned int i, bank_num = meminfo->nr_banks;
+
+ for ( i = 0; i < bank_num; i++ )
+ {
+ bank_start = meminfo->bank[i].start;
+ bank_end = bank_start + meminfo->bank[i].size;
+
+ if ( region_end <= bank_start || region_start >= bank_end )
+ continue;
+ else
+ {
+ printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
+ region_start, region_end, i, bank_start, bank_end);
+ return true;
+ }
+ }
+
+ return false;
+}
+
void __init fw_unreserved_regions(paddr_t s, paddr_t e,
void (*cb)(paddr_t, paddr_t),
unsigned int first)
@@ -271,7 +301,22 @@ void __init fw_unreserved_regions(paddr_t s, paddr_t e,
cb(s, e);
}
+/*
+ * Given an input physical address range, check if this range is overlapping
+ * with the existing reserved memory regions defined in bootinfo.
+ * Return true if the input physical address range is overlapping with any
+ * existing reserved memory regions, otherwise false.
+ */
+bool __init check_reserved_regions_overlap(paddr_t region_start,
+ paddr_t region_size)
+{
+ /* Check if input region is overlapping with bootinfo.reserved_mem banks */
+ if ( meminfo_overlap_check(&bootinfo.reserved_mem,
+ region_start, region_size) )
+ return true;
+ return false;
+}
struct bootmodule __init *add_boot_module(bootmodule_kind kind,
paddr_t start, paddr_t size,