diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 13 | ||||
-rw-r--r-- | arch/x86/kernel/setup.c | 24 | ||||
-rw-r--r-- | include/linux/kexec.h | 2 | ||||
-rw-r--r-- | kernel/kexec.c | 9 |
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 | ||
517 | static void __init reserve_crashkernel_low(void) | 520 | static 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 | ||
201 | int __init parse_crashkernel(char *cmdline, unsigned long long system_ram, | 201 | int __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); |
203 | int parse_crashkernel_high(char *cmdline, unsigned long long system_ram, | ||
204 | unsigned long long *crash_size, unsigned long long *crash_base); | ||
203 | int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, | 205 | int 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); |
205 | int crash_shrink_memory(unsigned long new_size); | 207 | int 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 | ||
1425 | int __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 | |||
1425 | int __init parse_crashkernel_low(char *cmdline, | 1434 | int __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, |