Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Geert Uytterhoeven and committed by
Russell King (Oracle)
48342ae7 1c183875

+42 -6
+42 -6
arch/arm/boot/compressed/fdt_check_mem_start.c
··· 55 55 * DTB, and, if out-of-range, replace it by the real start address. 56 56 * To preserve backwards compatibility (systems reserving a block of memory 57 57 * at the start of physical memory, kdump, ...), the traditional method is 58 - * always used if it yields a valid address. 58 + * used if it yields a valid address, unless the "linux,usable-memory-range" 59 + * property is present. 59 60 * 60 61 * Return value: start address of physical memory to use 61 62 */ 62 63 uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt) 63 64 { 64 - uint32_t addr_cells, size_cells, base; 65 + uint32_t addr_cells, size_cells, usable_base, base; 65 66 uint32_t fdt_mem_start = 0xffffffff; 66 - const fdt32_t *reg, *endp; 67 - uint64_t size, end; 67 + const fdt32_t *usable, *reg, *endp; 68 + uint64_t size, usable_end, end; 68 69 const char *type; 69 70 int offset, len; 70 71 ··· 80 79 size_cells = get_cells(fdt, "#size-cells"); 81 80 if (addr_cells > 2 || size_cells > 2) 82 81 return mem_start; 82 + 83 + /* 84 + * Usable memory in case of a crash dump kernel 85 + * This property describes a limitation: memory within this range is 86 + * only valid when also described through another mechanism 87 + */ 88 + usable = get_prop(fdt, "/chosen", "linux,usable-memory-range", 89 + (addr_cells + size_cells) * sizeof(fdt32_t)); 90 + if (usable) { 91 + size = get_val(usable + addr_cells, size_cells); 92 + if (!size) 93 + return mem_start; 94 + 95 + if (addr_cells > 1 && fdt32_ld(usable)) { 96 + /* Outside 32-bit address space */ 97 + return mem_start; 98 + } 99 + 100 + usable_base = fdt32_ld(usable + addr_cells - 1); 101 + usable_end = usable_base + size; 102 + } 83 103 84 104 /* Walk all memory nodes and regions */ 85 105 for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; ··· 129 107 130 108 base = fdt32_ld(reg + addr_cells - 1); 131 109 end = base + size; 132 - if (mem_start >= base && mem_start < end) { 110 + if (usable) { 111 + /* 112 + * Clip to usable range, which takes precedence 113 + * over mem_start 114 + */ 115 + if (base < usable_base) 116 + base = usable_base; 117 + 118 + if (end > usable_end) 119 + end = usable_end; 120 + 121 + if (end <= base) 122 + continue; 123 + } else if (mem_start >= base && mem_start < end) { 133 124 /* Calculated address is valid, use it */ 134 125 return mem_start; 135 126 } ··· 158 123 } 159 124 160 125 /* 161 - * The calculated address is not usable. 126 + * The calculated address is not usable, or was overridden by the 127 + * "linux,usable-memory-range" property. 162 128 * Use the lowest usable physical memory address from the DTB instead, 163 129 * and make sure this is a multiple of 2 MiB for phys/virt patching. 164 130 */