Commit b4a96ab5 authored by Sourabh Jain's avatar Sourabh Jain Committed by Madhavan Srinivasan
Browse files

powerpc/kdump: Add support for crashkernel CMA reservation



Commit 35c18f29 ("Add a new optional ",cma" suffix to the
crashkernel= command line option") and commit ab475510 ("kdump:
implement reserve_crashkernel_cma") added CMA support for kdump
crashkernel reservation.

Extend crashkernel CMA reservation support to powerpc.

The following changes are made to enable CMA reservation on powerpc:

- Parse and obtain the CMA reservation size along with other crashkernel
  parameters
- Call reserve_crashkernel_cma() to allocate the CMA region for kdump
- Include the CMA-reserved ranges in the usable memory ranges for the
  kdump kernel to use.
- Exclude the CMA-reserved ranges from the crash kernel memory to
  prevent them from being exported through /proc/vmcore.

With the introduction of the CMA crashkernel regions,
crash_exclude_mem_range() needs to be called multiple times to exclude
both crashk_res and crashk_cma_ranges from the crash memory ranges. To
avoid repetitive logic for validating mem_ranges size and handling
reallocation when required, this functionality is moved to a new wrapper
function crash_exclude_mem_range_guarded().

To ensure proper CMA reservation, reserve_crashkernel_cma() is called
after pageblock_order is initialized.

Update kernel-parameters.txt to document CMA support for crashkernel on
powerpc architecture.

Signed-off-by: default avatarSourabh Jain <sourabhjain@linux.ibm.com>
Reviewed-by: default avatarRitesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: default avatarMadhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20251107080334.708028-1-sourabhjain@linux.ibm.com
parent 8127c4fd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1013,7 +1013,7 @@
			It will be ignored when crashkernel=X,high is not used
			or memory reserved is below 4G.
	crashkernel=size[KMG],cma
			[KNL, X86] Reserve additional crash kernel memory from
			[KNL, X86, ppc] Reserve additional crash kernel memory from
			CMA. This reservation is usable by the first system's
			userspace memory and kernel movable allocations (memory
			balloon, zswap). Pages allocated from this memory range
+2 −0
Original line number Diff line number Diff line
@@ -115,9 +115,11 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, struct crash_mem
#ifdef CONFIG_CRASH_RESERVE
int __init overlaps_crashkernel(unsigned long start, unsigned long size);
extern void arch_reserve_crashkernel(void);
extern void kdump_cma_reserve(void);
#else
static inline void arch_reserve_crashkernel(void) {}
static inline int overlaps_crashkernel(unsigned long start, unsigned long size) { return 0; }
static inline void kdump_cma_reserve(void) { }
#endif

#if defined(CONFIG_CRASH_DUMP)
+3 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/of_irq.h>
#include <linux/hugetlb.h>
#include <linux/pgtable.h>
#include <asm/kexec.h>
#include <asm/io.h>
#include <asm/paca.h>
#include <asm/processor.h>
@@ -995,11 +996,12 @@ void __init setup_arch(char **cmdline_p)
	initmem_init();

	/*
	 * Reserve large chunks of memory for use by CMA for fadump, KVM and
	 * Reserve large chunks of memory for use by CMA for kdump, fadump, KVM and
	 * hugetlb. These must be called after initmem_init(), so that
	 * pageblock_order is initialised.
	 */
	fadump_cma_init();
	kdump_cma_reserve();
	kvm_cma_reserve();
	gigantic_hugetlb_cma_reserve();

+9 −1
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ void machine_kexec(struct kimage *image)

#ifdef CONFIG_CRASH_RESERVE

static unsigned long long crashk_cma_size;

static unsigned long long __init get_crash_base(unsigned long long crash_base)
{

@@ -110,7 +112,7 @@ void __init arch_reserve_crashkernel(void)

	/* use common parsing */
	ret = parse_crashkernel(boot_command_line, total_mem_sz, &crash_size,
				&crash_base, NULL, NULL, NULL);
				&crash_base, NULL, &crashk_cma_size, NULL);

	if (ret)
		return;
@@ -130,6 +132,12 @@ void __init arch_reserve_crashkernel(void)
	reserve_crashkernel_generic(crash_size, crash_base, 0, false);
}

void __init kdump_cma_reserve(void)
{
	if (crashk_cma_size)
		reserve_crashkernel_cma(crashk_cma_size);
}

int __init overlaps_crashkernel(unsigned long start, unsigned long size)
{
	return (start + size) > crashk_res.start && start <= crashk_res.end;
+32 −11
Original line number Diff line number Diff line
@@ -515,7 +515,7 @@ int get_exclude_memory_ranges(struct crash_mem **mem_ranges)
 */
int get_usable_memory_ranges(struct crash_mem **mem_ranges)
{
	int ret;
	int ret, i;

	/*
	 * Early boot failure observed on guests when low memory (first memory
@@ -528,6 +528,13 @@ int get_usable_memory_ranges(struct crash_mem **mem_ranges)
	if (ret)
		goto out;

	for (i = 0; i < crashk_cma_cnt; i++) {
		ret = add_mem_range(mem_ranges, crashk_cma_ranges[i].start,
				    crashk_cma_ranges[i].end - crashk_cma_ranges[i].start + 1);
		if (ret)
			goto out;
	}

	ret = add_rtas_mem_range(mem_ranges);
	if (ret)
		goto out;
@@ -546,6 +553,22 @@ int get_usable_memory_ranges(struct crash_mem **mem_ranges)
#endif /* CONFIG_KEXEC_FILE */

#ifdef CONFIG_CRASH_DUMP
static int crash_exclude_mem_range_guarded(struct crash_mem **mem_ranges,
					   unsigned long long mstart,
					   unsigned long long mend)
{
	struct crash_mem *tmem = *mem_ranges;

	/* Reallocate memory ranges if there is no space to split ranges */
	if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) {
		tmem = realloc_mem_ranges(mem_ranges);
		if (!tmem)
			return -ENOMEM;
	}

	return crash_exclude_mem_range(tmem, mstart, mend);
}

/**
 * get_crash_memory_ranges - Get crash memory ranges. This list includes
 *                           first/crashing kernel's memory regions that
@@ -557,7 +580,6 @@ int get_usable_memory_ranges(struct crash_mem **mem_ranges)
int get_crash_memory_ranges(struct crash_mem **mem_ranges)
{
	phys_addr_t base, end;
	struct crash_mem *tmem;
	u64 i;
	int ret;

@@ -582,18 +604,17 @@ int get_crash_memory_ranges(struct crash_mem **mem_ranges)
			sort_memory_ranges(*mem_ranges, true);
	}

	/* Reallocate memory ranges if there is no space to split ranges */
	tmem = *mem_ranges;
	if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) {
		tmem = realloc_mem_ranges(mem_ranges);
		if (!tmem)
	/* Exclude crashkernel region */
	ret = crash_exclude_mem_range_guarded(mem_ranges, crashk_res.start, crashk_res.end);
	if (ret)
		goto out;
	}

	/* Exclude crashkernel region */
	ret = crash_exclude_mem_range(tmem, crashk_res.start, crashk_res.end);
	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);
		if (ret)
			goto out;
	}

	/*
	 * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL