aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBernhard Walle <bwalle@suse.de>2008-06-26 15:54:08 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 07:16:18 -0400
commit32105f7fd8faa7bc3d101dcc3eabc0ae1ac375a7 (patch)
treeff6bcff32e3641b2c4c2c98c242dc4803eddf3f9 /arch
parentfd6493e16625b92a506fba13deda31c0be5f1cd4 (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.c70
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 */
432unsigned 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
425static inline unsigned long long get_total_mem(void) 453static 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
473static void __init reserve_crashkernel(void) 507static void __init reserve_crashkernel(void)