All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation
@ 2026-07-08 14:33 Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before " Sourabh Jain
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Sourabh Jain @ 2026-07-08 14:33 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, ritesh.list, shivangu, hbathini, mahesh,
	adityag, venkat88, Sourabh Jain

Add support for reserving crashkernel memory in higher address ranges
using the crashkernel=xxM,high command-line option.

With this feature, most of the crashkernel memory for kdump is reserved
in high memory regions, while only a small portion (64 MB) is reserved
in low memory for RTAS usage. This helps free up low memory for other
components that require allocations in that region.

For example, if crashkernel=2G,high is specified, the kernel reserves
2 GB of crashkernel memory near the end of system RAM and an additional
64 MB of low memory (below 1 GB) for RTAS to function properly.

Currently, this feature is supported only on PPC64 systems with:
64-bit RTAS support
Radix MMU enabled

HASH MMU is currently not supported because kexec segments are loaded
into higher memory by default when using high crashkernel reservation,
and HASH MMU does not support booting kernels loaded at higher memory
addresses.

To support this feature:

- CPU feature discovery is moved before crashkernel reservation so the
  MMU type is known before selecting crashkernel regions. (Patch 01/04)
- RTAS argument handling, allowing RTAS to correctly return to kernel
  addresses above 4 GB. (Patch 02/04)

This patch series leverages the new firmware capability property
("ibm,rtas-64-capable") to enable 64-bit RTAS support and significantly
changes RTAS call handling. Feedback is requested, particularly on the
overall approach and implementation of the 64-bit RTAS support.

- The approach used for enabling 64-bit RTAS support
- The handling and conversion of RTAS arguments for 64-bit RTAS calls
- The RTAS call flow and MSR handling in 64-bit mode

The new DT property "ibm,rtas-64-capable" is currently not described in
PAPR.

Changes since v1:
https://lore.kernel.org/all/20251027151338.819957-1-sourabhjain@linux.ibm.com/

- Detect 64-bit RTAS capability using "ibm,rtas-64-capable" instead of
  relying on instantiate-rtas-64 failure handling
- Add proper 64-bit RTAS argument structure conversion and return value
  handling
- Add dedicated 64-bit RTAS entry path
- Read the actual "linux,rtas-64" DT property value instead of checking
  only property presence
- Simplify rtas_64 initialization and tracking

Sourabh Jain (4):
  powerpc/mmu: do MMU type discovery before crashkernel reservation
  powerpc: move to 64-bit RTAS
  powerpc/kdump: consider high crashkernel memory if enabled
  powerpc/kdump: add support for high crashkernel reservation

 arch/powerpc/include/asm/book3s/64/mmu.h |  1 +
 arch/powerpc/include/asm/crash_reserve.h |  6 +++
 arch/powerpc/include/asm/kexec.h         |  1 +
 arch/powerpc/include/asm/mmu.h           |  1 +
 arch/powerpc/include/asm/rtas-types.h    |  8 ++++
 arch/powerpc/include/asm/rtas.h          | 11 ++++++
 arch/powerpc/kernel/prom.c               | 28 +++++++-------
 arch/powerpc/kernel/prom_init.c          | 20 ++++++++--
 arch/powerpc/kernel/rtas.c               | 48 ++++++++++++++++++++++--
 arch/powerpc/kernel/rtas_entry.S         | 17 ++++++++-
 arch/powerpc/kexec/core.c                | 45 ++++++++++++++++------
 arch/powerpc/kexec/elf_64.c              | 10 +++--
 arch/powerpc/kexec/file_load_64.c        |  5 ++-
 arch/powerpc/kexec/ranges.c              | 24 ++++++++++--
 arch/powerpc/mm/init_64.c                | 27 ++++++++-----
 15 files changed, 202 insertions(+), 50 deletions(-)

-- 
2.52.0



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

* [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before crashkernel reservation
  2026-07-08 14:33 [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation Sourabh Jain
@ 2026-07-08 14:33 ` Sourabh Jain
  2026-07-10  2:44   ` Ritesh Harjani
  2026-07-08 14:33 ` [PATCH v2 2/4] powerpc: move to 64-bit RTAS Sourabh Jain
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 7+ messages in thread
From: Sourabh Jain @ 2026-07-08 14:33 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, ritesh.list, shivangu, hbathini, mahesh,
	adityag, venkat88, Sourabh Jain

Crashkernel reservation on high memory depends on the MMU type, so
finalize the MMU type before calling arch_reserve_crashkernel().

With the changes introduced here, early_radix_enabled() becomes usable
and will be used in arch_reserve_crashkernel() in the upcoming patch.

early_radix_enabled() depends on cur_cpu_spec->mmu_features to find
out if the radix MMU is enabled. The radix MMU bit in mmu_features is
discovered from the FDT and kernel configs. To make sure the MMU type is
finalized before arch_reserve_crashkernel() is called, the function that
scans the FDT and sets mmu_features, along with some bits from
mmu_early_type_finalize(), has been moved above
arch_reserve_crashkernel().

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/include/asm/book3s/64/mmu.h |  1 +
 arch/powerpc/include/asm/mmu.h           |  1 +
 arch/powerpc/kernel/prom.c               | 28 +++++++++++++-----------
 arch/powerpc/mm/init_64.c                | 27 ++++++++++++++---------
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index 48631365b48c..7a3b2ff02041 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -208,6 +208,7 @@ extern int mmu_vmemmap_psize;
 
 /* MMU initialization */
 void mmu_early_init_devtree(void);
+void mmu_early_type_finalize(void);
 void hash__early_init_devtree(void);
 void radix__early_init_devtree(void);
 #ifdef CONFIG_PPC_PKEY
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 5f9c5d436e17..c40dc6349e55 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -384,6 +384,7 @@ extern void early_init_mmu_secondary(void);
 extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				       phys_addr_t first_memblock_size);
 static inline void mmu_early_init_devtree(void) { }
+static inline void mmu_early_type_finalize(void) { }
 
 static inline void pkey_early_init_devtree(void) {}
 
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9ed9dde7d231..db1615f26075 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -853,6 +853,21 @@ void __init early_init_devtree(void *params)
 	if (PHYSICAL_START > MEMORY_START)
 		memblock_reserve(MEMORY_START, int_vector_size);
 	reserve_kdump_trampoline();
+
+	DBG("Scanning CPUs ...\n");
+
+	dt_cpu_ftrs_scan();
+
+	/* Retrieve CPU related informations from the flat tree
+	 * (altivec support, boot CPU ID, ...)
+	 */
+	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
+	if (boot_cpuid < 0) {
+		printk("Failed to identify boot CPU !\n");
+		BUG();
+	}
+
+	mmu_early_type_finalize();
 #if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)
 	/*
 	 * If we fail to reserve memory for firmware-assisted dump then
@@ -884,19 +899,6 @@ void __init early_init_devtree(void *params)
 	 * FIXME .. and the initrd too? */
 	move_device_tree();
 
-	DBG("Scanning CPUs ...\n");
-
-	dt_cpu_ftrs_scan();
-
-	/* Retrieve CPU related informations from the flat tree
-	 * (altivec support, boot CPU ID, ...)
-	 */
-	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
-	if (boot_cpuid < 0) {
-		printk("Failed to identify boot CPU !\n");
-		BUG();
-	}
-
 	save_fscr_to_task();
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 64f0df5bb5cd..2fd533bc17cc 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -614,8 +614,10 @@ static void __init early_init_memory_block_size(void)
 	of_scan_flat_dt(probe_memory_block_size, &memory_block_size);
 }
 
-void __init mmu_early_init_devtree(void)
+
+void __init mmu_early_type_finalize(void)
 {
+
 	bool hvmode = !!(mfmsr() & MSR_HV);
 
 	/* Disable radix mode based on kernel command line. */
@@ -626,6 +628,20 @@ void __init mmu_early_init_devtree(void)
 			pr_warn("WARNING: Ignoring cmdline option disable_radix\n");
 	}
 
+	/*
+	 * Check /chosen/ibm,architecture-vec-5 if running as a guest.
+	 * When running bare-metal, we can use radix if we like
+	 * even though the ibm,architecture-vec-5 property created by
+	 * skiboot doesn't have the necessary bits set.
+	 */
+	if (!hvmode)
+		early_check_vec5();
+}
+
+void __init mmu_early_init_devtree(void)
+{
+	bool hvmode = !!(mfmsr() & MSR_HV);
+
 	of_scan_flat_dt(dt_scan_mmu_pid_width, NULL);
 	if (hvmode && !mmu_lpid_bits) {
 		if (early_cpu_has_feature(CPU_FTR_ARCH_207S))
@@ -638,15 +654,6 @@ void __init mmu_early_init_devtree(void)
 			mmu_pid_bits = 20; /* POWER9-10 */
 	}
 
-	/*
-	 * Check /chosen/ibm,architecture-vec-5 if running as a guest.
-	 * When running bare-metal, we can use radix if we like
-	 * even though the ibm,architecture-vec-5 property created by
-	 * skiboot doesn't have the necessary bits set.
-	 */
-	if (!hvmode)
-		early_check_vec5();
-
 	early_init_memory_block_size();
 
 	if (early_radix_enabled()) {
-- 
2.52.0



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

* [PATCH v2 2/4] powerpc: move to 64-bit RTAS
  2026-07-08 14:33 [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before " Sourabh Jain
@ 2026-07-08 14:33 ` Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 3/4] powerpc/kdump: consider high crashkernel memory if enabled Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 4/4] powerpc/kdump: add support for high crashkernel reservation Sourabh Jain
  3 siblings, 0 replies; 7+ messages in thread
From: Sourabh Jain @ 2026-07-08 14:33 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, ritesh.list, shivangu, hbathini, mahesh,
	adityag, venkat88, Sourabh Jain

Kdump kernels loaded at high addresses (above 4G) could not boot
because the kernel used 32-bit RTAS.

Until now, the kernel always used 32-bit RTAS, even for 64-bit kernels.
Before making an RTAS call, it clears the SF bit in MSR and uses LR as
the return address from RTAS. For kdump kernels loaded above 4G, RTAS
returns to a 32-bit truncated LR address, typically causing an exception
and kernel panic.

Fix this by switching to 64-bit RTAS support on systems where firmware
advertises "ibm,rtas-64-capable". The kernel instantiates 64-bit RTAS,
passes RTAS arguments using a 64-bit argument structure, and sets the
SF bit in MSR before entering RTAS. This ensures RTAS can correctly
return to addresses above 4G and allows high-address kdump kernels to
boot successfully.

If 64-bit RTAS is not supported or initialization fails, the kernel
continues to use 32-bit RTAS. In that case, high-address kdump kernels
will not be allowed (handled in upcoming patches), and RTAS calls will
continue to run with the SF bit cleared.

Changes made to support 64-bit RTAS:
- Detect firmware support using "ibm,rtas-64-capable"
- Initialize 64-bit RTAS in prom_init and add a new FDT property
  "linux,rtas-64"
- Read "linux,rtas-64" during boot and track RTAS mode using rtas_64
- Add 64-bit RTAS argument handling and return value conversion
- Prepare MSR appropriately for 32-bit or 64-bit RTAS calls

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/include/asm/rtas-types.h |  8 +++++
 arch/powerpc/include/asm/rtas.h       |  2 ++
 arch/powerpc/kernel/prom_init.c       | 20 +++++++++--
 arch/powerpc/kernel/rtas.c            | 48 +++++++++++++++++++++++++--
 arch/powerpc/kernel/rtas_entry.S      | 17 +++++++++-
 5 files changed, 88 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/rtas-types.h b/arch/powerpc/include/asm/rtas-types.h
index 5d40d187b965..de794b3e0fbd 100644
--- a/arch/powerpc/include/asm/rtas-types.h
+++ b/arch/powerpc/include/asm/rtas-types.h
@@ -14,6 +14,14 @@ struct rtas_args {
 	rtas_arg_t *rets;     /* Pointer to return values in args[]. */
 } __aligned(8);
 
+struct rtas_args_64 {
+        __be64 token;
+        __be64 nargs;
+        __be64 nret;
+        __be64 args[16];
+        __be64 *rets;     /* Pointer to return values in args[]. */
+} __aligned(8);
+
 struct rtas_t {
 	unsigned long entry;		/* physical address pointer */
 	unsigned long base;		/* physical address pointer */
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index d046bbd5017d..aaa4c3bc1d61 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -10,6 +10,8 @@
 #include <linux/time.h>
 #include <linux/cpumask.h>
 
+extern int rtas_64;
+
 /*
  * Definitions for talking to the RTAS on CHRP machines.
  *
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 53503937de0e..be7c5ea0b75d 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1841,6 +1841,7 @@ static void __init prom_instantiate_rtas(void)
 	u32 base, entry = 0;
 	__be32 val;
 	u32 size = 0;
+	u32 rtas_64 = 0;
 
 	prom_debug("prom_instantiate_rtas: start...\n");
 
@@ -1865,15 +1866,24 @@ static void __init prom_instantiate_rtas(void)
 		return;
 	}
 
+	/* Check for rtas 64-bit support */
+	if (prom_getprop(rtas_node, "ibm,rtas-64-capable",
+			 &val, sizeof(val)) != PROM_ERROR) {
+		rtas_64 = 1;
+		prom_debug("Node ibm,rtas-64-capable: %x\n", val);
+	}
+
 	prom_printf("instantiating rtas at 0x%x...", base);
 
+	const char *method = rtas_64 ? "instantiate-rtas-64" : "instantiate-rtas";
+
 	if (call_prom_ret("call-method", 3, 2, &entry,
-			  ADDR("instantiate-rtas"),
-			  rtas_inst, base) != 0
-	    || entry == 0) {
+			  ADDR(method), rtas_inst, base) != 0 ||
+			  entry == 0) {
 		prom_printf(" failed\n");
 		return;
 	}
+
 	prom_printf(" done\n");
 
 	reserve_mem(base, size);
@@ -1884,6 +1894,9 @@ static void __init prom_instantiate_rtas(void)
 	val = cpu_to_be32(entry);
 	prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
 		     &val, sizeof(val));
+	val = cpu_to_be32(rtas_64);
+	prom_setprop(rtas_node, "/rtas", "linux,rtas-64",
+		     &val, sizeof(val));
 
 	/* Check if it supports "query-cpu-stopped-state" */
 	if (prom_getprop(rtas_node, "query-cpu-stopped-state",
@@ -1893,6 +1906,7 @@ static void __init prom_instantiate_rtas(void)
 	prom_debug("rtas base     = 0x%x\n", base);
 	prom_debug("rtas entry    = 0x%x\n", entry);
 	prom_debug("rtas size     = 0x%x\n", size);
+	prom_debug("rtas 64-bit   = 0x%x\n", rtas_64);
 
 	prom_debug("prom_instantiate_rtas: end...\n");
 }
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 8d81c1e7a8db..b7b9bd0b5b43 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -45,6 +45,8 @@
 #include <asm/trace.h>
 #include <asm/udbg.h>
 
+int rtas_64;
+
 struct rtas_filter {
 	/* Indexes into the args buffer, -1 if not used */
 	const int buf_idx1;
@@ -569,6 +571,7 @@ static struct rtas_function rtas_function_table[] __ro_after_init = {
  */
 static DEFINE_RAW_SPINLOCK(rtas_lock);
 static struct rtas_args rtas_args;
+static struct rtas_args_64 rtas_args_64;
 
 /**
  * rtas_function_token() - RTAS function token lookup.
@@ -690,13 +693,48 @@ static const struct rtas_function *rtas_token_to_function(s32 token)
 	return NULL;
 }
 
+static void populate_rtas_args_64(struct rtas_args *args)
+{
+	int i;
+
+	rtas_args_64.token = cpu_to_be64((s64)(s32)be32_to_cpu(args->token));
+	rtas_args_64.nargs = cpu_to_be64((s64)(s32)be32_to_cpu(args->nargs));
+	rtas_args_64.nret  = cpu_to_be64((s64)(s32)be32_to_cpu(args->nret));
+	rtas_args_64.rets  = &rtas_args_64.args[be32_to_cpu(args->nargs)];
+
+	for (i = 0; i < be32_to_cpu(args->nargs); ++i)
+		rtas_args_64.args[i] = cpu_to_be64((s64)(s32)be32_to_cpu(args->args[i]));
+
+	for (i = 0; i < be32_to_cpu(args->nret); ++i)
+		rtas_args_64.rets[i] = 0;
+}
+
+static void rtas_args_copy_64_32(struct rtas_args *args)
+{
+	int i;
+
+	for (i = 0; i < (s32)be64_to_cpu(rtas_args_64.nret); ++i)
+		args->rets[i] = cpu_to_be32((s32)be64_to_cpu(rtas_args_64.rets[i]));
+}
+
 /* This is here deliberately so it's only used in this file */
 void enter_rtas(unsigned long);
 
+static void _do_enter_rtas_64(struct rtas_args *args)
+{
+	populate_rtas_args_64(args);
+	enter_rtas(__pa(&rtas_args_64));
+	rtas_args_copy_64_32(args);
+}
+
 static void __do_enter_rtas(struct rtas_args *args)
 {
-	enter_rtas(__pa(args));
-	srr_regs_clobbered(); /* rtas uses SRRs, invalidate */
+	if (rtas_64)
+		_do_enter_rtas_64(args);
+	else
+		enter_rtas(__pa(args));
+
+	srr_regs_clobbered();
 }
 
 static void __do_enter_rtas_trace(struct rtas_args *args)
@@ -2078,7 +2116,7 @@ void __init rtas_initialize(void)
 int __init early_init_dt_scan_rtas(unsigned long node,
 		const char *uname, int depth, void *data)
 {
-	const u32 *basep, *entryp, *sizep;
+	const u32 *basep, *entryp, *sizep, *val;
 
 	if (depth != 1 || strcmp(uname, "rtas") != 0)
 		return 0;
@@ -2086,6 +2124,10 @@ int __init early_init_dt_scan_rtas(unsigned long node,
 	basep  = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
 	entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
 	sizep  = of_get_flat_dt_prop(node, "rtas-size", NULL);
+	val    = of_get_flat_dt_prop(node, "linux,rtas-64", NULL);
+
+	if (*val)
+		rtas_64 = 1;
 
 #ifdef CONFIG_PPC64
 	/* need this feature to decide the crashkernel offset */
diff --git a/arch/powerpc/kernel/rtas_entry.S b/arch/powerpc/kernel/rtas_entry.S
index 6ce95ddadbcd..df776f0103c9 100644
--- a/arch/powerpc/kernel/rtas_entry.S
+++ b/arch/powerpc/kernel/rtas_entry.S
@@ -54,6 +54,10 @@ _ASM_NOKPROBE_SYMBOL(enter_rtas)
 /*
  * 32-bit rtas on 64-bit machines has the additional problem that RTAS may
  * not preserve the upper parts of registers it uses.
+ *
+ * Note: In 64-bit RTAS, the SF bit is set so that RTAS can return
+ * correctly if the return address is above 4 GB. Everything else
+ * works the same as in 32-bit RTAS.
  */
 _GLOBAL(enter_rtas)
 	mflr	r0
@@ -113,7 +117,18 @@ __enter_rtas:
 	 * from the saved MSR value and insert into the value RTAS will use.
 	 */
 	extrdi	r0, r6, 1, 63 - MSR_HV_LG
-	LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
+
+	LOAD_REG_ADDR(r7, rtas_64)	/* Load the address rtas_64 into r7 */
+	ld      r8, 0(r7)               /* Load the value of rtas_64 from memory into r8 */
+	cmpdi   r8, 0                   /* Compare r8 with 0 (check if rtas_64 is zero) */
+	beq     no_sf_bit               /* Branch to no_sf_bit if rtas_64 is zero */
+	LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI | MSR_SF)	/* r6 = ME|RI|SF */
+	b       continue
+
+no_sf_bit:
+	LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)		/* r6 = ME|RI (NO SF bit in MSR) */
+
+continue:
 	insrdi	r6, r0, 1, 63 - MSR_HV_LG
 
 	li      r0,0
-- 
2.52.0



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

* [PATCH v2 3/4] powerpc/kdump: consider high crashkernel memory if enabled
  2026-07-08 14:33 [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before " Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 2/4] powerpc: move to 64-bit RTAS Sourabh Jain
@ 2026-07-08 14:33 ` Sourabh Jain
  2026-07-08 14:33 ` [PATCH v2 4/4] powerpc/kdump: add support for high crashkernel reservation Sourabh Jain
  3 siblings, 0 replies; 7+ messages in thread
From: Sourabh Jain @ 2026-07-08 14:33 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, ritesh.list, shivangu, hbathini, mahesh,
	adityag, venkat88, Sourabh Jain

The next patch adds high crashkernel reservation support on powerpc, so
kdump setup is updated to handle high crashkernel while loading the kdump
kernel.

With high crashkernel reservation, the crashkernel is split into two
regions: low crashkernel and high crashkernel. To ensure kdump loads
properly with the split reservation, the following changes are made:

 - Load the kdump image in high memory if enabled
 - Include both low and high crashkernel regions in usable memory
   ranges for the kdump kernel
 - Exclude both low and high crashkernel regions from crashkernel memory
  to prevent them from being exported through /proc/vmcore

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/kexec/elf_64.c       | 10 +++++++---
 arch/powerpc/kexec/file_load_64.c |  5 +++--
 arch/powerpc/kexec/ranges.c       | 24 +++++++++++++++++++++---
 3 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
index ea50a072debf..85a6e92f1160 100644
--- a/arch/powerpc/kexec/elf_64.c
+++ b/arch/powerpc/kexec/elf_64.c
@@ -52,9 +52,13 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
 	if (IS_ENABLED(CONFIG_CRASH_DUMP) && image->type == KEXEC_TYPE_CRASH) {
 		/* min & max buffer values for kdump case */
 		kbuf.buf_min = pbuf.buf_min = crashk_res.start;
-		kbuf.buf_max = pbuf.buf_max =
-				((crashk_res.end < ppc64_rma_size) ?
-				 crashk_res.end : (ppc64_rma_size - 1));
+
+		if (crashk_low_res.end)
+			kbuf.buf_max = pbuf.buf_max = crashk_res.end;
+		else
+			kbuf.buf_max = pbuf.buf_max =
+					((crashk_res.end < ppc64_rma_size) ?
+					crashk_res.end : (ppc64_rma_size - 1));
 	}
 
 	ret = kexec_elf_load(image, &ehdr, &elf_info, &kbuf, &kernel_load_addr);
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
index 8c72e12ea44e..701d226cd23f 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -731,6 +731,7 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, struct crash_mem
 	int i, nr_ranges, ret;
 
 #ifdef CONFIG_CRASH_DUMP
+	uint64_t crashk_start;
 	/*
 	 * Restrict memory usage for kdump kernel by setting up
 	 * usable memory ranges and memory reserve map.
@@ -750,8 +751,8 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, struct crash_mem
 		 * Ensure we don't touch crashed kernel's memory except the
 		 * first 64K of RAM, which will be backed up.
 		 */
-		ret = fdt_add_mem_rsv(fdt, BACKUP_SRC_END + 1,
-				      crashk_res.start - BACKUP_SRC_SIZE);
+		crashk_start = crashk_low_res.end ? crashk_low_res.start : crashk_res.start;
+		ret = fdt_add_mem_rsv(fdt, BACKUP_SRC_END + 1, crashk_start - BACKUP_SRC_SIZE);
 		if (ret) {
 			pr_err("Error reserving crash memory: %s\n",
 			       fdt_strerror(ret));
diff --git a/arch/powerpc/kexec/ranges.c b/arch/powerpc/kexec/ranges.c
index 867135560e5c..1b08c05ab5a8 100644
--- a/arch/powerpc/kexec/ranges.c
+++ b/arch/powerpc/kexec/ranges.c
@@ -524,9 +524,20 @@ int get_usable_memory_ranges(struct crash_mem **mem_ranges)
 	 * Also, crashed kernel's memory must be added to reserve map to
 	 * avoid kdump kernel from using it.
 	 */
-	ret = add_mem_range(mem_ranges, 0, crashk_res.end + 1);
-	if (ret)
-		goto out;
+	if (crashk_low_res.end) {
+		ret = add_mem_range(mem_ranges, 0, crashk_low_res.end + 1);
+		if (ret)
+			goto out;
+
+		ret = add_mem_range(mem_ranges, crashk_res.start,
+				    crashk_res.end - crashk_res.start + 1);
+		if (ret)
+			goto out;
+	} else {
+		ret = add_mem_range(mem_ranges, 0, crashk_res.end + 1);
+		if (ret)
+			goto out;
+	}
 
 	for (i = 0; i < crashk_cma_cnt; i++) {
 		ret = add_mem_range(mem_ranges, crashk_cma_ranges[i].start,
@@ -609,6 +620,13 @@ int get_crash_memory_ranges(struct crash_mem **mem_ranges)
 	if (ret)
 		goto out;
 
+	if (crashk_low_res.end) {
+		ret = crash_exclude_mem_range_guarded(mem_ranges, crashk_low_res.start,
+						      crashk_low_res.end);
+		if (ret)
+			goto out;
+	}
+
 	for (i = 0; i < crashk_cma_cnt; ++i) {
 		ret = crash_exclude_mem_range_guarded(mem_ranges, crashk_cma_ranges[i].start,
 					      crashk_cma_ranges[i].end);
-- 
2.52.0



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

* [PATCH v2 4/4] powerpc/kdump: add support for high crashkernel reservation
  2026-07-08 14:33 [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation Sourabh Jain
                   ` (2 preceding siblings ...)
  2026-07-08 14:33 ` [PATCH v2 3/4] powerpc/kdump: consider high crashkernel memory if enabled Sourabh Jain
@ 2026-07-08 14:33 ` Sourabh Jain
  3 siblings, 0 replies; 7+ messages in thread
From: Sourabh Jain @ 2026-07-08 14:33 UTC (permalink / raw)
  To: linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, ritesh.list, shivangu, hbathini, mahesh,
	adityag, venkat88, Sourabh Jain

With this changes included crashkernel=xxM,high will be supported on
powerpc. This allow user to allocated crashkernel memory on higer memory
region and keeping the low memory allocation minimal.

The low memory reservation is by default set to 64 MB and it is reserved
below RTAS_INSTANTIATE_MAX (1G) to make sure rtas instantiation work
properly.

powerpc uses generic crashkernel parser and reserve functions and they
are capable of handling high crashkernel reservtion so
arch_reserve_crashkernel() is updated call generic crashkernel praser
and reserve function with resptive options to make
crashkernel=XXM,high prase and make crashkernel memory get reserved on
higher memory regions.

Note: High crashkernel is supported only on PPC 64-bit systems when
64-bit RTAS is instantiated and Radix MMU is enabled; otherwise, the
crashkernel reservation falls back to the default, even if the kernel
command includes crashkernel=XXM,high.

Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
---
 arch/powerpc/include/asm/crash_reserve.h |  6 ++++
 arch/powerpc/include/asm/kexec.h         |  1 +
 arch/powerpc/include/asm/rtas.h          |  9 +++++
 arch/powerpc/kexec/core.c                | 45 +++++++++++++++++-------
 4 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/include/asm/crash_reserve.h b/arch/powerpc/include/asm/crash_reserve.h
index d1b570ddbf98..4f2096984736 100644
--- a/arch/powerpc/include/asm/crash_reserve.h
+++ b/arch/powerpc/include/asm/crash_reserve.h
@@ -2,6 +2,8 @@
 #ifndef _ASM_POWERPC_CRASH_RESERVE_H
 #define _ASM_POWERPC_CRASH_RESERVE_H
 
+#include <asm/rtas.h>
+
 /* crash kernel regions are Page size agliged */
 #define CRASH_ALIGN             PAGE_SIZE
 
@@ -12,5 +14,9 @@ static inline bool arch_add_crash_res_to_iomem(void)
 }
 #define arch_add_crash_res_to_iomem arch_add_crash_res_to_iomem
 #endif
+#define DEFAULT_CRASH_KERNEL_LOW_SIZE SZ_64M
+
+#define CRASH_ADDR_LOW_MAX	RTAS_INSTANTIATE_MAX
+#define CRASH_ADDR_HIGH_MAX	memblock_end_of_DRAM()
 
 #endif /* _ASM_POWERPC_CRASH_RESERVE_H */
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index e02710d6a2e1..9e676bd3bf03 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -118,6 +118,7 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, struct crash_mem
 int __init overlaps_crashkernel(unsigned long start, unsigned long size);
 extern void arch_reserve_crashkernel(void);
 extern void kdump_cma_reserve(void);
+unsigned long long __init get_crash_base(unsigned long long crash_base);
 #else
 static inline void arch_reserve_crashkernel(void) {}
 static inline int overlaps_crashkernel(unsigned long start, unsigned long size) { return 0; }
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h
index aaa4c3bc1d61..d290437d8131 100644
--- a/arch/powerpc/include/asm/rtas.h
+++ b/arch/powerpc/include/asm/rtas.h
@@ -561,6 +561,14 @@ static inline int page_is_rtas_user_buf(unsigned long pfn)
 	return 0;
 }
 
+static inline bool is_rtas_high_crashkernel_capable(void)
+{
+	if (rtas_64)
+		return true;
+
+	return false;
+}
+
 /* Not the best place to put pSeries_coalesce_init, will be fixed when we
  * move some of the rtas suspend-me stuff to pseries */
 void pSeries_coalesce_init(void);
@@ -569,6 +577,7 @@ void rtas_initialize(void);
 static inline int page_is_rtas_user_buf(unsigned long pfn) { return 0;}
 static inline void pSeries_coalesce_init(void) { }
 static inline void rtas_initialize(void) { }
+static inline bool is_rtas_high_crashkernel_capable(void) { return true; }
 #endif
 
 #ifdef CONFIG_HV_PERF_CTRS
diff --git a/arch/powerpc/kexec/core.c b/arch/powerpc/kexec/core.c
index dc44f11be353..81fc437377c8 100644
--- a/arch/powerpc/kexec/core.c
+++ b/arch/powerpc/kexec/core.c
@@ -15,6 +15,7 @@
 #include <linux/irq.h>
 #include <linux/ftrace.h>
 
+#include <asm/rtas.h>
 #include <asm/kdump.h>
 #include <asm/machdep.h>
 #include <asm/pgalloc.h>
@@ -64,7 +65,7 @@ void machine_kexec(struct kimage *image)
 
 static unsigned long long crashk_cma_size;
 
-static unsigned long long __init get_crash_base(unsigned long long crash_base)
+unsigned long long __init get_crash_base(unsigned long long crash_base)
 {
 
 #ifndef CONFIG_NONSTATIC_KERNEL
@@ -104,35 +105,55 @@ static unsigned long long __init get_crash_base(unsigned long long crash_base)
 #endif
 }
 
+static bool high_crashkernel_supported(void)
+{
+#if defined(CONFIG_PPC64) && (defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV))
+	if (early_radix_enabled() && is_rtas_high_crashkernel_capable())
+		return true;
+#endif
+	return false;
+}
+
 void __init arch_reserve_crashkernel(void)
 {
-	unsigned long long crash_size, crash_base, crash_end;
+	unsigned long long crash_size, crash_base, crash_end, low_size = 0;
 	unsigned long long kernel_start, kernel_size;
 	unsigned long long total_mem_sz;
+	bool high = false;
 	int ret;
 
 	total_mem_sz = memory_limit ? memory_limit : memblock_phys_mem_size();
 
 	/* use common parsing */
 	ret = parse_crashkernel(boot_command_line, total_mem_sz, &crash_size,
-				&crash_base, NULL, &crashk_cma_size, NULL);
+				&crash_base, &low_size, &crashk_cma_size, &high);
 
 	if (ret)
 		return;
 
-	crash_base = get_crash_base(crash_base);
-	crash_end = crash_base + crash_size - 1;
+	if (high && !high_crashkernel_supported()) {
+		high = false;
+		low_size = 0;
+		pr_warn("High crashkernel unsupported, using standard reservation");
+	}
 
-	kernel_start = __pa(_stext);
-	kernel_size = _end - _stext;
+	if (high) {
+		crash_base = 0;
+	} else {
+		crash_base = get_crash_base(crash_base);
+		crash_end = crash_base + crash_size - 1;
 
-	/* The crash region must not overlap the current kernel */
-	if ((kernel_start + kernel_size > crash_base) && (kernel_start <= crash_end)) {
-		pr_warn("Crash kernel can not overlap current kernel\n");
-		return;
+		kernel_start = __pa(_stext);
+		kernel_size = _end - _stext;
+
+		/* The crash region must not overlap the current kernel */
+		if ((kernel_start + kernel_size > crash_base) && (kernel_start <= crash_end)) {
+			pr_warn("Crash kernel can not overlap current kernel\n");
+			return;
+		}
 	}
 
-	reserve_crashkernel_generic(crash_size, crash_base, 0, false);
+	reserve_crashkernel_generic(crash_size, crash_base, low_size, high);
 }
 
 void __init kdump_cma_reserve(void)
-- 
2.52.0



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

* Re: [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before crashkernel reservation
  2026-07-08 14:33 ` [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before " Sourabh Jain
@ 2026-07-10  2:44   ` Ritesh Harjani
  2026-07-13 13:12     ` Sourabh Jain
  0 siblings, 1 reply; 7+ messages in thread
From: Ritesh Harjani @ 2026-07-10  2:44 UTC (permalink / raw)
  To: Sourabh Jain, linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88,
	Sourabh Jain


Minor nits

Sourabh Jain <sourabhjain@linux.ibm.com> writes:

> Crashkernel reservation on high memory depends on the MMU type, so
> finalize the MMU type before calling arch_reserve_crashkernel().
>
> With the changes introduced here, early_radix_enabled() becomes usable
> and will be used in arch_reserve_crashkernel() in the upcoming patch.
>
> early_radix_enabled() depends on cur_cpu_spec->mmu_features to find
> out if the radix MMU is enabled. The radix MMU bit in mmu_features is
> discovered from the FDT and kernel configs. To make sure the MMU type is
> finalized before arch_reserve_crashkernel() is called, the function that
> scans the FDT and sets mmu_features, along with some bits from
> mmu_early_type_finalize(), has been moved above
> arch_reserve_crashkernel().
>

Can you also add a short description of why can't we move
arch_reserve_crashkernel() to a later point instead of breaking
mmu_early_init_devtree() and moving the xx_type_finalize() part above?

If I am not wrong, it is since move_device_tree() checks whether the FDT
overlaps the crash kernel reservation. So arch_reserve_crashkernel()
must be called before move_device_tree().


> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
> ---
>  arch/powerpc/include/asm/book3s/64/mmu.h |  1 +
>  arch/powerpc/include/asm/mmu.h           |  1 +
>  arch/powerpc/kernel/prom.c               | 28 +++++++++++++-----------
>  arch/powerpc/mm/init_64.c                | 27 ++++++++++++++---------
>  4 files changed, 34 insertions(+), 23 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
> index 48631365b48c..7a3b2ff02041 100644
> --- a/arch/powerpc/include/asm/book3s/64/mmu.h
> +++ b/arch/powerpc/include/asm/book3s/64/mmu.h
> @@ -208,6 +208,7 @@ extern int mmu_vmemmap_psize;
>  
>  /* MMU initialization */
>  void mmu_early_init_devtree(void);
> +void mmu_early_type_finalize(void);

can you rename this as mmu_early_init_type().

Otherwise the change looks good to me. With the above 2 addressed, feel
free to add:

Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>



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

* Re: [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before crashkernel reservation
  2026-07-10  2:44   ` Ritesh Harjani
@ 2026-07-13 13:12     ` Sourabh Jain
  0 siblings, 0 replies; 7+ messages in thread
From: Sourabh Jain @ 2026-07-13 13:12 UTC (permalink / raw)
  To: Ritesh Harjani (IBM), linuxppc-dev, maddy, mpe
  Cc: npiggin, chleroy, shivangu, hbathini, mahesh, adityag, venkat88



On 10/07/26 08:14, Ritesh Harjani (IBM) wrote:
> Minor nits
>
> Sourabh Jain <sourabhjain@linux.ibm.com> writes:
>
>> Crashkernel reservation on high memory depends on the MMU type, so
>> finalize the MMU type before calling arch_reserve_crashkernel().
>>
>> With the changes introduced here, early_radix_enabled() becomes usable
>> and will be used in arch_reserve_crashkernel() in the upcoming patch.
>>
>> early_radix_enabled() depends on cur_cpu_spec->mmu_features to find
>> out if the radix MMU is enabled. The radix MMU bit in mmu_features is
>> discovered from the FDT and kernel configs. To make sure the MMU type is
>> finalized before arch_reserve_crashkernel() is called, the function that
>> scans the FDT and sets mmu_features, along with some bits from
>> mmu_early_type_finalize(), has been moved above
>> arch_reserve_crashkernel().
>>
> Can you also add a short description of why can't we move
> arch_reserve_crashkernel() to a later point instead of breaking
> mmu_early_init_devtree() and moving the xx_type_finalize() part above?

The main reason is that the crashkernel requires one large contiguous memory
block to be reserved at a specific memory offset. To ensure this 
allocation succeeds,
the crashkernel memory is reserved before any other components reserve 
memory.

> If I am not wrong, it is since move_device_tree() checks whether the FDT
> overlaps the crash kernel reservation. So arch_reserve_crashkernel()
> must be called before move_device_tree().

I think the bootloader loads the device tree and may chose a location 
that may falls
within the crashkernel region. The purpose of move_device_tree() is to 
relocate
the device tree so that it no longer occupies the crashkernel memory. 
Otherwise,
that memory region would also need to be excluded from the crashkernel
reserved area (and also need special APIs to access device tree present in
reserved memory regions), similar to the RTAS region.

- Sourabh Jain

>
>
>> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
>> ---
>>   arch/powerpc/include/asm/book3s/64/mmu.h |  1 +
>>   arch/powerpc/include/asm/mmu.h           |  1 +
>>   arch/powerpc/kernel/prom.c               | 28 +++++++++++++-----------
>>   arch/powerpc/mm/init_64.c                | 27 ++++++++++++++---------
>>   4 files changed, 34 insertions(+), 23 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
>> index 48631365b48c..7a3b2ff02041 100644
>> --- a/arch/powerpc/include/asm/book3s/64/mmu.h
>> +++ b/arch/powerpc/include/asm/book3s/64/mmu.h
>> @@ -208,6 +208,7 @@ extern int mmu_vmemmap_psize;
>>   
>>   /* MMU initialization */
>>   void mmu_early_init_devtree(void);
>> +void mmu_early_type_finalize(void);
> can you rename this as mmu_early_init_type().
>
> Otherwise the change looks good to me. With the above 2 addressed, feel
> free to add:
>
> Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
>
>



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

end of thread, other threads:[~2026-07-13 13:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 14:33 [PATCH v2 0/4] powerpc/kdump: Support high crashkernel reservation Sourabh Jain
2026-07-08 14:33 ` [PATCH v2 1/4] powerpc/mmu: do MMU type discovery before " Sourabh Jain
2026-07-10  2:44   ` Ritesh Harjani
2026-07-13 13:12     ` Sourabh Jain
2026-07-08 14:33 ` [PATCH v2 2/4] powerpc: move to 64-bit RTAS Sourabh Jain
2026-07-08 14:33 ` [PATCH v2 3/4] powerpc/kdump: consider high crashkernel memory if enabled Sourabh Jain
2026-07-08 14:33 ` [PATCH v2 4/4] powerpc/kdump: add support for high crashkernel reservation Sourabh Jain

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.