aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-01-07 20:58:03 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:35:48 -0500
commit7e57cba06074da84d7c24d8c3f44040d2d8c88ac (patch)
treee99519ca301b887de4d689421e7a954f1c7792e4 /arch/powerpc/kvm
parent992b5b29b5ae254c416c62faf98d59a6cf970027 (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.c4
-rw-r--r--arch/powerpc/kvm/book3s_64_interrupts.S216
-rw-r--r--arch/powerpc/kvm/book3s_64_rmhandlers.S32
-rw-r--r--arch/powerpc/kvm/book3s_64_slb.S150
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)
66void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 66void 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
72void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) 74void 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
95kvm_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)) 101kvm_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
144no_dcbz32_on: 132no_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
249no_dcbz32_off: 195no_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
115kvmppc_handler_lowmem_trampoline: 99kvmppc_handler_lowmem_trampoline:
116 100
117 mtsrr0 r6 101 mtsrr0 r5
118 mtsrr1 r7 102 mtsrr1 r6
119 blr 103 blr
120kvmppc_handler_lowmem_trampoline_end: 104kvmppc_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
150kvmppc_handler_trampoline_enter_end: 151kvmppc_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
234slb_do_exit: 266slb_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
261kvmppc_handler_trampoline_exit_end: 291kvmppc_handler_trampoline_exit_end: