diff options
| -rw-r--r-- | arch/powerpc/include/asm/paca.h | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 343 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 11 |
3 files changed, 300 insertions, 61 deletions
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 948f01a04cc3..8e956a0b6e85 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -116,8 +116,11 @@ struct paca_struct { | |||
| 116 | /* Shared by all threads of a core -- points to tcd of first thread */ | 116 | /* Shared by all threads of a core -- points to tcd of first thread */ |
| 117 | struct tlb_core_data *tcd_ptr; | 117 | struct tlb_core_data *tcd_ptr; |
| 118 | 118 | ||
| 119 | /* We can have up to 3 levels of reentrancy in the TLB miss handler */ | 119 | /* |
| 120 | u64 extlb[3][EX_TLB_SIZE / sizeof(u64)]; | 120 | * We can have up to 3 levels of reentrancy in the TLB miss handler, |
| 121 | * in each of four exception levels (normal, crit, mcheck, debug). | ||
| 122 | */ | ||
| 123 | u64 extlb[12][EX_TLB_SIZE / sizeof(u64)]; | ||
| 121 | u64 exmc[8]; /* used for machine checks */ | 124 | u64 exmc[8]; /* used for machine checks */ |
| 122 | u64 excrit[8]; /* used for crit interrupts */ | 125 | u64 excrit[8]; /* used for crit interrupts */ |
| 123 | u64 exdbg[8]; /* used for debug interrupts */ | 126 | u64 exdbg[8]; /* used for debug interrupts */ |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 2beb5bd0728b..c1bee3ce9d1f 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
| @@ -34,20 +34,250 @@ | |||
| 34 | * special interrupts from within a non-standard level will probably | 34 | * special interrupts from within a non-standard level will probably |
| 35 | * blow you up | 35 | * blow you up |
| 36 | */ | 36 | */ |
| 37 | #define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE | 37 | #define SPECIAL_EXC_SRR0 0 |
| 38 | #define SPECIAL_EXC_SRR1 1 | ||
| 39 | #define SPECIAL_EXC_SPRG_GEN 2 | ||
| 40 | #define SPECIAL_EXC_SPRG_TLB 3 | ||
| 41 | #define SPECIAL_EXC_MAS0 4 | ||
| 42 | #define SPECIAL_EXC_MAS1 5 | ||
| 43 | #define SPECIAL_EXC_MAS2 6 | ||
| 44 | #define SPECIAL_EXC_MAS3 7 | ||
| 45 | #define SPECIAL_EXC_MAS6 8 | ||
| 46 | #define SPECIAL_EXC_MAS7 9 | ||
| 47 | #define SPECIAL_EXC_MAS5 10 /* E.HV only */ | ||
| 48 | #define SPECIAL_EXC_MAS8 11 /* E.HV only */ | ||
| 49 | #define SPECIAL_EXC_IRQHAPPENED 12 | ||
| 50 | #define SPECIAL_EXC_DEAR 13 | ||
| 51 | #define SPECIAL_EXC_ESR 14 | ||
| 52 | #define SPECIAL_EXC_SOFTE 15 | ||
| 53 | #define SPECIAL_EXC_CSRR0 16 | ||
| 54 | #define SPECIAL_EXC_CSRR1 17 | ||
| 55 | /* must be even to keep 16-byte stack alignment */ | ||
| 56 | #define SPECIAL_EXC_END 18 | ||
| 57 | |||
| 58 | #define SPECIAL_EXC_FRAME_SIZE (INT_FRAME_SIZE + SPECIAL_EXC_END * 8) | ||
| 59 | #define SPECIAL_EXC_FRAME_OFFS (INT_FRAME_SIZE - 288) | ||
| 60 | |||
| 61 | #define SPECIAL_EXC_STORE(reg, name) \ | ||
| 62 | std reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1) | ||
| 63 | |||
| 64 | #define SPECIAL_EXC_LOAD(reg, name) \ | ||
| 65 | ld reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1) | ||
| 66 | |||
| 67 | special_reg_save: | ||
| 68 | lbz r9,PACAIRQHAPPENED(r13) | ||
| 69 | RECONCILE_IRQ_STATE(r3,r4) | ||
| 38 | 70 | ||
| 39 | /* Now we only store something to exception thread info */ | 71 | /* |
| 40 | #define EXC_LEVEL_EXCEPTION_PROLOG(type) \ | 72 | * We only need (or have stack space) to save this stuff if |
| 41 | ld r14,PACAKSAVE(r13); \ | 73 | * we interrupted the kernel. |
| 42 | CURRENT_THREAD_INFO(r14, r14); \ | 74 | */ |
| 43 | CURRENT_THREAD_INFO(r15, r1); \ | 75 | ld r3,_MSR(r1) |
| 44 | ld r10,TI_FLAGS(r14); \ | 76 | andi. r3,r3,MSR_PR |
| 45 | std r10,TI_FLAGS(r15); \ | 77 | bnelr |
| 46 | ld r10,TI_PREEMPT(r14); \ | 78 | |
| 47 | std r10,TI_PREEMPT(r15); \ | 79 | /* Copy info into temporary exception thread info */ |
| 48 | ld r10,TI_TASK(r14); \ | 80 | ld r11,PACAKSAVE(r13) |
| 49 | std r10,TI_TASK(r15); | 81 | CURRENT_THREAD_INFO(r11, r11) |
| 82 | CURRENT_THREAD_INFO(r12, r1) | ||
| 83 | ld r10,TI_FLAGS(r11) | ||
| 84 | std r10,TI_FLAGS(r12) | ||
| 85 | ld r10,TI_PREEMPT(r11) | ||
| 86 | std r10,TI_PREEMPT(r12) | ||
| 87 | ld r10,TI_TASK(r11) | ||
| 88 | std r10,TI_TASK(r12) | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Advance to the next TLB exception frame for handler | ||
| 92 | * types that don't do it automatically. | ||
| 93 | */ | ||
| 94 | LOAD_REG_ADDR(r11,extlb_level_exc) | ||
| 95 | lwz r12,0(r11) | ||
| 96 | mfspr r10,SPRN_SPRG_TLB_EXFRAME | ||
| 97 | add r10,r10,r12 | ||
| 98 | mtspr SPRN_SPRG_TLB_EXFRAME,r10 | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Save registers needed to allow nesting of certain exceptions | ||
| 102 | * (such as TLB misses) inside special exception levels | ||
| 103 | */ | ||
| 104 | mfspr r10,SPRN_SRR0 | ||
| 105 | SPECIAL_EXC_STORE(r10,SRR0) | ||
| 106 | mfspr r10,SPRN_SRR1 | ||
| 107 | SPECIAL_EXC_STORE(r10,SRR1) | ||
| 108 | mfspr r10,SPRN_SPRG_GEN_SCRATCH | ||
| 109 | SPECIAL_EXC_STORE(r10,SPRG_GEN) | ||
| 110 | mfspr r10,SPRN_SPRG_TLB_SCRATCH | ||
| 111 | SPECIAL_EXC_STORE(r10,SPRG_TLB) | ||
| 112 | mfspr r10,SPRN_MAS0 | ||
| 113 | SPECIAL_EXC_STORE(r10,MAS0) | ||
| 114 | mfspr r10,SPRN_MAS1 | ||
| 115 | SPECIAL_EXC_STORE(r10,MAS1) | ||
| 116 | mfspr r10,SPRN_MAS2 | ||
| 117 | SPECIAL_EXC_STORE(r10,MAS2) | ||
| 118 | mfspr r10,SPRN_MAS3 | ||
| 119 | SPECIAL_EXC_STORE(r10,MAS3) | ||
| 120 | mfspr r10,SPRN_MAS6 | ||
| 121 | SPECIAL_EXC_STORE(r10,MAS6) | ||
| 122 | mfspr r10,SPRN_MAS7 | ||
| 123 | SPECIAL_EXC_STORE(r10,MAS7) | ||
| 124 | BEGIN_FTR_SECTION | ||
| 125 | mfspr r10,SPRN_MAS5 | ||
| 126 | SPECIAL_EXC_STORE(r10,MAS5) | ||
| 127 | mfspr r10,SPRN_MAS8 | ||
| 128 | SPECIAL_EXC_STORE(r10,MAS8) | ||
| 129 | |||
| 130 | /* MAS5/8 could have inappropriate values if we interrupted KVM code */ | ||
| 131 | li r10,0 | ||
| 132 | mtspr SPRN_MAS5,r10 | ||
| 133 | mtspr SPRN_MAS8,r10 | ||
| 134 | END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) | ||
| 135 | SPECIAL_EXC_STORE(r9,IRQHAPPENED) | ||
| 136 | |||
| 137 | mfspr r10,SPRN_DEAR | ||
| 138 | SPECIAL_EXC_STORE(r10,DEAR) | ||
| 139 | mfspr r10,SPRN_ESR | ||
| 140 | SPECIAL_EXC_STORE(r10,ESR) | ||
| 141 | |||
| 142 | lbz r10,PACASOFTIRQEN(r13) | ||
| 143 | SPECIAL_EXC_STORE(r10,SOFTE) | ||
| 144 | ld r10,_NIP(r1) | ||
| 145 | SPECIAL_EXC_STORE(r10,CSRR0) | ||
| 146 | ld r10,_MSR(r1) | ||
| 147 | SPECIAL_EXC_STORE(r10,CSRR1) | ||
| 148 | |||
| 149 | blr | ||
| 150 | |||
| 151 | ret_from_level_except: | ||
| 152 | ld r3,_MSR(r1) | ||
| 153 | andi. r3,r3,MSR_PR | ||
| 154 | beq 1f | ||
| 155 | b ret_from_except | ||
| 156 | 1: | ||
| 157 | |||
| 158 | LOAD_REG_ADDR(r11,extlb_level_exc) | ||
| 159 | lwz r12,0(r11) | ||
| 160 | mfspr r10,SPRN_SPRG_TLB_EXFRAME | ||
| 161 | sub r10,r10,r12 | ||
| 162 | mtspr SPRN_SPRG_TLB_EXFRAME,r10 | ||
| 163 | |||
| 164 | /* | ||
| 165 | * It's possible that the special level exception interrupted a | ||
| 166 | * TLB miss handler, and inserted the same entry that the | ||
| 167 | * interrupted handler was about to insert. On CPUs without TLB | ||
| 168 | * write conditional, this can result in a duplicate TLB entry. | ||
| 169 | * Wipe all non-bolted entries to be safe. | ||
| 170 | * | ||
| 171 | * Note that this doesn't protect against any TLB misses | ||
| 172 | * we may take accessing the stack from here to the end of | ||
| 173 | * the special level exception. It's not clear how we can | ||
| 174 | * reasonably protect against that, but only CPUs with | ||
| 175 | * neither TLB write conditional nor bolted kernel memory | ||
| 176 | * are affected. Do any such CPUs even exist? | ||
| 177 | */ | ||
| 178 | PPC_TLBILX_ALL(0,R0) | ||
| 179 | |||
| 180 | REST_NVGPRS(r1) | ||
| 181 | |||
| 182 | SPECIAL_EXC_LOAD(r10,SRR0) | ||
| 183 | mtspr SPRN_SRR0,r10 | ||
| 184 | SPECIAL_EXC_LOAD(r10,SRR1) | ||
| 185 | mtspr SPRN_SRR1,r10 | ||
| 186 | SPECIAL_EXC_LOAD(r10,SPRG_GEN) | ||
| 187 | mtspr SPRN_SPRG_GEN_SCRATCH,r10 | ||
| 188 | SPECIAL_EXC_LOAD(r10,SPRG_TLB) | ||
| 189 | mtspr SPRN_SPRG_TLB_SCRATCH,r10 | ||
| 190 | SPECIAL_EXC_LOAD(r10,MAS0) | ||
| 191 | mtspr SPRN_MAS0,r10 | ||
| 192 | SPECIAL_EXC_LOAD(r10,MAS1) | ||
| 193 | mtspr SPRN_MAS1,r10 | ||
| 194 | SPECIAL_EXC_LOAD(r10,MAS2) | ||
| 195 | mtspr SPRN_MAS2,r10 | ||
| 196 | SPECIAL_EXC_LOAD(r10,MAS3) | ||
| 197 | mtspr SPRN_MAS3,r10 | ||
| 198 | SPECIAL_EXC_LOAD(r10,MAS6) | ||
| 199 | mtspr SPRN_MAS6,r10 | ||
| 200 | SPECIAL_EXC_LOAD(r10,MAS7) | ||
| 201 | mtspr SPRN_MAS7,r10 | ||
| 202 | BEGIN_FTR_SECTION | ||
| 203 | SPECIAL_EXC_LOAD(r10,MAS5) | ||
| 204 | mtspr SPRN_MAS5,r10 | ||
| 205 | SPECIAL_EXC_LOAD(r10,MAS8) | ||
| 206 | mtspr SPRN_MAS8,r10 | ||
| 207 | END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) | ||
| 208 | |||
| 209 | lbz r6,PACASOFTIRQEN(r13) | ||
| 210 | ld r5,SOFTE(r1) | ||
| 211 | |||
| 212 | /* Interrupts had better not already be enabled... */ | ||
| 213 | twnei r6,0 | ||
| 214 | |||
| 215 | cmpwi cr0,r5,0 | ||
| 216 | beq 1f | ||
| 50 | 217 | ||
| 218 | TRACE_ENABLE_INTS | ||
| 219 | stb r5,PACASOFTIRQEN(r13) | ||
| 220 | 1: | ||
| 221 | /* | ||
| 222 | * Restore PACAIRQHAPPENED rather than setting it based on | ||
| 223 | * the return MSR[EE], since we could have interrupted | ||
| 224 | * __check_irq_replay() or other inconsistent transitory | ||
| 225 | * states that must remain that way. | ||
| 226 | */ | ||
| 227 | SPECIAL_EXC_LOAD(r10,IRQHAPPENED) | ||
| 228 | stb r10,PACAIRQHAPPENED(r13) | ||
| 229 | |||
| 230 | SPECIAL_EXC_LOAD(r10,DEAR) | ||
| 231 | mtspr SPRN_DEAR,r10 | ||
| 232 | SPECIAL_EXC_LOAD(r10,ESR) | ||
| 233 | mtspr SPRN_ESR,r10 | ||
| 234 | |||
| 235 | stdcx. r0,0,r1 /* to clear the reservation */ | ||
| 236 | |||
| 237 | REST_4GPRS(2, r1) | ||
| 238 | REST_4GPRS(6, r1) | ||
| 239 | |||
| 240 | ld r10,_CTR(r1) | ||
| 241 | ld r11,_XER(r1) | ||
| 242 | mtctr r10 | ||
| 243 | mtxer r11 | ||
| 244 | |||
| 245 | blr | ||
| 246 | |||
| 247 | .macro ret_from_level srr0 srr1 paca_ex scratch | ||
| 248 | bl ret_from_level_except | ||
| 249 | |||
| 250 | ld r10,_LINK(r1) | ||
| 251 | ld r11,_CCR(r1) | ||
| 252 | ld r0,GPR13(r1) | ||
| 253 | mtlr r10 | ||
| 254 | mtcr r11 | ||
| 255 | |||
| 256 | ld r10,GPR10(r1) | ||
| 257 | ld r11,GPR11(r1) | ||
| 258 | ld r12,GPR12(r1) | ||
| 259 | mtspr \scratch,r0 | ||
| 260 | |||
| 261 | std r10,\paca_ex+EX_R10(r13); | ||
| 262 | std r11,\paca_ex+EX_R11(r13); | ||
| 263 | ld r10,_NIP(r1) | ||
| 264 | ld r11,_MSR(r1) | ||
| 265 | ld r0,GPR0(r1) | ||
| 266 | ld r1,GPR1(r1) | ||
| 267 | mtspr \srr0,r10 | ||
| 268 | mtspr \srr1,r11 | ||
| 269 | ld r10,\paca_ex+EX_R10(r13) | ||
| 270 | ld r11,\paca_ex+EX_R11(r13) | ||
| 271 | mfspr r13,\scratch | ||
| 272 | .endm | ||
| 273 | |||
| 274 | ret_from_crit_except: | ||
| 275 | ret_from_level SPRN_CSRR0 SPRN_CSRR1 PACA_EXCRIT SPRN_SPRG_CRIT_SCRATCH | ||
| 276 | rfci | ||
| 277 | |||
| 278 | ret_from_mc_except: | ||
| 279 | ret_from_level SPRN_MCSRR0 SPRN_MCSRR1 PACA_EXMC SPRN_SPRG_MC_SCRATCH | ||
| 280 | rfmci | ||
| 51 | 281 | ||
| 52 | /* Exception prolog code for all exceptions */ | 282 | /* Exception prolog code for all exceptions */ |
| 53 | #define EXCEPTION_PROLOG(n, intnum, type, addition) \ | 283 | #define EXCEPTION_PROLOG(n, intnum, type, addition) \ |
| @@ -81,22 +311,19 @@ | |||
| 81 | 311 | ||
| 82 | #define CRIT_SET_KSTACK \ | 312 | #define CRIT_SET_KSTACK \ |
| 83 | ld r1,PACA_CRIT_STACK(r13); \ | 313 | ld r1,PACA_CRIT_STACK(r13); \ |
| 84 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; \ | 314 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE |
| 85 | EXC_LEVEL_EXCEPTION_PROLOG(CRIT); | ||
| 86 | #define SPRN_CRIT_SRR0 SPRN_CSRR0 | 315 | #define SPRN_CRIT_SRR0 SPRN_CSRR0 |
| 87 | #define SPRN_CRIT_SRR1 SPRN_CSRR1 | 316 | #define SPRN_CRIT_SRR1 SPRN_CSRR1 |
| 88 | 317 | ||
| 89 | #define DBG_SET_KSTACK \ | 318 | #define DBG_SET_KSTACK \ |
| 90 | ld r1,PACA_DBG_STACK(r13); \ | 319 | ld r1,PACA_DBG_STACK(r13); \ |
| 91 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; \ | 320 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE |
| 92 | EXC_LEVEL_EXCEPTION_PROLOG(DBG); | ||
| 93 | #define SPRN_DBG_SRR0 SPRN_DSRR0 | 321 | #define SPRN_DBG_SRR0 SPRN_DSRR0 |
| 94 | #define SPRN_DBG_SRR1 SPRN_DSRR1 | 322 | #define SPRN_DBG_SRR1 SPRN_DSRR1 |
| 95 | 323 | ||
| 96 | #define MC_SET_KSTACK \ | 324 | #define MC_SET_KSTACK \ |
| 97 | ld r1,PACA_MC_STACK(r13); \ | 325 | ld r1,PACA_MC_STACK(r13); \ |
| 98 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; \ | 326 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE |
| 99 | EXC_LEVEL_EXCEPTION_PROLOG(MC); | ||
| 100 | #define SPRN_MC_SRR0 SPRN_MCSRR0 | 327 | #define SPRN_MC_SRR0 SPRN_MCSRR0 |
| 101 | #define SPRN_MC_SRR1 SPRN_MCSRR1 | 328 | #define SPRN_MC_SRR1 SPRN_MCSRR1 |
| 102 | 329 | ||
| @@ -322,27 +549,25 @@ interrupt_end_book3e: | |||
| 322 | START_EXCEPTION(critical_input); | 549 | START_EXCEPTION(critical_input); |
| 323 | CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL, | 550 | CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL, |
| 324 | PROLOG_ADDITION_NONE) | 551 | PROLOG_ADDITION_NONE) |
| 325 | // EXCEPTION_COMMON_CRIT(0x100) | 552 | EXCEPTION_COMMON_CRIT(0x100) |
| 326 | // INTS_DISABLE | 553 | bl .save_nvgprs |
| 327 | // bl special_reg_save_crit | 554 | bl special_reg_save |
| 328 | // CHECK_NAPPING(); | 555 | CHECK_NAPPING(); |
| 329 | // addi r3,r1,STACK_FRAME_OVERHEAD | 556 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 330 | // bl .critical_exception | 557 | bl .unknown_exception |
| 331 | // b ret_from_crit_except | 558 | b ret_from_crit_except |
| 332 | b . | ||
| 333 | 559 | ||
| 334 | /* Machine Check Interrupt */ | 560 | /* Machine Check Interrupt */ |
| 335 | START_EXCEPTION(machine_check); | 561 | START_EXCEPTION(machine_check); |
| 336 | MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK, | 562 | MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK, |
| 337 | PROLOG_ADDITION_NONE) | 563 | PROLOG_ADDITION_NONE) |
| 338 | // EXCEPTION_COMMON_MC(0x000) | 564 | EXCEPTION_COMMON_MC(0x000) |
| 339 | // INTS_DISABLE | 565 | bl .save_nvgprs |
| 340 | // bl special_reg_save_mc | 566 | bl special_reg_save |
| 341 | // addi r3,r1,STACK_FRAME_OVERHEAD | 567 | CHECK_NAPPING(); |
| 342 | // CHECK_NAPPING(); | 568 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 343 | // bl .machine_check_exception | 569 | bl .machine_check_exception |
| 344 | // b ret_from_mc_except | 570 | b ret_from_mc_except |
| 345 | b . | ||
| 346 | 571 | ||
| 347 | /* Data Storage Interrupt */ | 572 | /* Data Storage Interrupt */ |
| 348 | START_EXCEPTION(data_storage) | 573 | START_EXCEPTION(data_storage) |
| @@ -461,14 +686,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 461 | START_EXCEPTION(watchdog); | 686 | START_EXCEPTION(watchdog); |
| 462 | CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG, | 687 | CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG, |
| 463 | PROLOG_ADDITION_NONE) | 688 | PROLOG_ADDITION_NONE) |
| 464 | // EXCEPTION_COMMON_CRIT(0x9f0) | 689 | EXCEPTION_COMMON_CRIT(0x9f0) |
| 465 | // INTS_DISABLE | 690 | bl .save_nvgprs |
| 466 | // bl special_reg_save_crit | 691 | bl special_reg_save |
| 467 | // CHECK_NAPPING(); | 692 | CHECK_NAPPING(); |
| 468 | // addi r3,r1,STACK_FRAME_OVERHEAD | 693 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 469 | // bl .unknown_exception | 694 | #ifdef CONFIG_BOOKE_WDT |
| 470 | // b ret_from_crit_except | 695 | bl .WatchdogException |
| 471 | b . | 696 | #else |
| 697 | bl .unknown_exception | ||
| 698 | #endif | ||
| 699 | b ret_from_crit_except | ||
| 472 | 700 | ||
| 473 | /* System Call Interrupt */ | 701 | /* System Call Interrupt */ |
| 474 | START_EXCEPTION(system_call) | 702 | START_EXCEPTION(system_call) |
| @@ -541,7 +769,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 541 | */ | 769 | */ |
| 542 | mfspr r14,SPRN_DBSR | 770 | mfspr r14,SPRN_DBSR |
| 543 | EXCEPTION_COMMON_CRIT(0xd00) | 771 | EXCEPTION_COMMON_CRIT(0xd00) |
| 544 | INTS_DISABLE | ||
| 545 | std r14,_DSISR(r1) | 772 | std r14,_DSISR(r1) |
| 546 | addi r3,r1,STACK_FRAME_OVERHEAD | 773 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 547 | mr r4,r14 | 774 | mr r4,r14 |
| @@ -634,14 +861,13 @@ kernel_dbg_exc: | |||
| 634 | START_EXCEPTION(doorbell_crit); | 861 | START_EXCEPTION(doorbell_crit); |
| 635 | CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL, | 862 | CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL, |
| 636 | PROLOG_ADDITION_NONE) | 863 | PROLOG_ADDITION_NONE) |
| 637 | // EXCEPTION_COMMON_CRIT(0x2a0) | 864 | EXCEPTION_COMMON_CRIT(0x2a0) |
| 638 | // INTS_DISABLE | 865 | bl .save_nvgprs |
| 639 | // bl special_reg_save_crit | 866 | bl special_reg_save |
| 640 | // CHECK_NAPPING(); | 867 | CHECK_NAPPING(); |
| 641 | // addi r3,r1,STACK_FRAME_OVERHEAD | 868 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 642 | // bl .doorbell_critical_exception | 869 | bl .unknown_exception |
| 643 | // b ret_from_crit_except | 870 | b ret_from_crit_except |
| 644 | b . | ||
| 645 | 871 | ||
| 646 | /* | 872 | /* |
| 647 | * Guest doorbell interrupt | 873 | * Guest doorbell interrupt |
| @@ -661,14 +887,13 @@ kernel_dbg_exc: | |||
| 661 | START_EXCEPTION(guest_doorbell_crit); | 887 | START_EXCEPTION(guest_doorbell_crit); |
| 662 | CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT, | 888 | CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT, |
| 663 | PROLOG_ADDITION_NONE) | 889 | PROLOG_ADDITION_NONE) |
| 664 | // EXCEPTION_COMMON_CRIT(0x2e0) | 890 | EXCEPTION_COMMON_CRIT(0x2e0) |
| 665 | // INTS_DISABLE | 891 | bl .save_nvgprs |
| 666 | // bl special_reg_save_crit | 892 | bl special_reg_save |
| 667 | // CHECK_NAPPING(); | 893 | CHECK_NAPPING(); |
| 668 | // addi r3,r1,STACK_FRAME_OVERHEAD | 894 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 669 | // bl .guest_doorbell_critical_exception | 895 | bl .unknown_exception |
| 670 | // b ret_from_crit_except | 896 | b ret_from_crit_except |
| 671 | b . | ||
| 672 | 897 | ||
| 673 | /* Hypervisor call */ | 898 | /* Hypervisor call */ |
| 674 | START_EXCEPTION(hypercall); | 899 | START_EXCEPTION(hypercall); |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index b37a58e1c92d..ae3d5b799b90 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
| @@ -144,6 +144,15 @@ int mmu_vmemmap_psize; /* Page size used for the virtual mem map */ | |||
| 144 | int book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ | 144 | int book3e_htw_mode; /* HW tablewalk? Value is PPC_HTW_* */ |
| 145 | unsigned long linear_map_top; /* Top of linear mapping */ | 145 | unsigned long linear_map_top; /* Top of linear mapping */ |
| 146 | 146 | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Number of bytes to add to SPRN_SPRG_TLB_EXFRAME on crit/mcheck/debug | ||
| 150 | * exceptions. This is used for bolted and e6500 TLB miss handlers which | ||
| 151 | * do not modify this SPRG in the TLB miss code; for other TLB miss handlers, | ||
| 152 | * this is set to zero. | ||
| 153 | */ | ||
| 154 | int extlb_level_exc; | ||
| 155 | |||
| 147 | #endif /* CONFIG_PPC64 */ | 156 | #endif /* CONFIG_PPC64 */ |
| 148 | 157 | ||
| 149 | #ifdef CONFIG_PPC_FSL_BOOK3E | 158 | #ifdef CONFIG_PPC_FSL_BOOK3E |
| @@ -559,6 +568,7 @@ static void setup_mmu_htw(void) | |||
| 559 | break; | 568 | break; |
| 560 | #ifdef CONFIG_PPC_FSL_BOOK3E | 569 | #ifdef CONFIG_PPC_FSL_BOOK3E |
| 561 | case PPC_HTW_E6500: | 570 | case PPC_HTW_E6500: |
| 571 | extlb_level_exc = EX_TLB_SIZE; | ||
| 562 | patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); | 572 | patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); |
| 563 | patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); | 573 | patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); |
| 564 | break; | 574 | break; |
| @@ -652,6 +662,7 @@ static void __early_init_mmu(int boot_cpu) | |||
| 652 | memblock_enforce_memory_limit(linear_map_top); | 662 | memblock_enforce_memory_limit(linear_map_top); |
| 653 | 663 | ||
| 654 | if (book3e_htw_mode == PPC_HTW_NONE) { | 664 | if (book3e_htw_mode == PPC_HTW_NONE) { |
| 665 | extlb_level_exc = EX_TLB_SIZE; | ||
| 655 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); | 666 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); |
| 656 | patch_exception(0x1e0, | 667 | patch_exception(0x1e0, |
| 657 | exc_instruction_tlb_miss_bolted_book3e); | 668 | exc_instruction_tlb_miss_bolted_book3e); |
