diff options
author | Alexander Graf <agraf@suse.de> | 2010-01-07 20:58:03 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:35:48 -0500 |
commit | 7e57cba06074da84d7c24d8c3f44040d2d8c88ac (patch) | |
tree | e99519ca301b887de4d689421e7a954f1c7792e4 /arch/powerpc/kvm | |
parent | 992b5b29b5ae254c416c62faf98d59a6cf970027 (diff) |
KVM: PPC: Use PACA backed shadow vcpu
We're being horribly racy right now. All the entry and exit code hijacks
random fields from the PACA that could easily be used by different code in
case we get interrupted, for example by a #MC or even page fault.
After discussing this with Ben, we figured it's best to reserve some more
space in the PACA and just shove off some vcpu state to there.
That way we can drastically improve the readability of the code, make it
less racy and less complex.
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_interrupts.S | 216 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_rmhandlers.S | 32 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_slb.S | 150 |
4 files changed, 175 insertions, 227 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 09ba8dbaabab..3e06eae3f2c8 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -66,12 +66,16 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) | |||
66 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 66 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) |
67 | { | 67 | { |
68 | memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb)); | 68 | memcpy(get_paca()->kvm_slb, to_book3s(vcpu)->slb_shadow, sizeof(get_paca()->kvm_slb)); |
69 | memcpy(&get_paca()->shadow_vcpu, &to_book3s(vcpu)->shadow_vcpu, | ||
70 | sizeof(get_paca()->shadow_vcpu)); | ||
69 | get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max; | 71 | get_paca()->kvm_slb_max = to_book3s(vcpu)->slb_shadow_max; |
70 | } | 72 | } |
71 | 73 | ||
72 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 74 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) |
73 | { | 75 | { |
74 | memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb)); | 76 | memcpy(to_book3s(vcpu)->slb_shadow, get_paca()->kvm_slb, sizeof(get_paca()->kvm_slb)); |
77 | memcpy(&to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu, | ||
78 | sizeof(get_paca()->shadow_vcpu)); | ||
75 | to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max; | 79 | to_book3s(vcpu)->slb_shadow_max = get_paca()->kvm_slb_max; |
76 | } | 80 | } |
77 | 81 | ||
diff --git a/arch/powerpc/kvm/book3s_64_interrupts.S b/arch/powerpc/kvm/book3s_64_interrupts.S index d95d0d967d56..66e3b1179b32 100644 --- a/arch/powerpc/kvm/book3s_64_interrupts.S +++ b/arch/powerpc/kvm/book3s_64_interrupts.S | |||
@@ -28,11 +28,6 @@ | |||
28 | #define ULONG_SIZE 8 | 28 | #define ULONG_SIZE 8 |
29 | #define VCPU_GPR(n) (VCPU_GPRS + (n * ULONG_SIZE)) | 29 | #define VCPU_GPR(n) (VCPU_GPRS + (n * ULONG_SIZE)) |
30 | 30 | ||
31 | .macro mfpaca tmp_reg, src_reg, offset, vcpu_reg | ||
32 | ld \tmp_reg, (PACA_EXMC+\offset)(r13) | ||
33 | std \tmp_reg, VCPU_GPR(\src_reg)(\vcpu_reg) | ||
34 | .endm | ||
35 | |||
36 | .macro DISABLE_INTERRUPTS | 31 | .macro DISABLE_INTERRUPTS |
37 | mfmsr r0 | 32 | mfmsr r0 |
38 | rldicl r0,r0,48,1 | 33 | rldicl r0,r0,48,1 |
@@ -92,37 +87,30 @@ kvm_start_entry: | |||
92 | /* Load non-volatile guest state from the vcpu */ | 87 | /* Load non-volatile guest state from the vcpu */ |
93 | VCPU_LOAD_NVGPRS(r4) | 88 | VCPU_LOAD_NVGPRS(r4) |
94 | 89 | ||
95 | kvm_start_lightweight: | ||
96 | |||
97 | ld r9, VCPU_PC(r4) /* r9 = vcpu->arch.pc */ | ||
98 | ld r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */ | ||
99 | |||
100 | DISABLE_INTERRUPTS | ||
101 | |||
102 | /* Save R1/R2 in the PACA */ | 90 | /* Save R1/R2 in the PACA */ |
103 | std r1, PACAR1(r13) | 91 | std r1, PACA_KVM_HOST_R1(r13) |
104 | std r2, (PACA_EXMC+EX_SRR0)(r13) | 92 | std r2, PACA_KVM_HOST_R2(r13) |
93 | |||
94 | /* XXX swap in/out on load? */ | ||
105 | ld r3, VCPU_HIGHMEM_HANDLER(r4) | 95 | ld r3, VCPU_HIGHMEM_HANDLER(r4) |
106 | std r3, PACASAVEDMSR(r13) | 96 | std r3, PACA_KVM_VMHANDLER(r13) |
107 | 97 | ||
108 | ld r3, VCPU_TRAMPOLINE_ENTER(r4) | 98 | ld r3, VCPU_TRAMPOLINE_ENTER(r4) |
109 | mtsrr0 r3 | 99 | std r3, PACA_KVM_RMHANDLER(r13) |
110 | 100 | ||
111 | LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)) | 101 | kvm_start_lightweight: |
112 | mtsrr1 r3 | ||
113 | 102 | ||
114 | /* Load guest state in the respective registers */ | 103 | ld r9, VCPU_PC(r4) /* r9 = vcpu->arch.pc */ |
115 | lwz r3, VCPU_CR(r4) /* r3 = vcpu->arch.cr */ | 104 | ld r10, VCPU_SHADOW_MSR(r4) /* r10 = vcpu->arch.shadow_msr */ |
116 | stw r3, (PACA_EXMC + EX_CCR)(r13) | ||
117 | 105 | ||
106 | /* Load some guest state in the respective registers */ | ||
118 | ld r3, VCPU_CTR(r4) /* r3 = vcpu->arch.ctr */ | 107 | ld r3, VCPU_CTR(r4) /* r3 = vcpu->arch.ctr */ |
119 | mtctr r3 /* CTR = r3 */ | 108 | mtctr r3 /* CTR = r3 */ |
120 | 109 | ||
121 | ld r3, VCPU_LR(r4) /* r3 = vcpu->arch.lr */ | 110 | ld r3, VCPU_LR(r4) /* r3 = vcpu->arch.lr */ |
122 | mtlr r3 /* LR = r3 */ | 111 | mtlr r3 /* LR = r3 */ |
123 | 112 | ||
124 | ld r3, VCPU_XER(r4) /* r3 = vcpu->arch.xer */ | 113 | DISABLE_INTERRUPTS |
125 | std r3, (PACA_EXMC + EX_R3)(r13) | ||
126 | 114 | ||
127 | /* Some guests may need to have dcbz set to 32 byte length. | 115 | /* Some guests may need to have dcbz set to 32 byte length. |
128 | * | 116 | * |
@@ -142,34 +130,21 @@ kvm_start_lightweight: | |||
142 | mtspr SPRN_HID5,r3 | 130 | mtspr SPRN_HID5,r3 |
143 | 131 | ||
144 | no_dcbz32_on: | 132 | no_dcbz32_on: |
145 | /* Load guest GPRs */ | ||
146 | |||
147 | ld r3, VCPU_GPR(r9)(r4) | ||
148 | std r3, (PACA_EXMC + EX_R9)(r13) | ||
149 | ld r3, VCPU_GPR(r10)(r4) | ||
150 | std r3, (PACA_EXMC + EX_R10)(r13) | ||
151 | ld r3, VCPU_GPR(r11)(r4) | ||
152 | std r3, (PACA_EXMC + EX_R11)(r13) | ||
153 | ld r3, VCPU_GPR(r12)(r4) | ||
154 | std r3, (PACA_EXMC + EX_R12)(r13) | ||
155 | ld r3, VCPU_GPR(r13)(r4) | ||
156 | std r3, (PACA_EXMC + EX_R13)(r13) | ||
157 | |||
158 | ld r0, VCPU_GPR(r0)(r4) | ||
159 | ld r1, VCPU_GPR(r1)(r4) | ||
160 | ld r2, VCPU_GPR(r2)(r4) | ||
161 | ld r3, VCPU_GPR(r3)(r4) | ||
162 | ld r5, VCPU_GPR(r5)(r4) | ||
163 | ld r6, VCPU_GPR(r6)(r4) | ||
164 | ld r7, VCPU_GPR(r7)(r4) | ||
165 | ld r8, VCPU_GPR(r8)(r4) | ||
166 | ld r4, VCPU_GPR(r4)(r4) | ||
167 | 133 | ||
168 | /* This sets the Magic value for the trampoline */ | 134 | /* This sets the Magic value for the trampoline */ |
169 | 135 | ||
136 | /* XXX this needs to move into a safe function, so we can | ||
137 | be sure we don't get any interrupts */ | ||
138 | |||
170 | li r11, 1 | 139 | li r11, 1 |
171 | stb r11, PACA_KVM_IN_GUEST(r13) | 140 | stb r11, PACA_KVM_IN_GUEST(r13) |
172 | 141 | ||
142 | ld r3, PACA_KVM_RMHANDLER(r13) | ||
143 | mtsrr0 r3 | ||
144 | |||
145 | LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)) | ||
146 | mtsrr1 r3 | ||
147 | |||
173 | /* Jump to SLB patching handlder and into our guest */ | 148 | /* Jump to SLB patching handlder and into our guest */ |
174 | RFI | 149 | RFI |
175 | 150 | ||
@@ -185,60 +160,31 @@ kvmppc_handler_highmem: | |||
185 | /* | 160 | /* |
186 | * Register usage at this point: | 161 | * Register usage at this point: |
187 | * | 162 | * |
188 | * R00 = guest R13 | 163 | * R0 = guest last inst |
189 | * R01 = host R1 | 164 | * R1 = host R1 |
190 | * R02 = host R2 | 165 | * R2 = host R2 |
191 | * R10 = guest PC | 166 | * R3 = guest PC |
192 | * R11 = guest MSR | 167 | * R4 = guest MSR |
193 | * R12 = exit handler id | 168 | * R5 = guest DAR |
194 | * R13 = PACA | 169 | * R6 = guest DSISR |
195 | * PACA.exmc.R9 = guest R1 | 170 | * R13 = PACA |
196 | * PACA.exmc.R10 = guest R10 | 171 | * PACA.KVM.* = guest * |
197 | * PACA.exmc.R11 = guest R11 | ||
198 | * PACA.exmc.R12 = guest R12 | ||
199 | * PACA.exmc.R13 = guest R2 | ||
200 | * PACA.exmc.DAR = guest DAR | ||
201 | * PACA.exmc.DSISR = guest DSISR | ||
202 | * PACA.exmc.LR = guest instruction | ||
203 | * PACA.exmc.CCR = guest CR | ||
204 | * PACA.exmc.SRR0 = guest R0 | ||
205 | * | 172 | * |
206 | */ | 173 | */ |
207 | 174 | ||
208 | std r3, (PACA_EXMC+EX_R3)(r13) | 175 | /* R7 = vcpu */ |
176 | ld r7, GPR4(r1) | ||
209 | 177 | ||
210 | /* save the exit id in R3 */ | 178 | /* Now save the guest state */ |
211 | mr r3, r12 | ||
212 | 179 | ||
213 | /* R12 = vcpu */ | 180 | stw r0, VCPU_LAST_INST(r7) |
214 | ld r12, GPR4(r1) | ||
215 | 181 | ||
216 | /* Now save the guest state */ | 182 | std r3, VCPU_PC(r7) |
183 | std r4, VCPU_SHADOW_MSR(r7) | ||
184 | std r5, VCPU_FAULT_DEAR(r7) | ||
185 | std r6, VCPU_FAULT_DSISR(r7) | ||
217 | 186 | ||
218 | std r0, VCPU_GPR(r13)(r12) | 187 | ld r5, VCPU_HFLAGS(r7) |
219 | std r4, VCPU_GPR(r4)(r12) | ||
220 | std r5, VCPU_GPR(r5)(r12) | ||
221 | std r6, VCPU_GPR(r6)(r12) | ||
222 | std r7, VCPU_GPR(r7)(r12) | ||
223 | std r8, VCPU_GPR(r8)(r12) | ||
224 | std r9, VCPU_GPR(r9)(r12) | ||
225 | |||
226 | /* get registers from PACA */ | ||
227 | mfpaca r5, r0, EX_SRR0, r12 | ||
228 | mfpaca r5, r3, EX_R3, r12 | ||
229 | mfpaca r5, r1, EX_R9, r12 | ||
230 | mfpaca r5, r10, EX_R10, r12 | ||
231 | mfpaca r5, r11, EX_R11, r12 | ||
232 | mfpaca r5, r12, EX_R12, r12 | ||
233 | mfpaca r5, r2, EX_R13, r12 | ||
234 | |||
235 | lwz r5, (PACA_EXMC+EX_LR)(r13) | ||
236 | stw r5, VCPU_LAST_INST(r12) | ||
237 | |||
238 | lwz r5, (PACA_EXMC+EX_CCR)(r13) | ||
239 | stw r5, VCPU_CR(r12) | ||
240 | |||
241 | ld r5, VCPU_HFLAGS(r12) | ||
242 | rldicl. r5, r5, 0, 63 /* CR = ((r5 & 1) == 0) */ | 188 | rldicl. r5, r5, 0, 63 /* CR = ((r5 & 1) == 0) */ |
243 | beq no_dcbz32_off | 189 | beq no_dcbz32_off |
244 | 190 | ||
@@ -248,58 +194,42 @@ kvmppc_handler_highmem: | |||
248 | 194 | ||
249 | no_dcbz32_off: | 195 | no_dcbz32_off: |
250 | 196 | ||
251 | std r14, VCPU_GPR(r14)(r12) | 197 | std r14, VCPU_GPR(r14)(r7) |
252 | std r15, VCPU_GPR(r15)(r12) | 198 | std r15, VCPU_GPR(r15)(r7) |
253 | std r16, VCPU_GPR(r16)(r12) | 199 | std r16, VCPU_GPR(r16)(r7) |
254 | std r17, VCPU_GPR(r17)(r12) | 200 | std r17, VCPU_GPR(r17)(r7) |
255 | std r18, VCPU_GPR(r18)(r12) | 201 | std r18, VCPU_GPR(r18)(r7) |
256 | std r19, VCPU_GPR(r19)(r12) | 202 | std r19, VCPU_GPR(r19)(r7) |
257 | std r20, VCPU_GPR(r20)(r12) | 203 | std r20, VCPU_GPR(r20)(r7) |
258 | std r21, VCPU_GPR(r21)(r12) | 204 | std r21, VCPU_GPR(r21)(r7) |
259 | std r22, VCPU_GPR(r22)(r12) | 205 | std r22, VCPU_GPR(r22)(r7) |
260 | std r23, VCPU_GPR(r23)(r12) | 206 | std r23, VCPU_GPR(r23)(r7) |
261 | std r24, VCPU_GPR(r24)(r12) | 207 | std r24, VCPU_GPR(r24)(r7) |
262 | std r25, VCPU_GPR(r25)(r12) | 208 | std r25, VCPU_GPR(r25)(r7) |
263 | std r26, VCPU_GPR(r26)(r12) | 209 | std r26, VCPU_GPR(r26)(r7) |
264 | std r27, VCPU_GPR(r27)(r12) | 210 | std r27, VCPU_GPR(r27)(r7) |
265 | std r28, VCPU_GPR(r28)(r12) | 211 | std r28, VCPU_GPR(r28)(r7) |
266 | std r29, VCPU_GPR(r29)(r12) | 212 | std r29, VCPU_GPR(r29)(r7) |
267 | std r30, VCPU_GPR(r30)(r12) | 213 | std r30, VCPU_GPR(r30)(r7) |
268 | std r31, VCPU_GPR(r31)(r12) | 214 | std r31, VCPU_GPR(r31)(r7) |
269 | 215 | ||
270 | /* Save guest PC (R10) */ | 216 | /* Save guest CTR */ |
271 | std r10, VCPU_PC(r12) | ||
272 | |||
273 | /* Save guest msr (R11) */ | ||
274 | std r11, VCPU_SHADOW_MSR(r12) | ||
275 | |||
276 | /* Save guest CTR (in R12) */ | ||
277 | mfctr r5 | 217 | mfctr r5 |
278 | std r5, VCPU_CTR(r12) | 218 | std r5, VCPU_CTR(r7) |
279 | 219 | ||
280 | /* Save guest LR */ | 220 | /* Save guest LR */ |
281 | mflr r5 | 221 | mflr r5 |
282 | std r5, VCPU_LR(r12) | 222 | std r5, VCPU_LR(r7) |
283 | |||
284 | /* Save guest XER */ | ||
285 | mfxer r5 | ||
286 | std r5, VCPU_XER(r12) | ||
287 | 223 | ||
288 | /* Save guest DAR */ | 224 | /* XXX convert to safe function call */ |
289 | ld r5, (PACA_EXMC+EX_DAR)(r13) | ||
290 | std r5, VCPU_FAULT_DEAR(r12) | ||
291 | |||
292 | /* Save guest DSISR */ | ||
293 | lwz r5, (PACA_EXMC+EX_DSISR)(r13) | ||
294 | std r5, VCPU_FAULT_DSISR(r12) | ||
295 | 225 | ||
296 | /* Restore host msr -> SRR1 */ | 226 | /* Restore host msr -> SRR1 */ |
297 | ld r7, VCPU_HOST_MSR(r12) | 227 | ld r6, VCPU_HOST_MSR(r7) |
298 | mtsrr1 r7 | 228 | mtsrr1 r6 |
299 | 229 | ||
300 | /* Restore host IP -> SRR0 */ | 230 | /* Restore host IP -> SRR0 */ |
301 | ld r6, VCPU_HOST_RETIP(r12) | 231 | ld r5, VCPU_HOST_RETIP(r7) |
302 | mtsrr0 r6 | 232 | mtsrr0 r5 |
303 | 233 | ||
304 | /* | 234 | /* |
305 | * For some interrupts, we need to call the real Linux | 235 | * For some interrupts, we need to call the real Linux |
@@ -311,9 +241,9 @@ no_dcbz32_off: | |||
311 | * r3 = address of interrupt handler (exit reason) | 241 | * r3 = address of interrupt handler (exit reason) |
312 | */ | 242 | */ |
313 | 243 | ||
314 | cmpwi r3, BOOK3S_INTERRUPT_EXTERNAL | 244 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
315 | beq call_linux_handler | 245 | beq call_linux_handler |
316 | cmpwi r3, BOOK3S_INTERRUPT_DECREMENTER | 246 | cmpwi r12, BOOK3S_INTERRUPT_DECREMENTER |
317 | beq call_linux_handler | 247 | beq call_linux_handler |
318 | 248 | ||
319 | /* Back to Interruptable Mode! (goto kvm_return_point) */ | 249 | /* Back to Interruptable Mode! (goto kvm_return_point) */ |
@@ -334,12 +264,12 @@ call_linux_handler: | |||
334 | * R7 VCPU_HOST_MSR | 264 | * R7 VCPU_HOST_MSR |
335 | */ | 265 | */ |
336 | 266 | ||
337 | mtlr r3 | 267 | mtlr r12 |
338 | 268 | ||
339 | ld r5, VCPU_TRAMPOLINE_LOWMEM(r12) | 269 | ld r4, VCPU_TRAMPOLINE_LOWMEM(r7) |
340 | mtsrr0 r5 | 270 | mtsrr0 r4 |
341 | LOAD_REG_IMMEDIATE(r5, MSR_KERNEL & ~(MSR_IR | MSR_DR)) | 271 | LOAD_REG_IMMEDIATE(r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)) |
342 | mtsrr1 r5 | 272 | mtsrr1 r3 |
343 | 273 | ||
344 | RFI | 274 | RFI |
345 | 275 | ||
@@ -350,7 +280,7 @@ kvm_return_point: | |||
350 | /* go back into the guest */ | 280 | /* go back into the guest */ |
351 | 281 | ||
352 | /* Pass the exit number as 3rd argument to kvmppc_handle_exit */ | 282 | /* Pass the exit number as 3rd argument to kvmppc_handle_exit */ |
353 | mr r5, r3 | 283 | mr r5, r12 |
354 | 284 | ||
355 | /* Restore r3 (kvm_run) and r4 (vcpu) */ | 285 | /* Restore r3 (kvm_run) and r4 (vcpu) */ |
356 | REST_2GPRS(3, r1) | 286 | REST_2GPRS(3, r1) |
diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S index fb7dd2e9ac88..cd9f0b609e48 100644 --- a/arch/powerpc/kvm/book3s_64_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S | |||
@@ -45,37 +45,21 @@ kvmppc_trampoline_\intno: | |||
45 | * To distinguish, we check a magic byte in the PACA | 45 | * To distinguish, we check a magic byte in the PACA |
46 | */ | 46 | */ |
47 | mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ | 47 | mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ |
48 | std r12, (PACA_EXMC + EX_R12)(r13) | 48 | std r12, PACA_KVM_SCRATCH0(r13) |
49 | mfcr r12 | 49 | mfcr r12 |
50 | stw r12, (PACA_EXMC + EX_CCR)(r13) | 50 | stw r12, PACA_KVM_SCRATCH1(r13) |
51 | lbz r12, PACA_KVM_IN_GUEST(r13) | 51 | lbz r12, PACA_KVM_IN_GUEST(r13) |
52 | cmpwi r12, 0 | 52 | cmpwi r12, 0 |
53 | bne ..kvmppc_handler_hasmagic_\intno | 53 | bne ..kvmppc_handler_hasmagic_\intno |
54 | /* No KVM guest? Then jump back to the Linux handler! */ | 54 | /* No KVM guest? Then jump back to the Linux handler! */ |
55 | lwz r12, (PACA_EXMC + EX_CCR)(r13) | 55 | lwz r12, PACA_KVM_SCRATCH1(r13) |
56 | mtcr r12 | 56 | mtcr r12 |
57 | ld r12, (PACA_EXMC + EX_R12)(r13) | 57 | ld r12, PACA_KVM_SCRATCH0(r13) |
58 | mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ | 58 | mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ |
59 | b kvmppc_resume_\intno /* Get back original handler */ | 59 | b kvmppc_resume_\intno /* Get back original handler */ |
60 | 60 | ||
61 | /* Now we know we're handling a KVM guest */ | 61 | /* Now we know we're handling a KVM guest */ |
62 | ..kvmppc_handler_hasmagic_\intno: | 62 | ..kvmppc_handler_hasmagic_\intno: |
63 | /* Unset guest state */ | ||
64 | li r12, 0 | ||
65 | stb r12, PACA_KVM_IN_GUEST(r13) | ||
66 | |||
67 | std r1, (PACA_EXMC+EX_R9)(r13) | ||
68 | std r10, (PACA_EXMC+EX_R10)(r13) | ||
69 | std r11, (PACA_EXMC+EX_R11)(r13) | ||
70 | std r2, (PACA_EXMC+EX_R13)(r13) | ||
71 | |||
72 | mfsrr0 r10 | ||
73 | mfsrr1 r11 | ||
74 | |||
75 | /* Restore R1/R2 so we can handle faults */ | ||
76 | ld r1, PACAR1(r13) | ||
77 | ld r2, (PACA_EXMC+EX_SRR0)(r13) | ||
78 | |||
79 | /* Let's store which interrupt we're handling */ | 63 | /* Let's store which interrupt we're handling */ |
80 | li r12, \intno | 64 | li r12, \intno |
81 | 65 | ||
@@ -106,16 +90,16 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX | |||
106 | * | 90 | * |
107 | * Input Registers: | 91 | * Input Registers: |
108 | * | 92 | * |
109 | * R6 = SRR0 | 93 | * R5 = SRR0 |
110 | * R7 = SRR1 | 94 | * R6 = SRR1 |
111 | * LR = real-mode IP | 95 | * LR = real-mode IP |
112 | * | 96 | * |
113 | */ | 97 | */ |
114 | .global kvmppc_handler_lowmem_trampoline | 98 | .global kvmppc_handler_lowmem_trampoline |
115 | kvmppc_handler_lowmem_trampoline: | 99 | kvmppc_handler_lowmem_trampoline: |
116 | 100 | ||
117 | mtsrr0 r6 | 101 | mtsrr0 r5 |
118 | mtsrr1 r7 | 102 | mtsrr1 r6 |
119 | blr | 103 | blr |
120 | kvmppc_handler_lowmem_trampoline_end: | 104 | kvmppc_handler_lowmem_trampoline_end: |
121 | 105 | ||
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S index 8e4478866669..7188c11ed7d1 100644 --- a/arch/powerpc/kvm/book3s_64_slb.S +++ b/arch/powerpc/kvm/book3s_64_slb.S | |||
@@ -51,24 +51,18 @@ kvmppc_handler_trampoline_enter: | |||
51 | * | 51 | * |
52 | * MSR = ~IR|DR | 52 | * MSR = ~IR|DR |
53 | * R13 = PACA | 53 | * R13 = PACA |
54 | * R1 = host R1 | ||
55 | * R2 = host R2 | ||
54 | * R9 = guest IP | 56 | * R9 = guest IP |
55 | * R10 = guest MSR | 57 | * R10 = guest MSR |
56 | * R11 = free | 58 | * all other GPRS = free |
57 | * R12 = free | 59 | * PACA[KVM_CR] = guest CR |
58 | * PACA[PACA_EXMC + EX_R9] = guest R9 | 60 | * PACA[KVM_XER] = guest XER |
59 | * PACA[PACA_EXMC + EX_R10] = guest R10 | ||
60 | * PACA[PACA_EXMC + EX_R11] = guest R11 | ||
61 | * PACA[PACA_EXMC + EX_R12] = guest R12 | ||
62 | * PACA[PACA_EXMC + EX_R13] = guest R13 | ||
63 | * PACA[PACA_EXMC + EX_CCR] = guest CR | ||
64 | * PACA[PACA_EXMC + EX_R3] = guest XER | ||
65 | */ | 61 | */ |
66 | 62 | ||
67 | mtsrr0 r9 | 63 | mtsrr0 r9 |
68 | mtsrr1 r10 | 64 | mtsrr1 r10 |
69 | 65 | ||
70 | mtspr SPRN_SPRG_SCRATCH0, r0 | ||
71 | |||
72 | /* Remove LPAR shadow entries */ | 66 | /* Remove LPAR shadow entries */ |
73 | 67 | ||
74 | #if SLB_NUM_BOLTED == 3 | 68 | #if SLB_NUM_BOLTED == 3 |
@@ -131,20 +125,27 @@ slb_do_enter: | |||
131 | 125 | ||
132 | /* Enter guest */ | 126 | /* Enter guest */ |
133 | 127 | ||
134 | mfspr r0, SPRN_SPRG_SCRATCH0 | 128 | ld r0, (PACA_KVM_R0)(r13) |
135 | 129 | ld r1, (PACA_KVM_R1)(r13) | |
136 | ld r9, (PACA_EXMC+EX_R9)(r13) | 130 | ld r2, (PACA_KVM_R2)(r13) |
137 | ld r10, (PACA_EXMC+EX_R10)(r13) | 131 | ld r3, (PACA_KVM_R3)(r13) |
138 | ld r12, (PACA_EXMC+EX_R12)(r13) | 132 | ld r4, (PACA_KVM_R4)(r13) |
139 | 133 | ld r5, (PACA_KVM_R5)(r13) | |
140 | lwz r11, (PACA_EXMC+EX_CCR)(r13) | 134 | ld r6, (PACA_KVM_R6)(r13) |
135 | ld r7, (PACA_KVM_R7)(r13) | ||
136 | ld r8, (PACA_KVM_R8)(r13) | ||
137 | ld r9, (PACA_KVM_R9)(r13) | ||
138 | ld r10, (PACA_KVM_R10)(r13) | ||
139 | ld r12, (PACA_KVM_R12)(r13) | ||
140 | |||
141 | lwz r11, (PACA_KVM_CR)(r13) | ||
141 | mtcr r11 | 142 | mtcr r11 |
142 | 143 | ||
143 | ld r11, (PACA_EXMC+EX_R3)(r13) | 144 | ld r11, (PACA_KVM_XER)(r13) |
144 | mtxer r11 | 145 | mtxer r11 |
145 | 146 | ||
146 | ld r11, (PACA_EXMC+EX_R11)(r13) | 147 | ld r11, (PACA_KVM_R11)(r13) |
147 | ld r13, (PACA_EXMC+EX_R13)(r13) | 148 | ld r13, (PACA_KVM_R13)(r13) |
148 | 149 | ||
149 | RFI | 150 | RFI |
150 | kvmppc_handler_trampoline_enter_end: | 151 | kvmppc_handler_trampoline_enter_end: |
@@ -162,28 +163,58 @@ kvmppc_handler_trampoline_exit: | |||
162 | 163 | ||
163 | /* Register usage at this point: | 164 | /* Register usage at this point: |
164 | * | 165 | * |
165 | * SPRG_SCRATCH0 = guest R13 | 166 | * SPRG_SCRATCH0 = guest R13 |
166 | * R01 = host R1 | 167 | * R12 = exit handler id |
167 | * R02 = host R2 | 168 | * R13 = PACA |
168 | * R10 = guest PC | 169 | * PACA.KVM.SCRATCH0 = guest R12 |
169 | * R11 = guest MSR | 170 | * PACA.KVM.SCRATCH1 = guest CR |
170 | * R12 = exit handler id | ||
171 | * R13 = PACA | ||
172 | * PACA.exmc.CCR = guest CR | ||
173 | * PACA.exmc.R9 = guest R1 | ||
174 | * PACA.exmc.R10 = guest R10 | ||
175 | * PACA.exmc.R11 = guest R11 | ||
176 | * PACA.exmc.R12 = guest R12 | ||
177 | * PACA.exmc.R13 = guest R2 | ||
178 | * | 171 | * |
179 | */ | 172 | */ |
180 | 173 | ||
181 | /* Save registers */ | 174 | /* Save registers */ |
182 | 175 | ||
183 | std r0, (PACA_EXMC+EX_SRR0)(r13) | 176 | std r0, PACA_KVM_R0(r13) |
184 | std r9, (PACA_EXMC+EX_R3)(r13) | 177 | std r1, PACA_KVM_R1(r13) |
185 | std r10, (PACA_EXMC+EX_LR)(r13) | 178 | std r2, PACA_KVM_R2(r13) |
186 | std r11, (PACA_EXMC+EX_DAR)(r13) | 179 | std r3, PACA_KVM_R3(r13) |
180 | std r4, PACA_KVM_R4(r13) | ||
181 | std r5, PACA_KVM_R5(r13) | ||
182 | std r6, PACA_KVM_R6(r13) | ||
183 | std r7, PACA_KVM_R7(r13) | ||
184 | std r8, PACA_KVM_R8(r13) | ||
185 | std r9, PACA_KVM_R9(r13) | ||
186 | std r10, PACA_KVM_R10(r13) | ||
187 | std r11, PACA_KVM_R11(r13) | ||
188 | |||
189 | /* Restore R1/R2 so we can handle faults */ | ||
190 | ld r1, PACA_KVM_HOST_R1(r13) | ||
191 | ld r2, PACA_KVM_HOST_R2(r13) | ||
192 | |||
193 | /* Save guest PC and MSR in GPRs */ | ||
194 | mfsrr0 r3 | ||
195 | mfsrr1 r4 | ||
196 | |||
197 | /* Get scratch'ed off registers */ | ||
198 | mfspr r9, SPRN_SPRG_SCRATCH0 | ||
199 | std r9, PACA_KVM_R13(r13) | ||
200 | |||
201 | ld r8, PACA_KVM_SCRATCH0(r13) | ||
202 | std r8, PACA_KVM_R12(r13) | ||
203 | |||
204 | lwz r7, PACA_KVM_SCRATCH1(r13) | ||
205 | stw r7, PACA_KVM_CR(r13) | ||
206 | |||
207 | /* Save more register state */ | ||
208 | |||
209 | mfxer r6 | ||
210 | stw r6, PACA_KVM_XER(r13) | ||
211 | |||
212 | mfdar r5 | ||
213 | mfdsisr r6 | ||
214 | |||
215 | /* Unset guest state */ | ||
216 | li r9, 0 | ||
217 | stb r9, PACA_KVM_IN_GUEST(r13) | ||
187 | 218 | ||
188 | /* | 219 | /* |
189 | * In order for us to easily get the last instruction, | 220 | * In order for us to easily get the last instruction, |
@@ -207,7 +238,8 @@ ld_last_inst: | |||
207 | ori r11, r9, MSR_DR /* Enable paging for data */ | 238 | ori r11, r9, MSR_DR /* Enable paging for data */ |
208 | mtmsr r11 | 239 | mtmsr r11 |
209 | /* 2) fetch the instruction */ | 240 | /* 2) fetch the instruction */ |
210 | lwz r0, 0(r10) | 241 | /* XXX implement PACA_KVM_IN_GUEST=2 path to safely jump over this */ |
242 | lwz r0, 0(r3) | ||
211 | /* 3) disable paging again */ | 243 | /* 3) disable paging again */ |
212 | mtmsr r9 | 244 | mtmsr r9 |
213 | 245 | ||
@@ -233,29 +265,27 @@ no_ld_last_inst: | |||
233 | 265 | ||
234 | slb_do_exit: | 266 | slb_do_exit: |
235 | 267 | ||
236 | /* Restore registers */ | 268 | /* Register usage at this point: |
237 | 269 | * | |
238 | ld r11, (PACA_EXMC+EX_DAR)(r13) | 270 | * R0 = guest last inst |
239 | ld r10, (PACA_EXMC+EX_LR)(r13) | 271 | * R1 = host R1 |
240 | ld r9, (PACA_EXMC+EX_R3)(r13) | 272 | * R2 = host R2 |
241 | 273 | * R3 = guest PC | |
242 | /* Save last inst */ | 274 | * R4 = guest MSR |
243 | stw r0, (PACA_EXMC+EX_LR)(r13) | 275 | * R5 = guest DAR |
244 | 276 | * R6 = guest DSISR | |
245 | /* Save DAR and DSISR before going to paged mode */ | 277 | * R12 = exit handler id |
246 | mfdar r0 | 278 | * R13 = PACA |
247 | std r0, (PACA_EXMC+EX_DAR)(r13) | 279 | * PACA.KVM.* = guest * |
248 | mfdsisr r0 | 280 | * |
249 | stw r0, (PACA_EXMC+EX_DSISR)(r13) | 281 | */ |
250 | 282 | ||
251 | /* RFI into the highmem handler */ | 283 | /* RFI into the highmem handler */ |
252 | mfmsr r0 | 284 | mfmsr r7 |
253 | ori r0, r0, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ | 285 | ori r7, r7, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ |
254 | mtsrr1 r0 | 286 | mtsrr1 r7 |
255 | ld r0, PACASAVEDMSR(r13) /* Highmem handler address */ | 287 | ld r8, PACA_KVM_VMHANDLER(r13) /* Highmem handler address */ |
256 | mtsrr0 r0 | 288 | mtsrr0 r8 |
257 | |||
258 | mfspr r0, SPRN_SPRG_SCRATCH0 | ||
259 | 289 | ||
260 | RFI | 290 | RFI |
261 | kvmppc_handler_trampoline_exit_end: | 291 | kvmppc_handler_trampoline_exit_end: |