if ( mem->nr_banks >= mem->max_banks )
return false;
#ifdef CONFIG_ACPI
- if ( check_reserved_regions_overlap(start, size) )
+ if ( check_reserved_regions_overlap(start, size, false) )
return false;
#endif
bank = &mem->bank[mem->nr_banks];
bank->start = start;
bank->size = size;
+ bank->type = MEMBANK_DEFAULT;
mem->nr_banks++;
if (i < mem->max_banks)
{
if ( (paddr != INVALID_PADDR) &&
- check_reserved_regions_overlap(paddr, size) )
+ check_reserved_regions_overlap(paddr, size, false) )
return -EINVAL;
/* Static shared memory shall be reserved from any other use. */
for ( i = 0; i < banks && mem->nr_banks < mem->max_banks; i++ )
{
device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
+ /*
+ * Some valid device trees, such as those generated by OpenPOWER
+ * skiboot firmware, expose all reserved memory regions in the
+ * FDT memory reservation block AND in the reserved-memory node which
+ * has already been parsed. Thus, any matching overlaps in the
+ * reserved_mem banks should be ignored.
+ */
if ( mem == bootinfo_get_reserved_mem() &&
- check_reserved_regions_overlap(start, size) )
+ check_reserved_regions_overlap(start, size, true) )
return -EINVAL;
/* Some DT may describe empty bank, ignore them */
if ( !size )
*/
static bool __init meminfo_overlap_check(const struct membanks *mem,
paddr_t region_start,
- paddr_t region_size)
+ paddr_t region_size,
+ bool allow_memreserve_overlap)
{
paddr_t bank_start = INVALID_PADDR, bank_end = 0;
paddr_t region_end = region_start + region_size;
if ( INVALID_PADDR == bank_start || 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;
- }
+
+ /*
+ * If allow_memreserve_overlap is set, this check allows a region to be
+ * included in a MEMBANK_FDT_RESVMEM bank, but struct membanks *mem of
+ * type STATIC_SHARED_MEMORY don't set the bank[].type field because
+ * that is declared in a union with a field that is instead used,
+ * in any case this restriction is ok since STATIC_SHARED_MEMORY banks
+ * are not meant to clash with FDT /memreserve/ ranges.
+ */
+ if ( allow_memreserve_overlap && mem->type != STATIC_SHARED_MEMORY &&
+ region_start >= bank_start && region_end <= bank_end &&
+ mem->bank[i].type == MEMBANK_FDT_RESVMEM )
+ continue;
+
+ printk("Region: [%#"PRIpaddr", %#"PRIpaddr") overlapping with bank[%u]: [%#"PRIpaddr", %#"PRIpaddr")\n",
+ region_start, region_end, i, bank_start, bank_end);
+ return true;
}
return false;
* existing reserved memory regions, otherwise false.
*/
bool __init check_reserved_regions_overlap(paddr_t region_start,
- paddr_t region_size)
+ paddr_t region_size,
+ bool allow_memreserve_overlap)
{
const struct membanks *mem_banks[] = {
bootinfo_get_reserved_mem(),
* shared memory banks (when static shared memory feature is enabled)
*/
for ( i = 0; i < ARRAY_SIZE(mem_banks); i++ )
- if ( meminfo_overlap_check(mem_banks[i], region_start, region_size) )
+ if ( meminfo_overlap_check(mem_banks[i], region_start, region_size,
+ allow_memreserve_overlap) )
return true;
/* Check if input region is overlapping with bootmodules */
return NULL;
}
- if ( check_reserved_regions_overlap(start, size) )
+ /*
+ * u-boot adds boot module such as ramdisk to the /memreserve/, since these
+ * ranges are saved in reserved_mem at this stage, allow an eventual exact
+ * match with MEMBANK_FDT_RESVMEM banks.
+ */
+ if ( check_reserved_regions_overlap(start, size, true) )
return NULL;
for ( i = 0 ; i < mods->nr_mods ; i++ )
MEMBANK_FDT_RESVMEM,
};
+enum region_type {
+ MEMORY,
+ RESERVED_MEMORY,
+ STATIC_SHARED_MEMORY
+};
+
/* Indicates the maximum number of characters(\0 included) for shm_id */
#define MAX_SHM_ID_LENGTH 16
__struct_group(membanks_hdr, common, ,
unsigned int nr_banks;
unsigned int max_banks;
+ enum region_type type;
);
struct membank bank[];
};
};
#ifdef CONFIG_ACPI
-#define BOOTINFO_ACPI_INIT .acpi.common.max_banks = NR_MEM_BANKS,
+#define BOOTINFO_ACPI_INIT \
+ .acpi.common.max_banks = NR_MEM_BANKS, \
+ .acpi.common.type = MEMORY
#else
#define BOOTINFO_ACPI_INIT
#endif
#ifdef CONFIG_STATIC_SHM
-#define BOOTINFO_SHMEM_INIT .shmem.common.max_banks = NR_SHMEM_BANKS,
+#define BOOTINFO_SHMEM_INIT \
+ .shmem.common.max_banks = NR_SHMEM_BANKS, \
+ .shmem.common.type = STATIC_SHARED_MEMORY
#else
#define BOOTINFO_SHMEM_INIT
#endif
#define BOOTINFO_INIT \
{ \
.mem.common.max_banks = NR_MEM_BANKS, \
+ .mem.common.type = MEMORY, \
.reserved_mem.common.max_banks = NR_MEM_BANKS, \
+ .reserved_mem.common.type = RESERVED_MEMORY, \
BOOTINFO_ACPI_INIT \
BOOTINFO_SHMEM_INIT \
}
extern struct bootinfo bootinfo;
bool check_reserved_regions_overlap(paddr_t region_start,
- paddr_t region_size);
+ paddr_t region_size,
+ bool allow_memreserve_overlap);
struct bootmodule *add_boot_module(bootmodule_kind kind,
paddr_t start, paddr_t size, bool domU);