linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property
@ 2021-09-15 12:46 Geert Uytterhoeven
  2021-09-22  7:14 ` Ard Biesheuvel
  2021-09-23  0:08 ` Linus Walleij
  0 siblings, 2 replies; 3+ messages in thread
From: Geert Uytterhoeven @ 2021-09-15 12:46 UTC (permalink / raw)
  To: Russell King, Nicolas Pitre, Ard Biesheuvel, Linus Walleij,
	Lukasz Stelmach
  Cc: Simon Horman, linux-arm-kernel, devicetree, linux-kernel, kexec,
	Geert Uytterhoeven

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>
---
KernelVersion: v5.15-rc1
---
The corresponding patch for kexec-tools is "[PATCH] arm: kdump: Add DT
properties to crash dump kernel's DTB", which is still valid:
https://lore.kernel.org/r/20200902154129.6358-1-geert+renesas@glider.be/

v6:
  - All dependencies are in v5.15-rc1,

v5:
  - Remove the addition of "linux,elfcorehdr" and
    "linux,usable-memory-range" handling to arch/arm/mm/init.c,

v4:
  - Remove references to architectures in chosen.txt, to avoid having to
    change this again when more architectures copy kdump support,
  - Remove the architecture-specific code for parsing
    "linux,usable-memory-range" and "linux,elfcorehdr", as the FDT core
    code now takes care of this,
  - Move chosen.txt change to patch changing the FDT core,
  - Use IS_ENABLED(CONFIG_CRASH_DUMP) instead of #ifdef,

v3:
  - Rebase on top of accepted solution for DTB memory information
    handling, which is part of v5.12-rc1,

v2:
  - Rebase on top of reworked DTB memory information handling.
---
 .../arm/boot/compressed/fdt_check_mem_start.c | 48 ++++++++++++++++---
 1 file changed, 42 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/compressed/fdt_check_mem_start.c b/arch/arm/boot/compressed/fdt_check_mem_start.c
index 62450d824c3ca180..9291a2661bdfe57f 100644
--- 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 *cells, uint32_t ncells)
  * 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 mem_start, const void *fdt)
 	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 mem_start, const void *fdt)
 
 			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 mem_start, const void *fdt)
 	}
 
 	/*
-	 * 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.
 	 */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property
  2021-09-15 12:46 [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property Geert Uytterhoeven
@ 2021-09-22  7:14 ` Ard Biesheuvel
  2021-09-23  0:08 ` Linus Walleij
  1 sibling, 0 replies; 3+ messages in thread
From: Ard Biesheuvel @ 2021-09-22  7:14 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Russell King, Nicolas Pitre, Linus Walleij, Lukasz Stelmach,
	Simon Horman, Linux ARM,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux Kernel Mailing List, kexec

On Wed, 15 Sept 2021 at 15:20, Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
>
> 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>

Acked-by: Ard Biesheuvel <ardb@kernel.org>

> ---
> KernelVersion: v5.15-rc1
> ---
> The corresponding patch for kexec-tools is "[PATCH] arm: kdump: Add DT
> properties to crash dump kernel's DTB", which is still valid:
> https://lore.kernel.org/r/20200902154129.6358-1-geert+renesas@glider.be/
>
> v6:
>   - All dependencies are in v5.15-rc1,
>
> v5:
>   - Remove the addition of "linux,elfcorehdr" and
>     "linux,usable-memory-range" handling to arch/arm/mm/init.c,
>
> v4:
>   - Remove references to architectures in chosen.txt, to avoid having to
>     change this again when more architectures copy kdump support,
>   - Remove the architecture-specific code for parsing
>     "linux,usable-memory-range" and "linux,elfcorehdr", as the FDT core
>     code now takes care of this,
>   - Move chosen.txt change to patch changing the FDT core,
>   - Use IS_ENABLED(CONFIG_CRASH_DUMP) instead of #ifdef,
>
> v3:
>   - Rebase on top of accepted solution for DTB memory information
>     handling, which is part of v5.12-rc1,
>
> v2:
>   - Rebase on top of reworked DTB memory information handling.
> ---
>  .../arm/boot/compressed/fdt_check_mem_start.c | 48 ++++++++++++++++---
>  1 file changed, 42 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/compressed/fdt_check_mem_start.c b/arch/arm/boot/compressed/fdt_check_mem_start.c
> index 62450d824c3ca180..9291a2661bdfe57f 100644
> --- 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 *cells, uint32_t ncells)
>   * 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 mem_start, const void *fdt)
>         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 mem_start, const void *fdt)
>
>                         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 mem_start, const void *fdt)
>         }
>
>         /*
> -        * 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.
>          */
> --
> 2.25.1
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property
  2021-09-15 12:46 [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property Geert Uytterhoeven
  2021-09-22  7:14 ` Ard Biesheuvel
@ 2021-09-23  0:08 ` Linus Walleij
  1 sibling, 0 replies; 3+ messages in thread
From: Linus Walleij @ 2021-09-23  0:08 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Russell King, Nicolas Pitre, Ard Biesheuvel, Lukasz Stelmach,
	Simon Horman, Linux ARM,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel, kexec

On Wed, Sep 15, 2021 at 3:20 PM Geert Uytterhoeven
<geert+renesas@glider.be> wrote:

> 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>

Very nice patch!
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-09-23  0:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-15 12:46 [PATCH v6] ARM: uncompress: Parse "linux,usable-memory-range" DT property Geert Uytterhoeven
2021-09-22  7:14 ` Ard Biesheuvel
2021-09-23  0:08 ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).