powerpc/kexec: Check crash_base for relocatable kernel
authorMilton Miller <miltonm@bga.com>
Fri, 2 Jan 2009 10:46:15 +0000 (10:46 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 13 Jan 2009 03:47:59 +0000 (14:47 +1100)
Enforce that the crash kernel region never overlaps the current kernel,
as it will be written directly on kexec load.

Also, default to the previous KDUMP_KERNELBASE if the start is 0.

Other architectures (x86, ia64) state that specifying the start address
0 (or omitting it) will result in the kernel allocating it.  Before the
relocatable patch in 2.6.28, powerpc would adjust any other start value
to the hardcoded KDUMP_KERNELBASE of 32M.

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/machine_kexec.c

index b3abebb7ee64641420fd81fd796b5c13282dccbf..d59e2b1bdcbac7f1f64cf9d7289092345323f315 100644 (file)
@@ -93,10 +93,35 @@ void __init reserve_crashkernel(void)
                                KDUMP_KERNELBASE);
 
        crashk_res.start = KDUMP_KERNELBASE;
+#else
+       if (!crashk_res.start) {
+               /*
+                * unspecified address, choose a region of specified size
+                * can overlap with initrd (ignoring corruption when retained)
+                * ppc64 requires kernel and some stacks to be in first segemnt
+                */
+               crashk_res.start = KDUMP_KERNELBASE;
+       }
+
+       crash_base = PAGE_ALIGN(crashk_res.start);
+       if (crash_base != crashk_res.start) {
+               printk("Crash kernel base must be aligned to 0x%lx\n",
+                               PAGE_SIZE);
+               crashk_res.start = crash_base;
+       }
+
 #endif
        crash_size = PAGE_ALIGN(crash_size);
        crashk_res.end = crashk_res.start + crash_size - 1;
 
+       /* The crash region must not overlap the current kernel */
+       if (overlaps_crashkernel(__pa(_stext), _end - _stext)) {
+               printk(KERN_WARNING
+                       "Crash kernel can not overlap current kernel\n");
+               crashk_res.start = crashk_res.end = 0;
+               return;
+       }
+
        /* Crash kernel trumps memory limit */
        if (memory_limit && memory_limit <= crashk_res.end) {
                memory_limit = crashk_res.end + 1;