diff options
author | Bernhard Walle <bwalle@suse.de> | 2008-06-26 15:54:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-08 07:16:18 -0400 |
commit | 32105f7fd8faa7bc3d101dcc3eabc0ae1ac375a7 (patch) | |
tree | ff6bcff32e3641b2c4c2c98c242dc4803eddf3f9 /arch | |
parent | fd6493e16625b92a506fba13deda31c0be5f1cd4 (diff) |
x86: find offset for crashkernel reservation automatically
This patch removes the need of the crashkernel=...@offset parameter to define
a fixed offset for crashkernel reservation. That feature can be used together
with a relocatable kernel where the kexec-tools relocate the kernel and
get the actual offset from /proc/iomem.
The use case is a kernel where the .text+.data+.bss is after 16M physical
memory (debug kernel with lockdep on x86_64 can cause that) which caused a
major pain in autoconfiguration in our distribution.
Also, that patch unifies crashdump architectures a bit since IA64 has
that semantics from the very beginning of the kdump port.
Signed-off-by: Bernhard Walle <bwalle@suse.de>
Cc: vgoyal@redhat.com
Cc: Bernhard Walle <bwalle@suse.de>
Cc: kexec@lists.infradead.org
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/setup.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 2ca12d4c88fb..b3469898717e 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -422,6 +422,34 @@ static void __init reserve_setup_data(void) | |||
422 | */ | 422 | */ |
423 | 423 | ||
424 | #ifdef CONFIG_KEXEC | 424 | #ifdef CONFIG_KEXEC |
425 | |||
426 | /** | ||
427 | * Reserve @size bytes of crashkernel memory at any suitable offset. | ||
428 | * | ||
429 | * @size: Size of the crashkernel memory to reserve. | ||
430 | * Returns the base address on success, and -1ULL on failure. | ||
431 | */ | ||
432 | unsigned long long find_and_reserve_crashkernel(unsigned long long size) | ||
433 | { | ||
434 | const unsigned long long alignment = 16<<20; /* 16M */ | ||
435 | unsigned long long start = 0LL; | ||
436 | |||
437 | while (1) { | ||
438 | int ret; | ||
439 | |||
440 | start = find_e820_area(start, ULONG_MAX, size, alignment); | ||
441 | if (start == -1ULL) | ||
442 | return start; | ||
443 | |||
444 | /* try to reserve it */ | ||
445 | ret = reserve_bootmem_generic(start, size, BOOTMEM_EXCLUSIVE); | ||
446 | if (ret >= 0) | ||
447 | return start; | ||
448 | |||
449 | start += alignment; | ||
450 | } | ||
451 | } | ||
452 | |||
425 | static inline unsigned long long get_total_mem(void) | 453 | static inline unsigned long long get_total_mem(void) |
426 | { | 454 | { |
427 | unsigned long long total; | 455 | unsigned long long total; |
@@ -444,30 +472,36 @@ static void __init reserve_crashkernel(void) | |||
444 | 472 | ||
445 | ret = parse_crashkernel(boot_command_line, total_mem, | 473 | ret = parse_crashkernel(boot_command_line, total_mem, |
446 | &crash_size, &crash_base); | 474 | &crash_size, &crash_base); |
447 | if (ret == 0 && crash_size > 0) { | 475 | if (ret != 0 || crash_size <= 0) |
448 | if (crash_base <= 0) { | 476 | return; |
449 | printk(KERN_INFO "crashkernel reservation failed - " | 477 | |
450 | "you have to specify a base address\n"); | 478 | /* 0 means: find the address automatically */ |
479 | if (crash_base <= 0) { | ||
480 | crash_base = find_and_reserve_crashkernel(crash_size); | ||
481 | if (crash_base == -1ULL) { | ||
482 | pr_info("crashkernel reservation failed. " | ||
483 | "No suitable area found.\n"); | ||
451 | return; | 484 | return; |
452 | } | 485 | } |
453 | 486 | } else { | |
454 | if (reserve_bootmem_generic(crash_base, crash_size, | 487 | ret = reserve_bootmem_generic(crash_base, crash_size, |
455 | BOOTMEM_EXCLUSIVE) < 0) { | 488 | BOOTMEM_EXCLUSIVE); |
456 | printk(KERN_INFO "crashkernel reservation failed - " | 489 | if (ret < 0) { |
457 | "memory is in use\n"); | 490 | pr_info("crashkernel reservation failed - " |
491 | "memory is in use\n"); | ||
458 | return; | 492 | return; |
459 | } | 493 | } |
494 | } | ||
460 | 495 | ||
461 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " | 496 | printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " |
462 | "for crashkernel (System RAM: %ldMB)\n", | 497 | "for crashkernel (System RAM: %ldMB)\n", |
463 | (unsigned long)(crash_size >> 20), | 498 | (unsigned long)(crash_size >> 20), |
464 | (unsigned long)(crash_base >> 20), | 499 | (unsigned long)(crash_base >> 20), |
465 | (unsigned long)(total_mem >> 20)); | 500 | (unsigned long)(total_mem >> 20)); |
466 | 501 | ||
467 | crashk_res.start = crash_base; | 502 | crashk_res.start = crash_base; |
468 | crashk_res.end = crash_base + crash_size - 1; | 503 | crashk_res.end = crash_base + crash_size - 1; |
469 | insert_resource(&iomem_resource, &crashk_res); | 504 | insert_resource(&iomem_resource, &crashk_res); |
470 | } | ||
471 | } | 505 | } |
472 | #else | 506 | #else |
473 | static void __init reserve_crashkernel(void) | 507 | static void __init reserve_crashkernel(void) |