@@ -323,6 +323,26 @@ static int __init early_mem(char *p)
}
early_param("mem", early_mem);
+static int __init early_init_dt_scan_lowmem(unsigned long node,
+ const char *uname, int depth, void *data)
+{
+ struct memblock_region *lowmem = data;
+ const __be32 *reg;
+ int len;
+
+ if (depth != 1 || strcmp(uname, "chosen") != 0)
+ return 0;
+
+ reg = of_get_flat_dt_prop(node, "linux,low-memory-range", &len);
+ if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
+ return 1;
+
+ lowmem->base = dt_mem_next_cell(dt_root_addr_cells, ®);
+ lowmem->size = dt_mem_next_cell(dt_root_size_cells, ®);
+
+ return 1;
+}
+
static int __init early_init_dt_scan_usablemem(unsigned long node,
const char *uname, int depth, void *data)
{
@@ -353,13 +373,21 @@ static void __init fdt_enforce_memory_region(void)
if (reg.size)
memblock_cap_memory_range(reg.base, reg.size);
+
+ of_scan_flat_dt(early_init_dt_scan_lowmem, ®);
+
+ if (reg.size)
+ memblock_add(reg.base, reg.size);
}
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
- /* Handle linux,usable-memory-range property */
+ /*
+ * Handle linux,usable-memory-range and linux,low-memory-range
+ * properties.
+ */
fdt_enforce_memory_region();
/* Remove memory above our supported physical address size */