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 <b...@redhat.com>
> ---
>  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@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to