aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-06-28 20:18:26 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 06:16:48 -0400
commitb01c8b54a1a271c0fc4243845927fe1d250767a3 (patch)
tree4e818a41d602aa07cbdc06eca9372b9b95c533a4 /arch/powerpc/include
parentf05ed4d56e9cff1c46d2b3049ba0c72e7e29392f (diff)
powerpc, KVM: Rework KVM checks in first-level interrupt handlers
Instead of branching out-of-line with the DO_KVM macro to check if we are in a KVM guest at the time of an interrupt, this moves the KVM check inline in the first-level interrupt handlers. This speeds up the non-KVM case and makes sure that none of the interrupt handlers are missing the check. Because the first-level interrupt handlers are now larger, some things had to be move out of line in exceptions-64s.S. This all necessitated some minor changes to the interrupt entry code in KVM. This also streamlines the book3s_32 KVM test. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/include')
-rw-r--r--arch/powerpc/include/asm/exception-64s.h121
1 files changed, 81 insertions, 40 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index f5dfe3411f64..b6a3a443fbde 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -61,19 +61,22 @@
61#define EXC_HV H 61#define EXC_HV H
62#define EXC_STD 62#define EXC_STD
63 63
64#define EXCEPTION_PROLOG_1(area) \ 64#define __EXCEPTION_PROLOG_1(area, extra, vec) \
65 GET_PACA(r13); \ 65 GET_PACA(r13); \
66 std r9,area+EX_R9(r13); /* save r9 - r12 */ \ 66 std r9,area+EX_R9(r13); /* save r9 - r12 */ \
67 std r10,area+EX_R10(r13); \ 67 std r10,area+EX_R10(r13); \
68 std r11,area+EX_R11(r13); \
69 std r12,area+EX_R12(r13); \
70 BEGIN_FTR_SECTION_NESTED(66); \ 68 BEGIN_FTR_SECTION_NESTED(66); \
71 mfspr r10,SPRN_CFAR; \ 69 mfspr r10,SPRN_CFAR; \
72 std r10,area+EX_CFAR(r13); \ 70 std r10,area+EX_CFAR(r13); \
73 END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ 71 END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \
74 GET_SCRATCH0(r9); \ 72 mfcr r9; \
75 std r9,area+EX_R13(r13); \ 73 extra(vec); \
76 mfcr r9 74 std r11,area+EX_R11(r13); \
75 std r12,area+EX_R12(r13); \
76 GET_SCRATCH0(r10); \
77 std r10,area+EX_R13(r13)
78#define EXCEPTION_PROLOG_1(area, extra, vec) \
79 __EXCEPTION_PROLOG_1(area, extra, vec)
77 80
78#define __EXCEPTION_PROLOG_PSERIES_1(label, h) \ 81#define __EXCEPTION_PROLOG_PSERIES_1(label, h) \
79 ld r12,PACAKBASE(r13); /* get high part of &label */ \ 82 ld r12,PACAKBASE(r13); /* get high part of &label */ \
@@ -85,13 +88,54 @@
85 mtspr SPRN_##h##SRR1,r10; \ 88 mtspr SPRN_##h##SRR1,r10; \
86 h##rfid; \ 89 h##rfid; \
87 b . /* prevent speculative execution */ 90 b . /* prevent speculative execution */
88#define EXCEPTION_PROLOG_PSERIES_1(label, h) \ 91#define EXCEPTION_PROLOG_PSERIES_1(label, h) \
89 __EXCEPTION_PROLOG_PSERIES_1(label, h) 92 __EXCEPTION_PROLOG_PSERIES_1(label, h)
90 93
91#define EXCEPTION_PROLOG_PSERIES(area, label, h) \ 94#define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \
92 EXCEPTION_PROLOG_1(area); \ 95 EXCEPTION_PROLOG_1(area, extra, vec); \
93 EXCEPTION_PROLOG_PSERIES_1(label, h); 96 EXCEPTION_PROLOG_PSERIES_1(label, h);
94 97
98#define __KVMTEST(n) \
99 lbz r10,PACA_KVM_SVCPU+SVCPU_IN_GUEST(r13); \
100 cmpwi r10,0; \
101 bne do_kvm_##n
102
103#define __KVM_HANDLER(area, h, n) \
104do_kvm_##n: \
105 ld r10,area+EX_R10(r13); \
106 stw r9,PACA_KVM_SVCPU+SVCPU_SCRATCH1(r13); \
107 ld r9,area+EX_R9(r13); \
108 std r12,PACA_KVM_SVCPU+SVCPU_SCRATCH0(r13); \
109 li r12,n; \
110 b kvmppc_interrupt
111
112#define __KVM_HANDLER_SKIP(area, h, n) \
113do_kvm_##n: \
114 cmpwi r10,KVM_GUEST_MODE_SKIP; \
115 ld r10,area+EX_R10(r13); \
116 beq 89f; \
117 stw r9,PACA_KVM_SVCPU+SVCPU_SCRATCH1(r13); \
118 ld r9,area+EX_R9(r13); \
119 std r12,PACA_KVM_SVCPU+SVCPU_SCRATCH0(r13); \
120 li r12,n; \
121 b kvmppc_interrupt; \
12289: mtocrf 0x80,r9; \
123 ld r9,area+EX_R9(r13); \
124 b kvmppc_skip_##h##interrupt
125
126#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
127#define KVMTEST(n) __KVMTEST(n)
128#define KVM_HANDLER(area, h, n) __KVM_HANDLER(area, h, n)
129#define KVM_HANDLER_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n)
130
131#else
132#define KVMTEST(n)
133#define KVM_HANDLER(area, h, n)
134#define KVM_HANDLER_SKIP(area, h, n)
135#endif
136
137#define NOTEST(n)
138
95/* 139/*
96 * The common exception prolog is used for all except a few exceptions 140 * The common exception prolog is used for all except a few exceptions
97 * such as a segment miss on a kernel address. We have to be prepared 141 * such as a segment miss on a kernel address. We have to be prepared
@@ -164,57 +208,54 @@
164 .globl label##_pSeries; \ 208 .globl label##_pSeries; \
165label##_pSeries: \ 209label##_pSeries: \
166 HMT_MEDIUM; \ 210 HMT_MEDIUM; \
167 DO_KVM vec; \
168 SET_SCRATCH0(r13); /* save r13 */ \ 211 SET_SCRATCH0(r13); /* save r13 */ \
169 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_STD) 212 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
213 EXC_STD, KVMTEST, vec)
170 214
171#define STD_EXCEPTION_HV(loc, vec, label) \ 215#define STD_EXCEPTION_HV(loc, vec, label) \
172 . = loc; \ 216 . = loc; \
173 .globl label##_hv; \ 217 .globl label##_hv; \
174label##_hv: \ 218label##_hv: \
175 HMT_MEDIUM; \ 219 HMT_MEDIUM; \
176 DO_KVM vec; \ 220 SET_SCRATCH0(r13); /* save r13 */ \
177 SET_SCRATCH0(r13); /* save r13 */ \ 221 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
178 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, EXC_HV) 222 EXC_HV, KVMTEST, vec)
179 223
180#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h) \ 224#define __SOFTEN_TEST(h) \
181 HMT_MEDIUM; \
182 DO_KVM vec; \
183 SET_SCRATCH0(r13); /* save r13 */ \
184 GET_PACA(r13); \
185 std r9,PACA_EXGEN+EX_R9(r13); /* save r9, r10 */ \
186 std r10,PACA_EXGEN+EX_R10(r13); \
187 lbz r10,PACASOFTIRQEN(r13); \ 225 lbz r10,PACASOFTIRQEN(r13); \
188 mfcr r9; \
189 cmpwi r10,0; \ 226 cmpwi r10,0; \
190 beq masked_##h##interrupt; \ 227 beq masked_##h##interrupt
191 GET_SCRATCH0(r10); \ 228#define _SOFTEN_TEST(h) __SOFTEN_TEST(h)
192 std r10,PACA_EXGEN+EX_R13(r13); \ 229
193 std r11,PACA_EXGEN+EX_R11(r13); \ 230#define SOFTEN_TEST(vec) \
194 std r12,PACA_EXGEN+EX_R12(r13); \ 231 KVMTEST(vec); \
195 ld r12,PACAKBASE(r13); /* get high part of &label */ \ 232 _SOFTEN_TEST(EXC_STD)
196 ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ 233
197 mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ 234#define SOFTEN_TEST_HV(vec) \
198 LOAD_HANDLER(r12,label##_common) \ 235 KVMTEST(vec); \
199 mtspr SPRN_##h##SRR0,r12; \ 236 _SOFTEN_TEST(EXC_HV)
200 mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ 237
201 mtspr SPRN_##h##SRR1,r10; \ 238#define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \
202 h##rfid; \ 239 HMT_MEDIUM; \
203 b . /* prevent speculative execution */ 240 SET_SCRATCH0(r13); /* save r13 */ \
204#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h) \ 241 __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \
205 __MASKABLE_EXCEPTION_PSERIES(vec, label, h) 242 EXCEPTION_PROLOG_PSERIES_1(label##_common, h);
243#define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \
244 __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra)
206 245
207#define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \ 246#define MASKABLE_EXCEPTION_PSERIES(loc, vec, label) \
208 . = loc; \ 247 . = loc; \
209 .globl label##_pSeries; \ 248 .globl label##_pSeries; \
210label##_pSeries: \ 249label##_pSeries: \
211 _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_STD) 250 _MASKABLE_EXCEPTION_PSERIES(vec, label, \
251 EXC_STD, SOFTEN_TEST)
212 252
213#define MASKABLE_EXCEPTION_HV(loc, vec, label) \ 253#define MASKABLE_EXCEPTION_HV(loc, vec, label) \
214 . = loc; \ 254 . = loc; \
215 .globl label##_hv; \ 255 .globl label##_hv; \
216label##_hv: \ 256label##_hv: \
217 _MASKABLE_EXCEPTION_PSERIES(vec, label, EXC_HV) 257 _MASKABLE_EXCEPTION_PSERIES(vec, label, \
258 EXC_HV, SOFTEN_TEST_HV)
218 259
219#ifdef CONFIG_PPC_ISERIES 260#ifdef CONFIG_PPC_ISERIES
220#define DISABLE_INTS \ 261#define DISABLE_INTS \