123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- From 48342ae751c797ac73ac9c894b3f312df18ffd21 Mon Sep 17 00:00:00 2001
- From: Geert Uytterhoeven <[email protected]>
- 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 <[email protected]>
- Signed-off-by: Russell King (Oracle) <[email protected]>
- Signed-off-by: Daniel Danzberger <[email protected]>
- ---
- .../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
- @@ -55,16 +55,17 @@ static uint64_t get_val(const fdt32_t *c
- * 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;
- uint32_t fdt_mem_start = 0xffffffff;
- - const fdt32_t *reg, *endp;
- - uint64_t size, end;
- + const fdt32_t *usable, *reg, *endp;
- + uint64_t size, usable_end, end;
- 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;
-
- + /*
- + * 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;
- + }
- +
- /* 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;
- - 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) {
- /* Calculated address is valid, use it */
- return mem_start;
- }
- @@ -123,7 +158,8 @@ uint32_t fdt_check_mem_start(uint32_t me
- }
-
- /*
- - * The calculated address is not usable.
- + * The calculated address is not usable, or was overridden by the
- + * "linux,usable-memory-range" property.
- * 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.
- */
|