path: root/arch/powerpc/include/asm/exception-64s.h
diff options
authorPaul Mackerras <paulus@samba.org>2011-05-01 19:46:44 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-05-04 15:19:27 +1000
commit1977b502120d44b9b4897703adfb2e2fab346880 (patch)
treedfe0e5cc29b409e7638b5e33528b7c4bc003f5e7 /arch/powerpc/include/asm/exception-64s.h
parent851d2e2fe8dbcbe3afcad6fc4569c881d8ad4ce9 (diff)
powerpc: Save register r9-r13 values accurately on interrupt with bad stack
When we take an interrupt or exception from kernel mode and the stack pointer is obviously not a kernel address (i.e. the top bit is 0), we switch to an emergency stack, save register values and panic. However, on 64-bit server machines, we don't actually save the values of r9 - r13 at the time of the interrupt, but rather values corrupted by the exception entry code for r12-r13, and nothing at all for r9-r11. This fixes it by passing a pointer to the register save area in the paca through to the bad_stack code in r3. The register values are saved in one of the paca register save areas (depending on which exception this is). Using the pointer in r3, the bad_stack code now retrieves the saved values of r9 - r13 and stores them in the exception frame on the emergency stack. This also stores the normal exception frame marker ("regshere") in the exception frame. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index d6b4849df9b..96ccef136ca 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -104,10 +104,11 @@
beq- 1f; \
ld r1,PACAKSAVE(r13); /* kernel stack to use */ \
1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \
- bge- cr1,2f; /* abort if it is */ \
- b 3f; \
-2: li r1,(n); /* will be reloaded later */ \
+ blt+ cr1,3f; /* abort if it is */ \
+ li r1,(n); /* will be reloaded later */ \
sth r1,PACA_TRAP_SAVE(r13); \
+ std r3,area+EX_R3(r13); \
+ addi r3,r13,area; /* r3 -> where regs are saved*/ \
b bad_stack; \
3: std r9,_CCR(r1); /* save CR in stackframe */ \
std r11,_NIP(r1); /* save SRR0 in stackframe */ \