aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm/exception-64s.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/include/asm/exception-64s.h')
-rw-r--r--arch/powerpc/include/asm/exception-64s.h138
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) \
119BEGIN_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); \
123END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940)
124
125#define RESTORE_PPR_PACA(area, ra) \
126BEGIN_FTR_SECTION_NESTED(941) \
127 ld ra,area+EX_PPR(r13); \
128 mtspr SPRN_PPR,ra; \
129END_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 \
136BEGIN_FTR_SECTION_NESTED(942) \
137 HMT_MEDIUM; \
138END_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) \
144BEGIN_FTR_SECTION_NESTED(943) \
145 mfspr ra,spr; \
146END_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) \
152BEGIN_FTR_SECTION_NESTED(943) \
153 std ra,offset(r13); \
154END_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) \
151do_kvm_##n: \ 201do_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); \
2844: 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; \
268label##_pSeries: \ 324label##_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; \
333label##_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; \
277label##_hv: \ 340label##_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; \
349label##_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; \
286label##_relon_pSeries: \ 356label##_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; \
365label##_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; \
296label##_relon_hv: \ 372label##_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; \
381label##_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; \
442label##_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; \
471label##_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