aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorOlaf Hering <olh@suse.de>2006-07-19 04:34:05 -0400
committerPaul Mackerras <paulus@samba.org>2006-07-28 14:07:08 -0400
commit9fc0a92c7ebcad96467d62077497ce195d9b741c (patch)
tree8b5824d93be7746f69f992db9e684af0962a82ab /arch/powerpc/kernel
parent4c962b5a42e5fc24e2d5d73896732cf3578da260 (diff)
[POWERPC] force 64bit mode in fwnmi handlers to workaround firmware bugs
The firmware of POWER4 and JS20 systems does not switch the cpu to 64bit mode when the registered system_reset and machine_check handlers get called. If a 32bit process runs on that cpu at the time of the event, the cpu remains in 32bit mode. xmon and kdump can not deal with it, the result is an error like 'Bad kernel stack pointer fff2aad0 at 3200'. xmon just loses some register info, but booting the kdump kernel usually fails. Both handlers are not hot paths. Duplicate the EXCEPTION_PROLOG_PSERIES macro and add two instructions to switch to 64bit: li r11,5; rldimi r10,r11,61,0; Signed-off-by: Olaf Hering <olh@suse.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/head_64.S35
1 files changed, 33 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e16eb2a33173..6ff3cf506088 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -191,6 +191,37 @@ exception_marker:
191 ori reg,reg,(label)@l; /* virt addr of handler ... */ 191 ori reg,reg,(label)@l; /* virt addr of handler ... */
192#endif 192#endif
193 193
194/*
195 * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
196 * The firmware calls the registered system_reset_fwnmi and
197 * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
198 * a 32bit application at the time of the event.
199 * This firmware bug is present on POWER4 and JS20.
200 */
201#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label) \
202 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
203 std r9,area+EX_R9(r13); /* save r9 - r12 */ \
204 std r10,area+EX_R10(r13); \
205 std r11,area+EX_R11(r13); \
206 std r12,area+EX_R12(r13); \
207 mfspr r9,SPRN_SPRG1; \
208 std r9,area+EX_R13(r13); \
209 mfcr r9; \
210 clrrdi r12,r13,32; /* get high part of &label */ \
211 mfmsr r10; \
212 /* force 64bit mode */ \
213 li r11,5; /* MSR_SF_LG|MSR_ISF_LG */ \
214 rldimi r10,r11,61,0; /* insert into top 3 bits */ \
215 /* done 64bit mode */ \
216 mfspr r11,SPRN_SRR0; /* save SRR0 */ \
217 LOAD_HANDLER(r12,label) \
218 ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \
219 mtspr SPRN_SRR0,r12; \
220 mfspr r12,SPRN_SRR1; /* and SRR1 */ \
221 mtspr SPRN_SRR1,r10; \
222 rfid; \
223 b . /* prevent speculative execution */
224
194#define EXCEPTION_PROLOG_PSERIES(area, label) \ 225#define EXCEPTION_PROLOG_PSERIES(area, label) \
195 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ 226 mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \
196 std r9,area+EX_R9(r13); /* save r9 - r12 */ \ 227 std r9,area+EX_R9(r13); /* save r9 - r12 */ \
@@ -604,14 +635,14 @@ slb_miss_user_pseries:
604system_reset_fwnmi: 635system_reset_fwnmi:
605 HMT_MEDIUM 636 HMT_MEDIUM
606 mtspr SPRN_SPRG1,r13 /* save r13 */ 637 mtspr SPRN_SPRG1,r13 /* save r13 */
607 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) 638 EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
608 639
609 .globl machine_check_fwnmi 640 .globl machine_check_fwnmi
610 .align 7 641 .align 7
611machine_check_fwnmi: 642machine_check_fwnmi:
612 HMT_MEDIUM 643 HMT_MEDIUM
613 mtspr SPRN_SPRG1,r13 /* save r13 */ 644 mtspr SPRN_SPRG1,r13 /* save r13 */
614 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) 645 EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
615 646
616#ifdef CONFIG_PPC_ISERIES 647#ifdef CONFIG_PPC_ISERIES
617/*** ISeries-LPAR interrupt handlers ***/ 648/*** ISeries-LPAR interrupt handlers ***/