aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2010-08-24 10:23:44 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2010-11-28 23:48:17 -0500
commitd72e063bb32c06c6c1cec14f6857b7c37ba62d7a (patch)
tree9bab39d568bee4b95e37700b0e87ef7346525953 /arch
parent64ff31287693c1f325cb9cb049569c1611438ef1 (diff)
powerpc/kdump: Override crash_free_reserved_phys_range to avoid freeing RTAS
The crashkernel region will almost always overlap RTAS. If we free the crashkernel region via "echo 0 > /sys/kernel/kexec_crash_size" then we will free RTAS and the machine will crash in confusing and exciting ways. Override crash_free_reserved_phys_range and check for overlap with RTAS. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/crash_dump.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 8e05c16344e4..0a2af50243cb 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -19,6 +19,7 @@
19#include <asm/prom.h> 19#include <asm/prom.h>
20#include <asm/firmware.h> 20#include <asm/firmware.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22#include <asm/rtas.h>
22 23
23#ifdef DEBUG 24#ifdef DEBUG
24#include <asm/udbg.h> 25#include <asm/udbg.h>
@@ -141,3 +142,35 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
141 142
142 return csize; 143 return csize;
143} 144}
145
146#ifdef CONFIG_PPC_RTAS
147/*
148 * The crashkernel region will almost always overlap the RTAS region, so
149 * we have to be careful when shrinking the crashkernel region.
150 */
151void crash_free_reserved_phys_range(unsigned long begin, unsigned long end)
152{
153 unsigned long addr;
154 const u32 *basep, *sizep;
155 unsigned int rtas_start = 0, rtas_end = 0;
156
157 basep = of_get_property(rtas.dev, "linux,rtas-base", NULL);
158 sizep = of_get_property(rtas.dev, "rtas-size", NULL);
159
160 if (basep && sizep) {
161 rtas_start = *basep;
162 rtas_end = *basep + *sizep;
163 }
164
165 for (addr = begin; addr < end; addr += PAGE_SIZE) {
166 /* Does this page overlap with the RTAS region? */
167 if (addr <= rtas_end && ((addr + PAGE_SIZE) > rtas_start))
168 continue;
169
170 ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
171 init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
172 free_page((unsigned long)__va(addr));
173 totalram_pages++;
174 }
175}
176#endif