2022-08-03 15:31:03 +00:00
|
|
|
From 48342ae751c797ac73ac9c894b3f312df18ffd21 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Geert Uytterhoeven <geert+renesas@glider.be>
|
|
|
|
Date: Wed, 15 Sep 2021 13:46:20 +0100
|
|
|
|
Subject: [PATCH] ARM: 9124/1: uncompress: Parse "linux,usable-memory-range" DT
|
|
|
|
property
|
|
|
|
|
|
|
|
Add support for parsing the "linux,usable-memory-range" DT property.
|
|
|
|
This property is used to describe the usable memory reserved for the
|
|
|
|
crash dump kernel, and thus makes the memory reservation explicit.
|
|
|
|
If present, Linux no longer needs to mask the program counter, and rely
|
|
|
|
on the "mem=" kernel parameter to obtain the start and size of usable
|
|
|
|
memory.
|
|
|
|
|
|
|
|
For backwards compatibility, the traditional method to derive the start
|
|
|
|
of memory is still used if "linux,usable-memory-range" is absent.
|
|
|
|
|
|
|
|
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
|
|
|
|
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
|
|
|
Signed-off-by: Daniel Danzberger <daniel@dd-wrt.com>
|
|
|
|
---
|
|
|
|
.../arm/boot/compressed/fdt_check_mem_start.c | 48 ++++++++++++++++---
|
|
|
|
1 file changed, 42 insertions(+), 6 deletions(-)
|
|
|
|
|
|
|
|
--- a/arch/arm/boot/compressed/fdt_check_mem_start.c
|
|
|
|
+++ b/arch/arm/boot/compressed/fdt_check_mem_start.c
|
2022-09-15 12:07:08 +00:00
|
|
|
@@ -55,16 +55,17 @@ static uint64_t get_val(const fdt32_t *c
|
2022-08-03 15:31:03 +00:00
|
|
|
* DTB, and, if out-of-range, replace it by the real start address.
|
|
|
|
* To preserve backwards compatibility (systems reserving a block of memory
|
|
|
|
* at the start of physical memory, kdump, ...), the traditional method is
|
|
|
|
- * always used if it yields a valid address.
|
|
|
|
+ * used if it yields a valid address, unless the "linux,usable-memory-range"
|
|
|
|
+ * property is present.
|
|
|
|
*
|
|
|
|
* Return value: start address of physical memory to use
|
|
|
|
*/
|
|
|
|
uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
|
|
|
|
{
|
|
|
|
- uint32_t addr_cells, size_cells, base;
|
|
|
|
+ uint32_t addr_cells, size_cells, usable_base, base;
|
2022-09-15 12:07:08 +00:00
|
|
|
uint32_t fdt_mem_start = 0xffffffff;
|
2022-08-03 15:31:03 +00:00
|
|
|
- const fdt32_t *reg, *endp;
|
|
|
|
- uint64_t size, end;
|
|
|
|
+ const fdt32_t *usable, *reg, *endp;
|
|
|
|
+ uint64_t size, usable_end, end;
|
2022-09-15 12:07:08 +00:00
|
|
|
const char *type;
|
|
|
|
int offset, len;
|
|
|
|
|
|
|
|
@@ -80,6 +81,27 @@ uint32_t fdt_check_mem_start(uint32_t me
|
|
|
|
if (addr_cells > 2 || size_cells > 2)
|
|
|
|
return mem_start;
|
|
|
|
|
2022-08-03 15:31:03 +00:00
|
|
|
+ /*
|
|
|
|
+ * Usable memory in case of a crash dump kernel
|
|
|
|
+ * This property describes a limitation: memory within this range is
|
|
|
|
+ * only valid when also described through another mechanism
|
|
|
|
+ */
|
|
|
|
+ usable = get_prop(fdt, "/chosen", "linux,usable-memory-range",
|
|
|
|
+ (addr_cells + size_cells) * sizeof(fdt32_t));
|
|
|
|
+ if (usable) {
|
|
|
|
+ size = get_val(usable + addr_cells, size_cells);
|
|
|
|
+ if (!size)
|
|
|
|
+ return mem_start;
|
|
|
|
+
|
|
|
|
+ if (addr_cells > 1 && fdt32_ld(usable)) {
|
|
|
|
+ /* Outside 32-bit address space */
|
|
|
|
+ return mem_start;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ usable_base = fdt32_ld(usable + addr_cells - 1);
|
|
|
|
+ usable_end = usable_base + size;
|
|
|
|
+ }
|
|
|
|
+
|
2022-09-15 12:07:08 +00:00
|
|
|
/* Walk all memory nodes and regions */
|
|
|
|
for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0;
|
|
|
|
offset = fdt_next_node(fdt, offset, NULL)) {
|
|
|
|
@@ -107,7 +129,20 @@ uint32_t fdt_check_mem_start(uint32_t me
|
|
|
|
|
|
|
|
base = fdt32_ld(reg + addr_cells - 1);
|
|
|
|
end = base + size;
|
2022-08-03 15:31:03 +00:00
|
|
|
- if (mem_start >= base && mem_start < end) {
|
|
|
|
+ if (usable) {
|
|
|
|
+ /*
|
|
|
|
+ * Clip to usable range, which takes precedence
|
|
|
|
+ * over mem_start
|
|
|
|
+ */
|
|
|
|
+ if (base < usable_base)
|
|
|
|
+ base = usable_base;
|
|
|
|
+
|
|
|
|
+ if (end > usable_end)
|
|
|
|
+ end = usable_end;
|
|
|
|
+
|
|
|
|
+ if (end <= base)
|
|
|
|
+ continue;
|
|
|
|
+ } else if (mem_start >= base && mem_start < end) {
|
2022-09-15 12:07:08 +00:00
|
|
|
/* Calculated address is valid, use it */
|
|
|
|
return mem_start;
|
|
|
|
}
|
|
|
|
@@ -123,7 +158,8 @@ uint32_t fdt_check_mem_start(uint32_t me
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2022-08-03 15:31:03 +00:00
|
|
|
- * The calculated address is not usable.
|
|
|
|
+ * The calculated address is not usable, or was overridden by the
|
|
|
|
+ * "linux,usable-memory-range" property.
|
2022-09-15 12:07:08 +00:00
|
|
|
* Use the lowest usable physical memory address from the DTB instead,
|
|
|
|
* and make sure this is a multiple of 2 MiB for phys/virt patching.
|
|
|
|
*/
|