On 2023/8/29 20:16, Baoquan He wrote: > In architecture like x86_64, arm64 and riscv, they have vast virtual > address space and usually have huge physical memory RAM. Their > crashkernel reservation doesn't have to be limited under 4G RAM, > but can be extended to the whole physical memory via crashkernel=,high > support. > > Now add function reserve_crashkernel_generic() to reserve crashkernel > memory if users specify any case of kernel pamameters, like > crashkernel=xM[@offset] or crashkernel=,high|low. > > This is preparation to simplify code of crashkernel=,high support > in architecutures. > > Signed-off-by: Baoquan He <bhe@xxxxxxxxxx> > --- > include/linux/crash_core.h | 34 ++++++++++-- > kernel/crash_core.c | 109 ++++++++++++++++++++++++++++++++++++- > 2 files changed, 136 insertions(+), 7 deletions(-) > > diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h > index 85260bf4a734..2f732493e922 100644 > --- a/include/linux/crash_core.h > +++ b/include/linux/crash_core.h > @@ -77,12 +77,6 @@ Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type, > void *data, size_t data_len); > void final_note(Elf_Word *buf); > > -#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION > -#ifndef DEFAULT_CRASH_KERNEL_LOW_SIZE > -#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20) > -#endif > -#endif > - > int __init parse_crashkernel(char *cmdline, unsigned long long system_ram, > unsigned long long *crash_size, unsigned long long *crash_base, > unsigned long long *low_size, bool *high); > @@ -91,4 +85,32 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram, > int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, > unsigned long long *crash_size, unsigned long long *crash_base); > > +#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION > +#ifndef DEFAULT_CRASH_KERNEL_LOW_SIZE > +#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20) > +#endif > +#ifndef CRASH_ALIGN > +#define CRASH_ALIGN SZ_2M > +#endif > +#ifndef CRASH_ADDR_LOW_MAX > +#define CRASH_ADDR_LOW_MAX SZ_4G > +#endif > +#ifndef CRASH_ADDR_HIGH_MAX > +#define CRASH_ADDR_HIGH_MAX memblock_end_of_DRAM() > +#endif > + > +void __init reserve_crashkernel_generic(char *cmdline, > + unsigned long long crash_size, > + unsigned long long crash_base, > + unsigned long long crash_low_size, > + bool high); > +#else > +static inline void __init reserve_crashkernel_generic(char *cmdline, > + unsigned long long crash_size, > + unsigned long long crash_base, > + unsigned long long crash_low_size, > + bool high) > +{} > +#endif > + > #endif /* LINUX_CRASH_CORE_H */ > diff --git a/kernel/crash_core.c b/kernel/crash_core.c > index 355b0ab5189c..6bc00cc390b5 100644 > --- a/kernel/crash_core.c > +++ b/kernel/crash_core.c > @@ -5,11 +5,13 @@ > */ > > #include <linux/buildid.h> > -#include <linux/crash_core.h> > #include <linux/init.h> > #include <linux/utsname.h> > #include <linux/vmalloc.h> > #include <linux/sizes.h> > +#include <linux/memblock.h> > +#include <linux/kexec.h> > +#include <linux/kmemleak.h> > > #include <asm/page.h> > #include <asm/sections.h> > @@ -349,6 +351,111 @@ static int __init parse_crashkernel_dummy(char *arg) > } > early_param("crashkernel", parse_crashkernel_dummy); > > +#ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION > +static int __init reserve_crashkernel_low(unsigned long long low_size) > +{ > +#ifdef CONFIG_64BIT > + unsigned long long low_base; > + > + low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX); > + if (!low_base) { > + pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size); > + return -ENOMEM; > + } > + > + pr_info("crashkernel low memory reserved: 0x%08llx - 0x%08llx (%lld MB)\n", > + low_base, low_base + low_size, low_size >> 20); > + > + crashk_low_res.start = low_base; > + crashk_low_res.end = low_base + low_size - 1; > + insert_resource(&iomem_resource, &crashk_low_res); > +#endif > + return 0; > +} > + > +void __init reserve_crashkernel_generic(char *cmdline, > + unsigned long long crash_size, > + unsigned long long crash_base, > + unsigned long long crash_low_size, > + bool high) > +{ > + unsigned long long search_end = CRASH_ADDR_LOW_MAX, search_base = 0; > + bool fixed_base = false; > + > + /* User specifies base address explicitly. */ > + if (crash_base) { > + fixed_base = true; > + search_base = crash_base; > + search_end = crash_base + crash_size; > + } > + > + if (high) { It might be a little clearer to use "else if (high) {" > + search_base = CRASH_ADDR_LOW_MAX; > + search_end = CRASH_ADDR_HIGH_MAX; > + } > + > +retry: > + crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, > + search_base, search_end); > + if (!crash_base) { > + /* > + * For crashkernel=size[KMG]@offset[KMG], print out failure > + * message if can't reserve the specified region. > + */ > + if (fixed_base) { > + pr_warn("crashkernel reservation failed - memory is in use.\n"); > + return; > + } > + > + /* > + * For crashkernel=size[KMG], if the first attempt was for > + * low memory, fall back to high memory, the minimum required > + * low memory will be reserved later. > + */ > + if (!high && search_end == CRASH_ADDR_LOW_MAX) { > + search_end = CRASH_ADDR_HIGH_MAX; > + search_base = CRASH_ADDR_LOW_MAX; > + crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; > + goto retry; > + } > + > + /* > + * For crashkernel=size[KMG],high, if the first attempt was > + * for high memory, fall back to low memory. > + */ > + if (high && search_end == CRASH_ADDR_HIGH_MAX) { > + search_end = CRASH_ADDR_LOW_MAX; > + search_base = 0; > + goto retry; > + } > + pr_warn("cannot allocate crashkernel (size:0x%llx)\n", > + crash_size); > + return; > + } > + > + if ((crash_base > CRASH_ADDR_LOW_MAX) && > + crash_low_size && reserve_crashkernel_low(crash_low_size)) { > + memblock_phys_free(crash_base, crash_size); > + return; > + } > + > + pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", > + crash_base, crash_base + crash_size, crash_size >> 20); > + > + /* > + * The crashkernel memory will be removed from the kernel linear > + * map. Inform kmemleak so that it won't try to access it. > + */ > + kmemleak_ignore_phys(crash_base); > + if (crashk_low_res.end) > + kmemleak_ignore_phys(crashk_low_res.start); > + > + crashk_res.start = crash_base; > + crashk_res.end = crash_base + crash_size - 1; > + insert_resource(&iomem_resource, &crashk_res); > +} > +#endif > + > Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type, > void *data, size_t data_len) > { > -- Regards, Zhen Lei _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec