diff options
author | Paul Mackerras <paulus@samba.org> | 2011-06-28 20:18:26 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-07-12 06:16:48 -0400 |
commit | b01c8b54a1a271c0fc4243845927fe1d250767a3 (patch) | |
tree | 4e818a41d602aa07cbdc06eca9372b9b95c533a4 /arch/powerpc/include | |
parent | f05ed4d56e9cff1c46d2b3049ba0c72e7e29392f (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.h | 121 |
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) \ | ||
104 | do_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) \ | ||
113 | do_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; \ | ||
122 | 89: 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; \ |
165 | label##_pSeries: \ | 209 | label##_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; \ |
174 | label##_hv: \ | 218 | label##_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; \ |
210 | label##_pSeries: \ | 249 | label##_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; \ |
216 | label##_hv: \ | 256 | label##_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 \ |