aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt13
-rw-r--r--arch/x86/kernel/setup.c24
-rw-r--r--include/linux/kexec.h2
-rw-r--r--kernel/kexec.c9
4 files changed, 41 insertions, 7 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index cff672da2486..709eb3edc6b2 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -603,9 +603,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
603 a memory unit (amount[KMG]). See also 603 a memory unit (amount[KMG]). See also
604 Documentation/kdump/kdump.txt for an example. 604 Documentation/kdump/kdump.txt for an example.
605 605
606 crashkernel_high=size[KMG]
607 [KNL, x86_64] range could be above 4G. Allow kernel
608 to allocate physical memory region from top, so could
609 be above 4G if system have more than 4G ram installed.
610 Otherwise memory region will be allocated below 4G, if
611 available.
612 It will be ignored if crashkernel=X is specified.
606 crashkernel_low=size[KMG] 613 crashkernel_low=size[KMG]
607 [KNL, x86_64] range under 4G. When crashkernel= is 614 [KNL, x86_64] range under 4G. When crashkernel_high= is
608 passed, kernel allocate physical memory region 615 passed, kernel could allocate physical memory region
609 above 4G, that cause second kernel crash on system 616 above 4G, that cause second kernel crash on system
610 that require some amount of low memory, e.g. swiotlb 617 that require some amount of low memory, e.g. swiotlb
611 requires at least 64M+32K low memory. Kernel would 618 requires at least 64M+32K low memory. Kernel would
@@ -613,6 +620,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
613 This one let user to specify own low range under 4G 620 This one let user to specify own low range under 4G
614 for second kernel instead. 621 for second kernel instead.
615 0: to disable low allocation. 622 0: to disable low allocation.
623 It will be ignored when crashkernel_high=X is not used
624 or memory reserved is below 4G.
616 625
617 cs89x0_dma= [HW,NET] 626 cs89x0_dma= [HW,NET]
618 Format: <dma> 627 Format: <dma>
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 12349202cae7..a85a144f2052 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -507,11 +507,14 @@ static void __init memblock_x86_reserve_range_setup_data(void)
507/* 507/*
508 * Keep the crash kernel below this limit. On 32 bits earlier kernels 508 * Keep the crash kernel below this limit. On 32 bits earlier kernels
509 * would limit the kernel to the low 512 MiB due to mapping restrictions. 509 * would limit the kernel to the low 512 MiB due to mapping restrictions.
510 * On 64bit, old kexec-tools need to under 896MiB.
510 */ 511 */
511#ifdef CONFIG_X86_32 512#ifdef CONFIG_X86_32
512# define CRASH_KERNEL_ADDR_MAX (512 << 20) 513# define CRASH_KERNEL_ADDR_LOW_MAX (512 << 20)
514# define CRASH_KERNEL_ADDR_HIGH_MAX (512 << 20)
513#else 515#else
514# define CRASH_KERNEL_ADDR_MAX MAXMEM 516# define CRASH_KERNEL_ADDR_LOW_MAX (896UL<<20)
517# define CRASH_KERNEL_ADDR_HIGH_MAX MAXMEM
515#endif 518#endif
516 519
517static void __init reserve_crashkernel_low(void) 520static void __init reserve_crashkernel_low(void)
@@ -525,6 +528,7 @@ static void __init reserve_crashkernel_low(void)
525 int ret; 528 int ret;
526 529
527 total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); 530 total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
531 /* crashkernel_low=YM */
528 ret = parse_crashkernel_low(boot_command_line, total_low_mem, 532 ret = parse_crashkernel_low(boot_command_line, total_low_mem,
529 &low_size, &base); 533 &low_size, &base);
530 if (ret != 0) { 534 if (ret != 0) {
@@ -569,14 +573,22 @@ static void __init reserve_crashkernel(void)
569 const unsigned long long alignment = 16<<20; /* 16M */ 573 const unsigned long long alignment = 16<<20; /* 16M */
570 unsigned long long total_mem; 574 unsigned long long total_mem;
571 unsigned long long crash_size, crash_base; 575 unsigned long long crash_size, crash_base;
576 bool high = false;
572 int ret; 577 int ret;
573 578
574 total_mem = memblock_phys_mem_size(); 579 total_mem = memblock_phys_mem_size();
575 580
581 /* crashkernel=XM */
576 ret = parse_crashkernel(boot_command_line, total_mem, 582 ret = parse_crashkernel(boot_command_line, total_mem,
577 &crash_size, &crash_base); 583 &crash_size, &crash_base);
578 if (ret != 0 || crash_size <= 0) 584 if (ret != 0 || crash_size <= 0) {
579 return; 585 /* crashkernel_high=XM */
586 ret = parse_crashkernel_high(boot_command_line, total_mem,
587 &crash_size, &crash_base);
588 if (ret != 0 || crash_size <= 0)
589 return;
590 high = true;
591 }
580 592
581 /* 0 means: find the address automatically */ 593 /* 0 means: find the address automatically */
582 if (crash_base <= 0) { 594 if (crash_base <= 0) {
@@ -584,7 +596,9 @@ static void __init reserve_crashkernel(void)
584 * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX 596 * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
585 */ 597 */
586 crash_base = memblock_find_in_range(alignment, 598 crash_base = memblock_find_in_range(alignment,
587 CRASH_KERNEL_ADDR_MAX, crash_size, alignment); 599 high ? CRASH_KERNEL_ADDR_HIGH_MAX :
600 CRASH_KERNEL_ADDR_LOW_MAX,
601 crash_size, alignment);
588 602
589 if (!crash_base) { 603 if (!crash_base) {
590 pr_info("crashkernel reservation failed - No suitable area found.\n"); 604 pr_info("crashkernel reservation failed - No suitable area found.\n");
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d2e6927bbaae..d78d28a733b1 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -200,6 +200,8 @@ extern size_t vmcoreinfo_max_size;
200 200
201int __init parse_crashkernel(char *cmdline, unsigned long long system_ram, 201int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
202 unsigned long long *crash_size, unsigned long long *crash_base); 202 unsigned long long *crash_size, unsigned long long *crash_base);
203int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
204 unsigned long long *crash_size, unsigned long long *crash_base);
203int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, 205int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
204 unsigned long long *crash_size, unsigned long long *crash_base); 206 unsigned long long *crash_size, unsigned long long *crash_base);
205int crash_shrink_memory(unsigned long new_size); 207int crash_shrink_memory(unsigned long new_size);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index bddd3d7a74b6..1b2f73f5f9b9 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1422,6 +1422,15 @@ int __init parse_crashkernel(char *cmdline,
1422 "crashkernel="); 1422 "crashkernel=");
1423} 1423}
1424 1424
1425int __init parse_crashkernel_high(char *cmdline,
1426 unsigned long long system_ram,
1427 unsigned long long *crash_size,
1428 unsigned long long *crash_base)
1429{
1430 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1431 "crashkernel_high=");
1432}
1433
1425int __init parse_crashkernel_low(char *cmdline, 1434int __init parse_crashkernel_low(char *cmdline,
1426 unsigned long long system_ram, 1435 unsigned long long system_ram,
1427 unsigned long long *crash_size, 1436 unsigned long long *crash_size,