diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 90 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 25 |
2 files changed, 115 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 9258daac4964..10787d3673ac 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -48,6 +48,35 @@ | |||
48 | #define EX_LR 72 | 48 | #define EX_LR 72 |
49 | #define EX_CFAR 80 | 49 | #define EX_CFAR 80 |
50 | 50 | ||
51 | #ifdef CONFIG_RELOCATABLE | ||
52 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
53 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ | ||
54 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | ||
55 | LOAD_HANDLER(r12,label); \ | ||
56 | mtlr r12; \ | ||
57 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | ||
58 | li r10,MSR_RI; \ | ||
59 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | ||
60 | blr; | ||
61 | #else | ||
62 | /* If not relocatable, we can jump directly -- and save messing with LR */ | ||
63 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
64 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | ||
65 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | ||
66 | li r10,MSR_RI; \ | ||
67 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | ||
68 | b label; | ||
69 | #endif | ||
70 | |||
71 | /* | ||
72 | * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on | ||
73 | * so no need to rfid. Save lr in case we're CONFIG_RELOCATABLE, in which | ||
74 | * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. | ||
75 | */ | ||
76 | #define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec) \ | ||
77 | EXCEPTION_PROLOG_1(area, extra, vec); \ | ||
78 | EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) | ||
79 | |||
51 | /* | 80 | /* |
52 | * We're short on space and time in the exception prolog, so we can't | 81 | * We're short on space and time in the exception prolog, so we can't |
53 | * use the normal SET_REG_IMMEDIATE macro. Normally we just need the | 82 | * use the normal SET_REG_IMMEDIATE macro. Normally we just need the |
@@ -62,6 +91,22 @@ | |||
62 | #define EXC_HV H | 91 | #define EXC_HV H |
63 | #define EXC_STD | 92 | #define EXC_STD |
64 | 93 | ||
94 | #if defined(CONFIG_RELOCATABLE) | ||
95 | /* | ||
96 | * If we support interrupts with relocation on AND we're a relocatable | ||
97 | * kernel, we need to use LR to get to the 2nd level handler. So, save/restore | ||
98 | * it when required. | ||
99 | */ | ||
100 | #define SAVE_LR(reg, area) mflr reg ; std reg,area+EX_LR(r13) | ||
101 | #define GET_LR(reg, area) ld reg,area+EX_LR(r13) | ||
102 | #define RESTORE_LR(reg, area) ld reg,area+EX_LR(r13) ; mtlr reg | ||
103 | #else | ||
104 | /* ...else LR is unused and in register. */ | ||
105 | #define SAVE_LR(reg, area) | ||
106 | #define GET_LR(reg, area) mflr reg | ||
107 | #define RESTORE_LR(reg, area) | ||
108 | #endif | ||
109 | |||
65 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ | 110 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ |
66 | GET_PACA(r13); \ | 111 | GET_PACA(r13); \ |
67 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | 112 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ |
@@ -233,6 +278,26 @@ label##_hv: \ | |||
233 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 278 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
234 | EXC_HV, KVMTEST, vec) | 279 | EXC_HV, KVMTEST, vec) |
235 | 280 | ||
281 | #define STD_RELON_EXCEPTION_PSERIES(loc, vec, label) \ | ||
282 | . = loc; \ | ||
283 | .globl label##_relon_pSeries; \ | ||
284 | label##_relon_pSeries: \ | ||
285 | HMT_MEDIUM; \ | ||
286 | /* No guest interrupts come through here */ \ | ||
287 | SET_SCRATCH0(r13); /* save r13 */ \ | ||
288 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | ||
289 | EXC_STD, KVMTEST_PR, vec) | ||
290 | |||
291 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ | ||
292 | . = loc; \ | ||
293 | .globl label##_relon_hv; \ | ||
294 | label##_relon_hv: \ | ||
295 | HMT_MEDIUM; \ | ||
296 | /* No guest interrupts come through here */ \ | ||
297 | SET_SCRATCH0(r13); /* save r13 */ \ | ||
298 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | ||
299 | EXC_HV, KVMTEST, vec) | ||
300 | |||
236 | /* This associate vector numbers with bits in paca->irq_happened */ | 301 | /* This associate vector numbers with bits in paca->irq_happened */ |
237 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE | 302 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE |
238 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE | 303 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE |
@@ -258,6 +323,9 @@ label##_hv: \ | |||
258 | KVMTEST(vec); \ | 323 | KVMTEST(vec); \ |
259 | _SOFTEN_TEST(EXC_STD, vec) | 324 | _SOFTEN_TEST(EXC_STD, vec) |
260 | 325 | ||
326 | #define SOFTEN_NOTEST_PR(vec) _SOFTEN_TEST(EXC_STD, vec) | ||
327 | #define SOFTEN_NOTEST_HV(vec) _SOFTEN_TEST(EXC_HV, vec) | ||
328 | |||
261 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ | 329 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ |
262 | HMT_MEDIUM; \ | 330 | HMT_MEDIUM; \ |
263 | SET_SCRATCH0(r13); /* save r13 */ \ | 331 | SET_SCRATCH0(r13); /* save r13 */ \ |
@@ -280,6 +348,28 @@ label##_hv: \ | |||
280 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ | 348 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ |
281 | EXC_HV, SOFTEN_TEST_HV) | 349 | EXC_HV, SOFTEN_TEST_HV) |
282 | 350 | ||
351 | #define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | ||
352 | HMT_MEDIUM; \ | ||
353 | SET_SCRATCH0(r13); /* save r13 */ \ | ||
354 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | ||
355 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); | ||
356 | #define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | ||
357 | __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) | ||
358 | |||
359 | #define MASKABLE_RELON_EXCEPTION_PSERIES(loc, vec, label) \ | ||
360 | . = loc; \ | ||
361 | .globl label##_relon_pSeries; \ | ||
362 | label##_relon_pSeries: \ | ||
363 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ | ||
364 | EXC_STD, SOFTEN_NOTEST_PR) | ||
365 | |||
366 | #define MASKABLE_RELON_EXCEPTION_HV(loc, vec, label) \ | ||
367 | . = loc; \ | ||
368 | .globl label##_relon_hv; \ | ||
369 | label##_relon_hv: \ | ||
370 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ | ||
371 | EXC_HV, SOFTEN_NOTEST_HV) | ||
372 | |||
283 | /* | 373 | /* |
284 | * Our exception common code can be passed various "additions" | 374 | * Our exception common code can be passed various "additions" |
285 | * to specify the behaviour of interrupts, whether to kick the | 375 | * to specify the behaviour of interrupts, whether to kick the |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 85b3c7e9dd6d..4dc1a045052a 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -62,6 +62,31 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | |||
62 | rfid ; \ | 62 | rfid ; \ |
63 | b . ; /* prevent speculative execution */ | 63 | b . ; /* prevent speculative execution */ |
64 | 64 | ||
65 | #if defined(CONFIG_RELOCATABLE) | ||
66 | /* | ||
67 | * We can't branch directly; in the direct case we use LR | ||
68 | * and system_call_entry restores LR. (We thus need to move | ||
69 | * LR to r10 in the RFID case too.) | ||
70 | */ | ||
71 | #define SYSCALL_PSERIES_2_DIRECT \ | ||
72 | mflr r10 ; \ | ||
73 | ld r12,PACAKBASE(r13) ; \ | ||
74 | LOAD_HANDLER(r12, system_call_entry_direct) ; \ | ||
75 | mtlr r12 ; \ | ||
76 | mfspr r12,SPRN_SRR1 ; \ | ||
77 | /* Re-use of r13... No spare regs to do this */ \ | ||
78 | li r13,MSR_RI ; \ | ||
79 | mtmsrd r13,1 ; \ | ||
80 | GET_PACA(r13) ; /* get r13 back */ \ | ||
81 | blr ; | ||
82 | #else | ||
83 | /* We can branch directly */ | ||
84 | #define SYSCALL_PSERIES_2_DIRECT \ | ||
85 | mfspr r12,SPRN_SRR1 ; \ | ||
86 | li r10,MSR_RI ; \ | ||
87 | mtmsrd r10,1 ; /* Set RI (EE=0) */ \ | ||
88 | b system_call_entry_direct ; | ||
89 | #endif | ||
65 | 90 | ||
66 | /* | 91 | /* |
67 | * This is the start of the interrupt handlers for pSeries | 92 | * This is the start of the interrupt handlers for pSeries |