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

powerpc/kdump: Add support for crashkernel CMA reservation

Commit 35c18f2933c5 ("Add a new optional ",cma" suffix to the
crashkernel= command line option") and commit ab475510e042 ("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: Sourabh Jain <sourabhjain@linux.ibm.com>
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20251107080334.708028-1-sourabhjain@linux.ibm.com

authored by

Sourabh Jain and committed by
Madhavan Srinivasan
b4a96ab5 8127c4fd

+47 -14
+1 -1
Documentation/admin-guide/kernel-parameters.txt
··· 1013 1013 It will be ignored when crashkernel=X,high is not used 1014 1014 or memory reserved is below 4G. 1015 1015 crashkernel=size[KMG],cma 1016 - [KNL, X86] Reserve additional crash kernel memory from 1016 + [KNL, X86, ppc] Reserve additional crash kernel memory from 1017 1017 CMA. This reservation is usable by the first system's 1018 1018 userspace memory and kernel movable allocations (memory 1019 1019 balloon, zswap). Pages allocated from this memory range
+2
arch/powerpc/include/asm/kexec.h
··· 115 115 #ifdef CONFIG_CRASH_RESERVE 116 116 int __init overlaps_crashkernel(unsigned long start, unsigned long size); 117 117 extern void arch_reserve_crashkernel(void); 118 + extern void kdump_cma_reserve(void); 118 119 #else 119 120 static inline void arch_reserve_crashkernel(void) {} 120 121 static inline int overlaps_crashkernel(unsigned long start, unsigned long size) { return 0; } 122 + static inline void kdump_cma_reserve(void) { } 121 123 #endif 122 124 123 125 #if defined(CONFIG_CRASH_DUMP)
+3 -1
arch/powerpc/kernel/setup-common.c
··· 35 35 #include <linux/of_irq.h> 36 36 #include <linux/hugetlb.h> 37 37 #include <linux/pgtable.h> 38 + #include <asm/kexec.h> 38 39 #include <asm/io.h> 39 40 #include <asm/paca.h> 40 41 #include <asm/processor.h> ··· 996 995 initmem_init(); 997 996 998 997 /* 999 - * Reserve large chunks of memory for use by CMA for fadump, KVM and 998 + * Reserve large chunks of memory for use by CMA for kdump, fadump, KVM and 1000 999 * hugetlb. These must be called after initmem_init(), so that 1001 1000 * pageblock_order is initialised. 1002 1001 */ 1003 1002 fadump_cma_init(); 1003 + kdump_cma_reserve(); 1004 1004 kvm_cma_reserve(); 1005 1005 gigantic_hugetlb_cma_reserve(); 1006 1006
+9 -1
arch/powerpc/kexec/core.c
··· 59 59 60 60 #ifdef CONFIG_CRASH_RESERVE 61 61 62 + static unsigned long long crashk_cma_size; 63 + 62 64 static unsigned long long __init get_crash_base(unsigned long long crash_base) 63 65 { 64 66 ··· 112 110 113 111 /* use common parsing */ 114 112 ret = parse_crashkernel(boot_command_line, total_mem_sz, &crash_size, 115 - &crash_base, NULL, NULL, NULL); 113 + &crash_base, NULL, &crashk_cma_size, NULL); 116 114 117 115 if (ret) 118 116 return; ··· 130 128 } 131 129 132 130 reserve_crashkernel_generic(crash_size, crash_base, 0, false); 131 + } 132 + 133 + void __init kdump_cma_reserve(void) 134 + { 135 + if (crashk_cma_size) 136 + reserve_crashkernel_cma(crashk_cma_size); 133 137 } 134 138 135 139 int __init overlaps_crashkernel(unsigned long start, unsigned long size)
+32 -11
arch/powerpc/kexec/ranges.c
··· 515 515 */ 516 516 int get_usable_memory_ranges(struct crash_mem **mem_ranges) 517 517 { 518 - int ret; 518 + int ret, i; 519 519 520 520 /* 521 521 * Early boot failure observed on guests when low memory (first memory ··· 527 527 ret = add_mem_range(mem_ranges, 0, crashk_res.end + 1); 528 528 if (ret) 529 529 goto out; 530 + 531 + for (i = 0; i < crashk_cma_cnt; i++) { 532 + ret = add_mem_range(mem_ranges, crashk_cma_ranges[i].start, 533 + crashk_cma_ranges[i].end - crashk_cma_ranges[i].start + 1); 534 + if (ret) 535 + goto out; 536 + } 530 537 531 538 ret = add_rtas_mem_range(mem_ranges); 532 539 if (ret) ··· 553 546 #endif /* CONFIG_KEXEC_FILE */ 554 547 555 548 #ifdef CONFIG_CRASH_DUMP 549 + static int crash_exclude_mem_range_guarded(struct crash_mem **mem_ranges, 550 + unsigned long long mstart, 551 + unsigned long long mend) 552 + { 553 + struct crash_mem *tmem = *mem_ranges; 554 + 555 + /* Reallocate memory ranges if there is no space to split ranges */ 556 + if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) { 557 + tmem = realloc_mem_ranges(mem_ranges); 558 + if (!tmem) 559 + return -ENOMEM; 560 + } 561 + 562 + return crash_exclude_mem_range(tmem, mstart, mend); 563 + } 564 + 556 565 /** 557 566 * get_crash_memory_ranges - Get crash memory ranges. This list includes 558 567 * first/crashing kernel's memory regions that ··· 580 557 int get_crash_memory_ranges(struct crash_mem **mem_ranges) 581 558 { 582 559 phys_addr_t base, end; 583 - struct crash_mem *tmem; 584 560 u64 i; 585 561 int ret; 586 562 ··· 604 582 sort_memory_ranges(*mem_ranges, true); 605 583 } 606 584 607 - /* Reallocate memory ranges if there is no space to split ranges */ 608 - tmem = *mem_ranges; 609 - if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) { 610 - tmem = realloc_mem_ranges(mem_ranges); 611 - if (!tmem) 612 - goto out; 613 - } 614 - 615 585 /* Exclude crashkernel region */ 616 - ret = crash_exclude_mem_range(tmem, crashk_res.start, crashk_res.end); 586 + ret = crash_exclude_mem_range_guarded(mem_ranges, crashk_res.start, crashk_res.end); 617 587 if (ret) 618 588 goto out; 589 + 590 + for (i = 0; i < crashk_cma_cnt; ++i) { 591 + ret = crash_exclude_mem_range_guarded(mem_ranges, crashk_cma_ranges[i].start, 592 + crashk_cma_ranges[i].end); 593 + if (ret) 594 + goto out; 595 + } 619 596 620 597 /* 621 598 * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL