diff options
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 138 |
1 files changed, 119 insertions, 19 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index ad708dda3ba3..05e6d2ee1db9 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -47,9 +47,10 @@ | |||
47 | #define EX_R3 64 | 47 | #define EX_R3 64 |
48 | #define EX_LR 72 | 48 | #define EX_LR 72 |
49 | #define EX_CFAR 80 | 49 | #define EX_CFAR 80 |
50 | #define EX_PPR 88 /* SMT thread status register (priority) */ | ||
50 | 51 | ||
51 | #ifdef CONFIG_RELOCATABLE | 52 | #ifdef CONFIG_RELOCATABLE |
52 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | 53 | #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ |
53 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ | 54 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ |
54 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | 55 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
55 | LOAD_HANDLER(r12,label); \ | 56 | LOAD_HANDLER(r12,label); \ |
@@ -60,13 +61,15 @@ | |||
60 | blr; | 61 | blr; |
61 | #else | 62 | #else |
62 | /* If not relocatable, we can jump directly -- and save messing with LR */ | 63 | /* If not relocatable, we can jump directly -- and save messing with LR */ |
63 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | 64 | #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ |
64 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | 65 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
65 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | 66 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ |
66 | li r10,MSR_RI; \ | 67 | li r10,MSR_RI; \ |
67 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | 68 | mtmsrd r10,1; /* Set RI (EE=0) */ \ |
68 | b label; | 69 | b label; |
69 | #endif | 70 | #endif |
71 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
72 | __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
70 | 73 | ||
71 | /* | 74 | /* |
72 | * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on | 75 | * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on |
@@ -74,6 +77,7 @@ | |||
74 | * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. | 77 | * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. |
75 | */ | 78 | */ |
76 | #define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec) \ | 79 | #define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec) \ |
80 | EXCEPTION_PROLOG_0(area); \ | ||
77 | EXCEPTION_PROLOG_1(area, extra, vec); \ | 81 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
78 | EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) | 82 | EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) |
79 | 83 | ||
@@ -107,14 +111,59 @@ | |||
107 | #define RESTORE_LR(reg, area) | 111 | #define RESTORE_LR(reg, area) |
108 | #endif | 112 | #endif |
109 | 113 | ||
110 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ | 114 | /* |
115 | * PPR save/restore macros used in exceptions_64s.S | ||
116 | * Used for P7 or later processors | ||
117 | */ | ||
118 | #define SAVE_PPR(area, ra, rb) \ | ||
119 | BEGIN_FTR_SECTION_NESTED(940) \ | ||
120 | ld ra,PACACURRENT(r13); \ | ||
121 | ld rb,area+EX_PPR(r13); /* Read PPR from paca */ \ | ||
122 | std rb,TASKTHREADPPR(ra); \ | ||
123 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) | ||
124 | |||
125 | #define RESTORE_PPR_PACA(area, ra) \ | ||
126 | BEGIN_FTR_SECTION_NESTED(941) \ | ||
127 | ld ra,area+EX_PPR(r13); \ | ||
128 | mtspr SPRN_PPR,ra; \ | ||
129 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,941) | ||
130 | |||
131 | /* | ||
132 | * Increase the priority on systems where PPR save/restore is not | ||
133 | * implemented/ supported. | ||
134 | */ | ||
135 | #define HMT_MEDIUM_PPR_DISCARD \ | ||
136 | BEGIN_FTR_SECTION_NESTED(942) \ | ||
137 | HMT_MEDIUM; \ | ||
138 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,0,942) /*non P7*/ | ||
139 | |||
140 | /* | ||
141 | * Get an SPR into a register if the CPU has the given feature | ||
142 | */ | ||
143 | #define OPT_GET_SPR(ra, spr, ftr) \ | ||
144 | BEGIN_FTR_SECTION_NESTED(943) \ | ||
145 | mfspr ra,spr; \ | ||
146 | END_FTR_SECTION_NESTED(ftr,ftr,943) | ||
147 | |||
148 | /* | ||
149 | * Save a register to the PACA if the CPU has the given feature | ||
150 | */ | ||
151 | #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr) \ | ||
152 | BEGIN_FTR_SECTION_NESTED(943) \ | ||
153 | std ra,offset(r13); \ | ||
154 | END_FTR_SECTION_NESTED(ftr,ftr,943) | ||
155 | |||
156 | #define EXCEPTION_PROLOG_0(area) \ | ||
111 | GET_PACA(r13); \ | 157 | GET_PACA(r13); \ |
112 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | 158 | std r9,area+EX_R9(r13); /* save r9 */ \ |
113 | std r10,area+EX_R10(r13); \ | 159 | OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); \ |
114 | BEGIN_FTR_SECTION_NESTED(66); \ | 160 | HMT_MEDIUM; \ |
115 | mfspr r10,SPRN_CFAR; \ | 161 | std r10,area+EX_R10(r13); /* save r10 - r12 */ \ |
116 | std r10,area+EX_CFAR(r13); \ | 162 | OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR) |
117 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ | 163 | |
164 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ | ||
165 | OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ | ||
166 | OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ | ||
118 | SAVE_LR(r10, area); \ | 167 | SAVE_LR(r10, area); \ |
119 | mfcr r9; \ | 168 | mfcr r9; \ |
120 | extra(vec); \ | 169 | extra(vec); \ |
@@ -139,6 +188,7 @@ | |||
139 | __EXCEPTION_PROLOG_PSERIES_1(label, h) | 188 | __EXCEPTION_PROLOG_PSERIES_1(label, h) |
140 | 189 | ||
141 | #define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \ | 190 | #define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \ |
191 | EXCEPTION_PROLOG_0(area); \ | ||
142 | EXCEPTION_PROLOG_1(area, extra, vec); \ | 192 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
143 | EXCEPTION_PROLOG_PSERIES_1(label, h); | 193 | EXCEPTION_PROLOG_PSERIES_1(label, h); |
144 | 194 | ||
@@ -149,10 +199,14 @@ | |||
149 | 199 | ||
150 | #define __KVM_HANDLER(area, h, n) \ | 200 | #define __KVM_HANDLER(area, h, n) \ |
151 | do_kvm_##n: \ | 201 | do_kvm_##n: \ |
202 | BEGIN_FTR_SECTION_NESTED(947) \ | ||
203 | ld r10,area+EX_CFAR(r13); \ | ||
204 | std r10,HSTATE_CFAR(r13); \ | ||
205 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947); \ | ||
152 | ld r10,area+EX_R10(r13); \ | 206 | ld r10,area+EX_R10(r13); \ |
153 | stw r9,HSTATE_SCRATCH1(r13); \ | 207 | stw r9,HSTATE_SCRATCH1(r13); \ |
154 | ld r9,area+EX_R9(r13); \ | 208 | ld r9,area+EX_R9(r13); \ |
155 | std r12,HSTATE_SCRATCH0(r13); \ | 209 | std r12,HSTATE_SCRATCH0(r13); \ |
156 | li r12,n; \ | 210 | li r12,n; \ |
157 | b kvmppc_interrupt | 211 | b kvmppc_interrupt |
158 | 212 | ||
@@ -224,8 +278,10 @@ do_kvm_##n: \ | |||
224 | std r10,0(r1); /* make stack chain pointer */ \ | 278 | std r10,0(r1); /* make stack chain pointer */ \ |
225 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 279 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
226 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | 280 | std r10,GPR1(r1); /* save r1 in stackframe */ \ |
281 | beq 4f; /* if from kernel mode */ \ | ||
227 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | 282 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ |
228 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | 283 | SAVE_PPR(area, r9, r10); \ |
284 | 4: std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
229 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | 285 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ |
230 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | 286 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ |
231 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ | 287 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ |
@@ -266,45 +322,74 @@ do_kvm_##n: \ | |||
266 | . = loc; \ | 322 | . = loc; \ |
267 | .globl label##_pSeries; \ | 323 | .globl label##_pSeries; \ |
268 | label##_pSeries: \ | 324 | label##_pSeries: \ |
269 | HMT_MEDIUM; \ | 325 | HMT_MEDIUM_PPR_DISCARD; \ |
270 | SET_SCRATCH0(r13); /* save r13 */ \ | 326 | SET_SCRATCH0(r13); /* save r13 */ \ |
271 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 327 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
272 | EXC_STD, KVMTEST_PR, vec) | 328 | EXC_STD, KVMTEST_PR, vec) |
273 | 329 | ||
330 | /* Version of above for when we have to branch out-of-line */ | ||
331 | #define STD_EXCEPTION_PSERIES_OOL(vec, label) \ | ||
332 | .globl label##_pSeries; \ | ||
333 | label##_pSeries: \ | ||
334 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ | ||
335 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD) | ||
336 | |||
274 | #define STD_EXCEPTION_HV(loc, vec, label) \ | 337 | #define STD_EXCEPTION_HV(loc, vec, label) \ |
275 | . = loc; \ | 338 | . = loc; \ |
276 | .globl label##_hv; \ | 339 | .globl label##_hv; \ |
277 | label##_hv: \ | 340 | label##_hv: \ |
278 | HMT_MEDIUM; \ | 341 | HMT_MEDIUM_PPR_DISCARD; \ |
279 | SET_SCRATCH0(r13); /* save r13 */ \ | 342 | SET_SCRATCH0(r13); /* save r13 */ \ |
280 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 343 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
281 | EXC_HV, KVMTEST, vec) | 344 | EXC_HV, KVMTEST, vec) |
282 | 345 | ||
346 | /* Version of above for when we have to branch out-of-line */ | ||
347 | #define STD_EXCEPTION_HV_OOL(vec, label) \ | ||
348 | .globl label##_hv; \ | ||
349 | label##_hv: \ | ||
350 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec); \ | ||
351 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV) | ||
352 | |||
283 | #define STD_RELON_EXCEPTION_PSERIES(loc, vec, label) \ | 353 | #define STD_RELON_EXCEPTION_PSERIES(loc, vec, label) \ |
284 | . = loc; \ | 354 | . = loc; \ |
285 | .globl label##_relon_pSeries; \ | 355 | .globl label##_relon_pSeries; \ |
286 | label##_relon_pSeries: \ | 356 | label##_relon_pSeries: \ |
287 | HMT_MEDIUM; \ | 357 | HMT_MEDIUM_PPR_DISCARD; \ |
288 | /* No guest interrupts come through here */ \ | 358 | /* No guest interrupts come through here */ \ |
289 | SET_SCRATCH0(r13); /* save r13 */ \ | 359 | SET_SCRATCH0(r13); /* save r13 */ \ |
290 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 360 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
291 | EXC_STD, KVMTEST_PR, vec) | 361 | EXC_STD, KVMTEST_PR, vec) |
292 | 362 | ||
363 | #define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label) \ | ||
364 | .globl label##_relon_pSeries; \ | ||
365 | label##_relon_pSeries: \ | ||
366 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ | ||
367 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD) | ||
368 | |||
293 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ | 369 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ |
294 | . = loc; \ | 370 | . = loc; \ |
295 | .globl label##_relon_hv; \ | 371 | .globl label##_relon_hv; \ |
296 | label##_relon_hv: \ | 372 | label##_relon_hv: \ |
297 | HMT_MEDIUM; \ | 373 | HMT_MEDIUM_PPR_DISCARD; \ |
298 | /* No guest interrupts come through here */ \ | 374 | /* No guest interrupts come through here */ \ |
299 | SET_SCRATCH0(r13); /* save r13 */ \ | 375 | SET_SCRATCH0(r13); /* save r13 */ \ |
300 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 376 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
301 | EXC_HV, KVMTEST, vec) | 377 | EXC_HV, KVMTEST, vec) |
302 | 378 | ||
379 | #define STD_RELON_EXCEPTION_HV_OOL(vec, label) \ | ||
380 | .globl label##_relon_hv; \ | ||
381 | label##_relon_hv: \ | ||
382 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec); \ | ||
383 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV) | ||
384 | |||
303 | /* This associate vector numbers with bits in paca->irq_happened */ | 385 | /* This associate vector numbers with bits in paca->irq_happened */ |
304 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE | 386 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE |
305 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE | 387 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE |
306 | #define SOFTEN_VALUE_0x900 PACA_IRQ_DEC | 388 | #define SOFTEN_VALUE_0x900 PACA_IRQ_DEC |
307 | #define SOFTEN_VALUE_0x982 PACA_IRQ_DEC | 389 | #define SOFTEN_VALUE_0x982 PACA_IRQ_DEC |
390 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL | ||
391 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL | ||
392 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL | ||
308 | 393 | ||
309 | #define __SOFTEN_TEST(h, vec) \ | 394 | #define __SOFTEN_TEST(h, vec) \ |
310 | lbz r10,PACASOFTIRQEN(r13); \ | 395 | lbz r10,PACASOFTIRQEN(r13); \ |
@@ -329,10 +414,12 @@ label##_relon_hv: \ | |||
329 | #define SOFTEN_NOTEST_HV(vec) _SOFTEN_TEST(EXC_HV, vec) | 414 | #define SOFTEN_NOTEST_HV(vec) _SOFTEN_TEST(EXC_HV, vec) |
330 | 415 | ||
331 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ | 416 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ |
332 | HMT_MEDIUM; \ | 417 | HMT_MEDIUM_PPR_DISCARD; \ |
333 | SET_SCRATCH0(r13); /* save r13 */ \ | 418 | SET_SCRATCH0(r13); /* save r13 */ \ |
334 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | 419 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ |
420 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | ||
335 | EXCEPTION_PROLOG_PSERIES_1(label##_common, h); | 421 | EXCEPTION_PROLOG_PSERIES_1(label##_common, h); |
422 | |||
336 | #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ | 423 | #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ |
337 | __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) | 424 | __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) |
338 | 425 | ||
@@ -350,9 +437,16 @@ label##_hv: \ | |||
350 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ | 437 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ |
351 | EXC_HV, SOFTEN_TEST_HV) | 438 | EXC_HV, SOFTEN_TEST_HV) |
352 | 439 | ||
440 | #define MASKABLE_EXCEPTION_HV_OOL(vec, label) \ | ||
441 | .globl label##_hv; \ | ||
442 | label##_hv: \ | ||
443 | EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec); \ | ||
444 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); | ||
445 | |||
353 | #define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | 446 | #define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ |
354 | HMT_MEDIUM; \ | 447 | HMT_MEDIUM_PPR_DISCARD; \ |
355 | SET_SCRATCH0(r13); /* save r13 */ \ | 448 | SET_SCRATCH0(r13); /* save r13 */ \ |
449 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ | ||
356 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | 450 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ |
357 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); | 451 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); |
358 | #define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | 452 | #define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ |
@@ -372,6 +466,12 @@ label##_relon_hv: \ | |||
372 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ | 466 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ |
373 | EXC_HV, SOFTEN_NOTEST_HV) | 467 | EXC_HV, SOFTEN_NOTEST_HV) |
374 | 468 | ||
469 | #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label) \ | ||
470 | .globl label##_relon_hv; \ | ||
471 | label##_relon_hv: \ | ||
472 | EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec); \ | ||
473 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); | ||
474 | |||
375 | /* | 475 | /* |
376 | * Our exception common code can be passed various "additions" | 476 | * Our exception common code can be passed various "additions" |
377 | * to specify the behaviour of interrupts, whether to kick the | 477 | * to specify the behaviour of interrupts, whether to kick the |