diff options
| -rw-r--r-- | arch/powerpc/kernel/head_64.S | 35 |
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: | |||
| 604 | system_reset_fwnmi: | 635 | system_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 |
| 611 | machine_check_fwnmi: | 642 | machine_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 ***/ |
