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

Configure Feed

Select the types of activity you want to include in your feed.

crash_core: add generic function to do reservation

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.

Link: https://lkml.kernel.org/r/20230914033142.676708-5-bhe@redhat.com
Signed-off-by: Baoquan He <bhe@redhat.com>
Reviewed-by: Zhen Lei <thunder.leizhen@huawei.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Chen Jiahao <chenjiahao16@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Baoquan He and committed by
Andrew Morton
0ab97169 70916e9c

+134 -1
+28
include/linux/crash_core.h
··· 93 93 int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, 94 94 unsigned long long *crash_size, unsigned long long *crash_base); 95 95 96 + #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION 97 + #ifndef DEFAULT_CRASH_KERNEL_LOW_SIZE 98 + #define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20) 99 + #endif 100 + #ifndef CRASH_ALIGN 101 + #define CRASH_ALIGN SZ_2M 102 + #endif 103 + #ifndef CRASH_ADDR_LOW_MAX 104 + #define CRASH_ADDR_LOW_MAX SZ_4G 105 + #endif 106 + #ifndef CRASH_ADDR_HIGH_MAX 107 + #define CRASH_ADDR_HIGH_MAX memblock_end_of_DRAM() 108 + #endif 109 + 110 + void __init reserve_crashkernel_generic(char *cmdline, 111 + unsigned long long crash_size, 112 + unsigned long long crash_base, 113 + unsigned long long crash_low_size, 114 + bool high); 115 + #else 116 + static inline void __init reserve_crashkernel_generic(char *cmdline, 117 + unsigned long long crash_size, 118 + unsigned long long crash_base, 119 + unsigned long long crash_low_size, 120 + bool high) 121 + {} 122 + #endif 123 + 96 124 /* Alignment required for elf header segment */ 97 125 #define ELF_CORE_HEADER_ALIGN 4096 98 126
+106 -1
kernel/crash_core.c
··· 5 5 */ 6 6 7 7 #include <linux/buildid.h> 8 - #include <linux/crash_core.h> 9 8 #include <linux/init.h> 10 9 #include <linux/utsname.h> 11 10 #include <linux/vmalloc.h> ··· 12 13 #include <linux/kexec.h> 13 14 #include <linux/memory.h> 14 15 #include <linux/cpuhotplug.h> 16 + #include <linux/memblock.h> 17 + #include <linux/kexec.h> 18 + #include <linux/kmemleak.h> 15 19 16 20 #include <asm/page.h> 17 21 #include <asm/sections.h> ··· 361 359 return 0; 362 360 } 363 361 early_param("crashkernel", parse_crashkernel_dummy); 362 + 363 + #ifdef CONFIG_ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION 364 + static int __init reserve_crashkernel_low(unsigned long long low_size) 365 + { 366 + #ifdef CONFIG_64BIT 367 + unsigned long long low_base; 368 + 369 + low_base = memblock_phys_alloc_range(low_size, CRASH_ALIGN, 0, CRASH_ADDR_LOW_MAX); 370 + if (!low_base) { 371 + pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size); 372 + return -ENOMEM; 373 + } 374 + 375 + pr_info("crashkernel low memory reserved: 0x%08llx - 0x%08llx (%lld MB)\n", 376 + low_base, low_base + low_size, low_size >> 20); 377 + 378 + crashk_low_res.start = low_base; 379 + crashk_low_res.end = low_base + low_size - 1; 380 + insert_resource(&iomem_resource, &crashk_low_res); 381 + #endif 382 + return 0; 383 + } 384 + 385 + void __init reserve_crashkernel_generic(char *cmdline, 386 + unsigned long long crash_size, 387 + unsigned long long crash_base, 388 + unsigned long long crash_low_size, 389 + bool high) 390 + { 391 + unsigned long long search_end = CRASH_ADDR_LOW_MAX, search_base = 0; 392 + bool fixed_base = false; 393 + 394 + /* User specifies base address explicitly. */ 395 + if (crash_base) { 396 + fixed_base = true; 397 + search_base = crash_base; 398 + search_end = crash_base + crash_size; 399 + } else if (high) { 400 + search_base = CRASH_ADDR_LOW_MAX; 401 + search_end = CRASH_ADDR_HIGH_MAX; 402 + } 403 + 404 + retry: 405 + crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, 406 + search_base, search_end); 407 + if (!crash_base) { 408 + /* 409 + * For crashkernel=size[KMG]@offset[KMG], print out failure 410 + * message if can't reserve the specified region. 411 + */ 412 + if (fixed_base) { 413 + pr_warn("crashkernel reservation failed - memory is in use.\n"); 414 + return; 415 + } 416 + 417 + /* 418 + * For crashkernel=size[KMG], if the first attempt was for 419 + * low memory, fall back to high memory, the minimum required 420 + * low memory will be reserved later. 421 + */ 422 + if (!high && search_end == CRASH_ADDR_LOW_MAX) { 423 + search_end = CRASH_ADDR_HIGH_MAX; 424 + search_base = CRASH_ADDR_LOW_MAX; 425 + crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; 426 + goto retry; 427 + } 428 + 429 + /* 430 + * For crashkernel=size[KMG],high, if the first attempt was 431 + * for high memory, fall back to low memory. 432 + */ 433 + if (high && search_end == CRASH_ADDR_HIGH_MAX) { 434 + search_end = CRASH_ADDR_LOW_MAX; 435 + search_base = 0; 436 + goto retry; 437 + } 438 + pr_warn("cannot allocate crashkernel (size:0x%llx)\n", 439 + crash_size); 440 + return; 441 + } 442 + 443 + if ((crash_base > CRASH_ADDR_LOW_MAX) && 444 + crash_low_size && reserve_crashkernel_low(crash_low_size)) { 445 + memblock_phys_free(crash_base, crash_size); 446 + return; 447 + } 448 + 449 + pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", 450 + crash_base, crash_base + crash_size, crash_size >> 20); 451 + 452 + /* 453 + * The crashkernel memory will be removed from the kernel linear 454 + * map. Inform kmemleak so that it won't try to access it. 455 + */ 456 + kmemleak_ignore_phys(crash_base); 457 + if (crashk_low_res.end) 458 + kmemleak_ignore_phys(crashk_low_res.start); 459 + 460 + crashk_res.start = crash_base; 461 + crashk_res.end = crash_base + crash_size - 1; 462 + insert_resource(&iomem_resource, &crashk_res); 463 + } 464 + #endif 364 465 365 466 int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map, 366 467 void **addr, unsigned long *sz)