diff options
Diffstat (limited to 'arch/x86/kernel/setup.c')
-rw-r--r-- | arch/x86/kernel/setup.c | 45 |
1 files changed, 37 insertions, 8 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 90d8cc930f5e..fae9134a2de9 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) |
@@ -521,19 +524,35 @@ static void __init reserve_crashkernel_low(void) | |||
521 | unsigned long long low_base = 0, low_size = 0; | 524 | unsigned long long low_base = 0, low_size = 0; |
522 | unsigned long total_low_mem; | 525 | unsigned long total_low_mem; |
523 | unsigned long long base; | 526 | unsigned long long base; |
527 | bool auto_set = false; | ||
524 | int ret; | 528 | int ret; |
525 | 529 | ||
526 | total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); | 530 | total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); |
531 | /* crashkernel=Y,low */ | ||
527 | ret = parse_crashkernel_low(boot_command_line, total_low_mem, | 532 | ret = parse_crashkernel_low(boot_command_line, total_low_mem, |
528 | &low_size, &base); | 533 | &low_size, &base); |
529 | if (ret != 0 || low_size <= 0) | 534 | if (ret != 0) { |
530 | return; | 535 | /* |
536 | * two parts from lib/swiotlb.c: | ||
537 | * swiotlb size: user specified with swiotlb= or default. | ||
538 | * swiotlb overflow buffer: now is hardcoded to 32k. | ||
539 | * We round it to 8M for other buffers that | ||
540 | * may need to stay low too. | ||
541 | */ | ||
542 | low_size = swiotlb_size_or_default() + (8UL<<20); | ||
543 | auto_set = true; | ||
544 | } else { | ||
545 | /* passed with crashkernel=0,low ? */ | ||
546 | if (!low_size) | ||
547 | return; | ||
548 | } | ||
531 | 549 | ||
532 | low_base = memblock_find_in_range(low_size, (1ULL<<32), | 550 | low_base = memblock_find_in_range(low_size, (1ULL<<32), |
533 | low_size, alignment); | 551 | low_size, alignment); |
534 | 552 | ||
535 | if (!low_base) { | 553 | if (!low_base) { |
536 | pr_info("crashkernel low reservation failed - No suitable area found.\n"); | 554 | if (!auto_set) |
555 | pr_info("crashkernel low reservation failed - No suitable area found.\n"); | ||
537 | 556 | ||
538 | return; | 557 | return; |
539 | } | 558 | } |
@@ -554,14 +573,22 @@ static void __init reserve_crashkernel(void) | |||
554 | const unsigned long long alignment = 16<<20; /* 16M */ | 573 | const unsigned long long alignment = 16<<20; /* 16M */ |
555 | unsigned long long total_mem; | 574 | unsigned long long total_mem; |
556 | unsigned long long crash_size, crash_base; | 575 | unsigned long long crash_size, crash_base; |
576 | bool high = false; | ||
557 | int ret; | 577 | int ret; |
558 | 578 | ||
559 | total_mem = memblock_phys_mem_size(); | 579 | total_mem = memblock_phys_mem_size(); |
560 | 580 | ||
581 | /* crashkernel=XM */ | ||
561 | ret = parse_crashkernel(boot_command_line, total_mem, | 582 | ret = parse_crashkernel(boot_command_line, total_mem, |
562 | &crash_size, &crash_base); | 583 | &crash_size, &crash_base); |
563 | if (ret != 0 || crash_size <= 0) | 584 | if (ret != 0 || crash_size <= 0) { |
564 | return; | 585 | /* crashkernel=X,high */ |
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 | } | ||
565 | 592 | ||
566 | /* 0 means: find the address automatically */ | 593 | /* 0 means: find the address automatically */ |
567 | if (crash_base <= 0) { | 594 | if (crash_base <= 0) { |
@@ -569,7 +596,9 @@ static void __init reserve_crashkernel(void) | |||
569 | * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX | 596 | * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX |
570 | */ | 597 | */ |
571 | crash_base = memblock_find_in_range(alignment, | 598 | crash_base = memblock_find_in_range(alignment, |
572 | CRASH_KERNEL_ADDR_MAX, crash_size, alignment); | 599 | high ? CRASH_KERNEL_ADDR_HIGH_MAX : |
600 | CRASH_KERNEL_ADDR_LOW_MAX, | ||
601 | crash_size, alignment); | ||
573 | 602 | ||
574 | if (!crash_base) { | 603 | if (!crash_base) { |
575 | pr_info("crashkernel reservation failed - No suitable area found.\n"); | 604 | pr_info("crashkernel reservation failed - No suitable area found.\n"); |