aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/exception-64s.h90
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S25
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; \
284label##_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; \
294label##_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; \
362label##_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; \
369label##_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