diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_slb.S')
-rw-r--r-- | arch/powerpc/kvm/book3s_64_slb.S | 160 |
1 files changed, 100 insertions, 60 deletions
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S index ecd237a03fd..35b76272218 100644 --- a/arch/powerpc/kvm/book3s_64_slb.S +++ b/arch/powerpc/kvm/book3s_64_slb.S | |||
@@ -31,7 +31,7 @@ | |||
31 | #define REBOLT_SLB_ENTRY(num) \ | 31 | #define REBOLT_SLB_ENTRY(num) \ |
32 | ld r10, SHADOW_SLB_ESID(num)(r11); \ | 32 | ld r10, SHADOW_SLB_ESID(num)(r11); \ |
33 | cmpdi r10, 0; \ | 33 | cmpdi r10, 0; \ |
34 | beq slb_exit_skip_1; \ | 34 | beq slb_exit_skip_ ## num; \ |
35 | oris r10, r10, SLB_ESID_V@h; \ | 35 | oris r10, r10, SLB_ESID_V@h; \ |
36 | ld r9, SHADOW_SLB_VSID(num)(r11); \ | 36 | ld r9, SHADOW_SLB_VSID(num)(r11); \ |
37 | slbmte r9, r10; \ | 37 | slbmte r9, r10; \ |
@@ -51,23 +51,21 @@ 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 | 66 | /* Activate guest mode, so faults get handled by KVM */ |
67 | li r11, KVM_GUEST_MODE_GUEST | ||
68 | stb r11, PACA_KVM_IN_GUEST(r13) | ||
71 | 69 | ||
72 | /* Remove LPAR shadow entries */ | 70 | /* Remove LPAR shadow entries */ |
73 | 71 | ||
@@ -131,20 +129,27 @@ slb_do_enter: | |||
131 | 129 | ||
132 | /* Enter guest */ | 130 | /* Enter guest */ |
133 | 131 | ||
134 | mfspr r0, SPRN_SPRG_SCRATCH0 | 132 | ld r0, (PACA_KVM_R0)(r13) |
135 | 133 | ld r1, (PACA_KVM_R1)(r13) | |
136 | ld r9, (PACA_EXMC+EX_R9)(r13) | 134 | ld r2, (PACA_KVM_R2)(r13) |
137 | ld r10, (PACA_EXMC+EX_R10)(r13) | 135 | ld r3, (PACA_KVM_R3)(r13) |
138 | ld r12, (PACA_EXMC+EX_R12)(r13) | 136 | ld r4, (PACA_KVM_R4)(r13) |
139 | 137 | ld r5, (PACA_KVM_R5)(r13) | |
140 | lwz r11, (PACA_EXMC+EX_CCR)(r13) | 138 | ld r6, (PACA_KVM_R6)(r13) |
139 | ld r7, (PACA_KVM_R7)(r13) | ||
140 | ld r8, (PACA_KVM_R8)(r13) | ||
141 | ld r9, (PACA_KVM_R9)(r13) | ||
142 | ld r10, (PACA_KVM_R10)(r13) | ||
143 | ld r12, (PACA_KVM_R12)(r13) | ||
144 | |||
145 | lwz r11, (PACA_KVM_CR)(r13) | ||
141 | mtcr r11 | 146 | mtcr r11 |
142 | 147 | ||
143 | ld r11, (PACA_EXMC+EX_R3)(r13) | 148 | ld r11, (PACA_KVM_XER)(r13) |
144 | mtxer r11 | 149 | mtxer r11 |
145 | 150 | ||
146 | ld r11, (PACA_EXMC+EX_R11)(r13) | 151 | ld r11, (PACA_KVM_R11)(r13) |
147 | ld r13, (PACA_EXMC+EX_R13)(r13) | 152 | ld r13, (PACA_KVM_R13)(r13) |
148 | 153 | ||
149 | RFI | 154 | RFI |
150 | kvmppc_handler_trampoline_enter_end: | 155 | kvmppc_handler_trampoline_enter_end: |
@@ -162,28 +167,54 @@ kvmppc_handler_trampoline_exit: | |||
162 | 167 | ||
163 | /* Register usage at this point: | 168 | /* Register usage at this point: |
164 | * | 169 | * |
165 | * SPRG_SCRATCH0 = guest R13 | 170 | * SPRG_SCRATCH0 = guest R13 |
166 | * R01 = host R1 | 171 | * R12 = exit handler id |
167 | * R02 = host R2 | 172 | * R13 = PACA |
168 | * R10 = guest PC | 173 | * PACA.KVM.SCRATCH0 = guest R12 |
169 | * R11 = guest MSR | 174 | * 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 | * | 175 | * |
179 | */ | 176 | */ |
180 | 177 | ||
181 | /* Save registers */ | 178 | /* Save registers */ |
182 | 179 | ||
183 | std r0, (PACA_EXMC+EX_SRR0)(r13) | 180 | std r0, PACA_KVM_R0(r13) |
184 | std r9, (PACA_EXMC+EX_R3)(r13) | 181 | std r1, PACA_KVM_R1(r13) |
185 | std r10, (PACA_EXMC+EX_LR)(r13) | 182 | std r2, PACA_KVM_R2(r13) |
186 | std r11, (PACA_EXMC+EX_DAR)(r13) | 183 | std r3, PACA_KVM_R3(r13) |
184 | std r4, PACA_KVM_R4(r13) | ||
185 | std r5, PACA_KVM_R5(r13) | ||
186 | std r6, PACA_KVM_R6(r13) | ||
187 | std r7, PACA_KVM_R7(r13) | ||
188 | std r8, PACA_KVM_R8(r13) | ||
189 | std r9, PACA_KVM_R9(r13) | ||
190 | std r10, PACA_KVM_R10(r13) | ||
191 | std r11, PACA_KVM_R11(r13) | ||
192 | |||
193 | /* Restore R1/R2 so we can handle faults */ | ||
194 | ld r1, PACA_KVM_HOST_R1(r13) | ||
195 | ld r2, PACA_KVM_HOST_R2(r13) | ||
196 | |||
197 | /* Save guest PC and MSR in GPRs */ | ||
198 | mfsrr0 r3 | ||
199 | mfsrr1 r4 | ||
200 | |||
201 | /* Get scratch'ed off registers */ | ||
202 | mfspr r9, SPRN_SPRG_SCRATCH0 | ||
203 | std r9, PACA_KVM_R13(r13) | ||
204 | |||
205 | ld r8, PACA_KVM_SCRATCH0(r13) | ||
206 | std r8, PACA_KVM_R12(r13) | ||
207 | |||
208 | lwz r7, PACA_KVM_SCRATCH1(r13) | ||
209 | stw r7, PACA_KVM_CR(r13) | ||
210 | |||
211 | /* Save more register state */ | ||
212 | |||
213 | mfxer r6 | ||
214 | stw r6, PACA_KVM_XER(r13) | ||
215 | |||
216 | mfdar r5 | ||
217 | mfdsisr r6 | ||
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, |
@@ -202,17 +233,28 @@ kvmppc_handler_trampoline_exit: | |||
202 | 233 | ||
203 | ld_last_inst: | 234 | ld_last_inst: |
204 | /* Save off the guest instruction we're at */ | 235 | /* Save off the guest instruction we're at */ |
236 | |||
237 | /* Set guest mode to 'jump over instruction' so if lwz faults | ||
238 | * we'll just continue at the next IP. */ | ||
239 | li r9, KVM_GUEST_MODE_SKIP | ||
240 | stb r9, PACA_KVM_IN_GUEST(r13) | ||
241 | |||
205 | /* 1) enable paging for data */ | 242 | /* 1) enable paging for data */ |
206 | mfmsr r9 | 243 | mfmsr r9 |
207 | ori r11, r9, MSR_DR /* Enable paging for data */ | 244 | ori r11, r9, MSR_DR /* Enable paging for data */ |
208 | mtmsr r11 | 245 | mtmsr r11 |
209 | /* 2) fetch the instruction */ | 246 | /* 2) fetch the instruction */ |
210 | lwz r0, 0(r10) | 247 | li r0, KVM_INST_FETCH_FAILED /* In case lwz faults */ |
248 | lwz r0, 0(r3) | ||
211 | /* 3) disable paging again */ | 249 | /* 3) disable paging again */ |
212 | mtmsr r9 | 250 | mtmsr r9 |
213 | 251 | ||
214 | no_ld_last_inst: | 252 | no_ld_last_inst: |
215 | 253 | ||
254 | /* Unset guest mode */ | ||
255 | li r9, KVM_GUEST_MODE_NONE | ||
256 | stb r9, PACA_KVM_IN_GUEST(r13) | ||
257 | |||
216 | /* Restore bolted entries from the shadow and fix it along the way */ | 258 | /* Restore bolted entries from the shadow and fix it along the way */ |
217 | 259 | ||
218 | /* We don't store anything in entry 0, so we don't need to take care of it */ | 260 | /* We don't store anything in entry 0, so we don't need to take care of it */ |
@@ -233,29 +275,27 @@ no_ld_last_inst: | |||
233 | 275 | ||
234 | slb_do_exit: | 276 | slb_do_exit: |
235 | 277 | ||
236 | /* Restore registers */ | 278 | /* Register usage at this point: |
237 | 279 | * | |
238 | ld r11, (PACA_EXMC+EX_DAR)(r13) | 280 | * R0 = guest last inst |
239 | ld r10, (PACA_EXMC+EX_LR)(r13) | 281 | * R1 = host R1 |
240 | ld r9, (PACA_EXMC+EX_R3)(r13) | 282 | * R2 = host R2 |
241 | 283 | * R3 = guest PC | |
242 | /* Save last inst */ | 284 | * R4 = guest MSR |
243 | stw r0, (PACA_EXMC+EX_LR)(r13) | 285 | * R5 = guest DAR |
244 | 286 | * R6 = guest DSISR | |
245 | /* Save DAR and DSISR before going to paged mode */ | 287 | * R12 = exit handler id |
246 | mfdar r0 | 288 | * R13 = PACA |
247 | std r0, (PACA_EXMC+EX_DAR)(r13) | 289 | * PACA.KVM.* = guest * |
248 | mfdsisr r0 | 290 | * |
249 | stw r0, (PACA_EXMC+EX_DSISR)(r13) | 291 | */ |
250 | 292 | ||
251 | /* RFI into the highmem handler */ | 293 | /* RFI into the highmem handler */ |
252 | mfmsr r0 | 294 | mfmsr r7 |
253 | ori r0, r0, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ | 295 | ori r7, r7, MSR_IR|MSR_DR|MSR_RI /* Enable paging */ |
254 | mtsrr1 r0 | 296 | mtsrr1 r7 |
255 | ld r0, PACASAVEDMSR(r13) /* Highmem handler address */ | 297 | ld r8, PACA_KVM_VMHANDLER(r13) /* Highmem handler address */ |
256 | mtsrr0 r0 | 298 | mtsrr0 r8 |
257 | |||
258 | mfspr r0, SPRN_SPRG_SCRATCH0 | ||
259 | 299 | ||
260 | RFI | 300 | RFI |
261 | kvmppc_handler_trampoline_exit_end: | 301 | kvmppc_handler_trampoline_exit_end: |