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 29258c75a2f3..a5d550f2fa6e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -505,11 +505,14 @@ static void __init memblock_x86_reserve_range_setup_data(void) | |||
505 | /* | 505 | /* |
506 | * Keep the crash kernel below this limit. On 32 bits earlier kernels | 506 | * Keep the crash kernel below this limit. On 32 bits earlier kernels |
507 | * would limit the kernel to the low 512 MiB due to mapping restrictions. | 507 | * would limit the kernel to the low 512 MiB due to mapping restrictions. |
508 | * On 64bit, old kexec-tools need to under 896MiB. | ||
508 | */ | 509 | */ |
509 | #ifdef CONFIG_X86_32 | 510 | #ifdef CONFIG_X86_32 |
510 | # define CRASH_KERNEL_ADDR_MAX (512 << 20) | 511 | # define CRASH_KERNEL_ADDR_LOW_MAX (512 << 20) |
512 | # define CRASH_KERNEL_ADDR_HIGH_MAX (512 << 20) | ||
511 | #else | 513 | #else |
512 | # define CRASH_KERNEL_ADDR_MAX MAXMEM | 514 | # define CRASH_KERNEL_ADDR_LOW_MAX (896UL<<20) |
515 | # define CRASH_KERNEL_ADDR_HIGH_MAX MAXMEM | ||
513 | #endif | 516 | #endif |
514 | 517 | ||
515 | static void __init reserve_crashkernel_low(void) | 518 | static void __init reserve_crashkernel_low(void) |
@@ -519,19 +522,35 @@ static void __init reserve_crashkernel_low(void) | |||
519 | unsigned long long low_base = 0, low_size = 0; | 522 | unsigned long long low_base = 0, low_size = 0; |
520 | unsigned long total_low_mem; | 523 | unsigned long total_low_mem; |
521 | unsigned long long base; | 524 | unsigned long long base; |
525 | bool auto_set = false; | ||
522 | int ret; | 526 | int ret; |
523 | 527 | ||
524 | total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); | 528 | total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); |
529 | /* crashkernel=Y,low */ | ||
525 | ret = parse_crashkernel_low(boot_command_line, total_low_mem, | 530 | ret = parse_crashkernel_low(boot_command_line, total_low_mem, |
526 | &low_size, &base); | 531 | &low_size, &base); |
527 | if (ret != 0 || low_size <= 0) | 532 | if (ret != 0) { |
528 | return; | 533 | /* |
534 | * two parts from lib/swiotlb.c: | ||
535 | * swiotlb size: user specified with swiotlb= or default. | ||
536 | * swiotlb overflow buffer: now is hardcoded to 32k. | ||
537 | * We round it to 8M for other buffers that | ||
538 | * may need to stay low too. | ||
539 | */ | ||
540 | low_size = swiotlb_size_or_default() + (8UL<<20); | ||
541 | auto_set = true; | ||
542 | } else { | ||
543 | /* passed with crashkernel=0,low ? */ | ||
544 | if (!low_size) | ||
545 | return; | ||
546 | } | ||
529 | 547 | ||
530 | low_base = memblock_find_in_range(low_size, (1ULL<<32), | 548 | low_base = memblock_find_in_range(low_size, (1ULL<<32), |
531 | low_size, alignment); | 549 | low_size, alignment); |
532 | 550 | ||
533 | if (!low_base) { | 551 | if (!low_base) { |
534 | pr_info("crashkernel low reservation failed - No suitable area found.\n"); | 552 | if (!auto_set) |
553 | pr_info("crashkernel low reservation failed - No suitable area found.\n"); | ||
535 | 554 | ||
536 | return; | 555 | return; |
537 | } | 556 | } |
@@ -552,14 +571,22 @@ static void __init reserve_crashkernel(void) | |||
552 | const unsigned long long alignment = 16<<20; /* 16M */ | 571 | const unsigned long long alignment = 16<<20; /* 16M */ |
553 | unsigned long long total_mem; | 572 | unsigned long long total_mem; |
554 | unsigned long long crash_size, crash_base; | 573 | unsigned long long crash_size, crash_base; |
574 | bool high = false; | ||
555 | int ret; | 575 | int ret; |
556 | 576 | ||
557 | total_mem = memblock_phys_mem_size(); | 577 | total_mem = memblock_phys_mem_size(); |
558 | 578 | ||
579 | /* crashkernel=XM */ | ||
559 | ret = parse_crashkernel(boot_command_line, total_mem, | 580 | ret = parse_crashkernel(boot_command_line, total_mem, |
560 | &crash_size, &crash_base); | 581 | &crash_size, &crash_base); |
561 | if (ret != 0 || crash_size <= 0) | 582 | if (ret != 0 || crash_size <= 0) { |
562 | return; | 583 | /* crashkernel=X,high */ |
584 | ret = parse_crashkernel_high(boot_command_line, total_mem, | ||
585 | &crash_size, &crash_base); | ||
586 | if (ret != 0 || crash_size <= 0) | ||
587 | return; | ||
588 | high = true; | ||
589 | } | ||
563 | 590 | ||
564 | /* 0 means: find the address automatically */ | 591 | /* 0 means: find the address automatically */ |
565 | if (crash_base <= 0) { | 592 | if (crash_base <= 0) { |
@@ -567,7 +594,9 @@ static void __init reserve_crashkernel(void) | |||
567 | * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX | 594 | * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX |
568 | */ | 595 | */ |
569 | crash_base = memblock_find_in_range(alignment, | 596 | crash_base = memblock_find_in_range(alignment, |
570 | CRASH_KERNEL_ADDR_MAX, crash_size, alignment); | 597 | high ? CRASH_KERNEL_ADDR_HIGH_MAX : |
598 | CRASH_KERNEL_ADDR_LOW_MAX, | ||
599 | crash_size, alignment); | ||
571 | 600 | ||
572 | if (!crash_base) { | 601 | if (!crash_base) { |
573 | pr_info("crashkernel reservation failed - No suitable area found.\n"); | 602 | pr_info("crashkernel reservation failed - No suitable area found.\n"); |