[PATCH 10/12] powerpc: Parse crashkernel= parameter in first kernel

Michael Ellerman michael at ellerman.id.au
Tue Nov 8 00:07:12 EST 2005


This patch adds code to parse and setup the crash kernel resource in the
first kernel.

FIXME: PPC64 should ignore the @x, we always run at 32 MB.

Patch-by: Haren Myneni <haren at us.ibm.com>

 arch/powerpc/kernel/prom.c      |   16 +++++++++++
 arch/powerpc/kernel/prom_init.c |   55 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

Index: kexec/arch/powerpc/kernel/prom_init.c
===================================================================
--- kexec.orig/arch/powerpc/kernel/prom_init.c
+++ kexec/arch/powerpc/kernel/prom_init.c
@@ -44,6 +44,7 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
+#include <asm/kexec.h>
 
 #ifdef CONFIG_LOGO_LINUX_CLUT224
 #include <linux/linux_logo.h>
@@ -190,6 +191,12 @@ static unsigned long __initdata alloc_bo
 static unsigned long __initdata rmo_top;
 static unsigned long __initdata ram_top;
 
+#ifdef CONFIG_KEXEC
+static unsigned long __initdata prom_crashk_base;
+static unsigned long __initdata prom_crashk_size;
+#endif
+
+
 static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
 static int __initdata mem_reserve_cnt;
 
@@ -527,6 +534,31 @@ static void __init early_cmdline_parse(v
 		RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
 #endif
 	}
+
+#ifdef CONFIG_KEXEC
+       /*
+        * crashkernel=size at addr specifies the location to reserve for
+        * a crash kernel.
+        */
+       opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
+       if (opt) {
+               opt += 12;
+               RELOC(prom_crashk_size) =
+                       prom_memparse(opt, (const char **)&opt);
+               /* Align to 16 MB == size of large page */
+               RELOC(prom_crashk_size) =
+                       ALIGN(RELOC(prom_crashk_size), 0x1000000);
+               if (*opt == '@')  {
+                       opt++;
+                       RELOC(prom_crashk_base) =
+                               prom_memparse(opt, (const char **)&opt);
+                       RELOC(prom_crashk_base) =
+                               ALIGN(RELOC(prom_crashk_base), 0x1000000);
+               } else
+                       prom_printf("Error in 'crashkernel='\n");
+	}
+#endif
+
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -948,6 +980,13 @@ static void __init prom_init_mem(void)
 	prom_printf("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
 	prom_printf("  rmo_top      : %x\n", RELOC(rmo_top));
 	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
+#ifdef CONFIG_KEXEC
+	if (RELOC(prom_crashk_base)) {
+		prom_printf("  crashk_base : %x\n",  RELOC(prom_crashk_base));
+        	prom_printf("  crashk_size : %x\n", RELOC(prom_crashk_size));
+	}
+#endif
+
 }
 
 
@@ -2015,6 +2054,10 @@ unsigned long __init prom_init(unsigned 
 	 */
 	prom_init_mem();
 
+#ifdef CONFIG_KEXEC
+       if (RELOC(prom_crashk_base))
+               reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
+#endif
 	/*
 	 * Determine which cpu is actually running right _now_
 	 */
@@ -2069,6 +2112,18 @@ unsigned long __init prom_init(unsigned 
 	}
 #endif
 
+#ifdef CONFIG_KEXEC
+       if (RELOC(prom_crashk_base)) {
+               prom_setprop(_prom->chosen, "linux,crashkernel-base",
+                       PTRRELOC(&prom_crashk_base),
+                       sizeof(RELOC(prom_crashk_base)));
+               prom_setprop(_prom->chosen, "linux,crashkernel-size",
+                       PTRRELOC(&prom_crashk_size),
+                       sizeof(RELOC(prom_crashk_size)));
+       }
+#endif
+
+
 	/*
 	 * Fixup any known bugs in the device-tree
 	 */
Index: kexec/arch/powerpc/kernel/prom.c
===================================================================
--- kexec.orig/arch/powerpc/kernel/prom.c
+++ kexec/arch/powerpc/kernel/prom.c
@@ -29,6 +29,7 @@
 #include <linux/initrd.h>
 #include <linux/bitops.h>
 #include <linux/module.h>
+#include <linux/kexec.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -1221,6 +1222,17 @@ static int __init early_init_dt_scan_cho
 	}
 #endif /* CONFIG_PPC_RTAS */
 
+#ifdef CONFIG_KEXEC
+       lprop = (u64*)get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
+       if (lprop)
+               crashk_res.start = *lprop;
+
+       lprop = (u64*)get_flat_dt_prop(node, "linux,crashkernel-size", NULL);
+       if (lprop)
+               crashk_res.end = crashk_res.start + *lprop - 1;
+
+#endif
+
 	/* break now */
 	return 1;
 }
@@ -1362,6 +1374,10 @@ void __init early_init_devtree(void *par
 	lmb_reserve(__pa(KERNELBASE), __pa(klimit) - __pa(KERNELBASE));
 #ifdef CONFIG_CRASH_DUMP
 	lmb_reserve(0, KDUMP_BACKUP_LIMIT);
+	if (crashk_res.end > 0) {
+		lmb.rmo_size = _ALIGN_UP(crashk_res.end - crashk_res.start + 1,
+				PAGE_SIZE);
+	}
 #endif
 	early_reserve_mem();
 



More information about the Linuxppc64-dev mailing list