diff options
Diffstat (limited to 'arch/arm/kvm/emulate.c')
-rw-r--r-- | arch/arm/kvm/emulate.c | 137 |
1 files changed, 0 insertions, 137 deletions
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 30a13647c54c..cdff963f133a 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c | |||
@@ -165,143 +165,6 @@ unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu) | |||
165 | * Inject exceptions into the guest | 165 | * Inject exceptions into the guest |
166 | */ | 166 | */ |
167 | 167 | ||
168 | static u32 exc_vector_base(struct kvm_vcpu *vcpu) | ||
169 | { | ||
170 | u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); | ||
171 | u32 vbar = vcpu_cp15(vcpu, c12_VBAR); | ||
172 | |||
173 | if (sctlr & SCTLR_V) | ||
174 | return 0xffff0000; | ||
175 | else /* always have security exceptions */ | ||
176 | return vbar; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Switch to an exception mode, updating both CPSR and SPSR. Follow | ||
181 | * the logic described in AArch32.EnterMode() from the ARMv8 ARM. | ||
182 | */ | ||
183 | static void kvm_update_psr(struct kvm_vcpu *vcpu, unsigned long mode) | ||
184 | { | ||
185 | unsigned long cpsr = *vcpu_cpsr(vcpu); | ||
186 | u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); | ||
187 | |||
188 | *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | mode; | ||
189 | |||
190 | switch (mode) { | ||
191 | case FIQ_MODE: | ||
192 | *vcpu_cpsr(vcpu) |= PSR_F_BIT; | ||
193 | /* Fall through */ | ||
194 | case ABT_MODE: | ||
195 | case IRQ_MODE: | ||
196 | *vcpu_cpsr(vcpu) |= PSR_A_BIT; | ||
197 | /* Fall through */ | ||
198 | default: | ||
199 | *vcpu_cpsr(vcpu) |= PSR_I_BIT; | ||
200 | } | ||
201 | |||
202 | *vcpu_cpsr(vcpu) &= ~(PSR_IT_MASK | PSR_J_BIT | PSR_E_BIT | PSR_T_BIT); | ||
203 | |||
204 | if (sctlr & SCTLR_TE) | ||
205 | *vcpu_cpsr(vcpu) |= PSR_T_BIT; | ||
206 | if (sctlr & SCTLR_EE) | ||
207 | *vcpu_cpsr(vcpu) |= PSR_E_BIT; | ||
208 | |||
209 | /* Note: These now point to the mode banked copies */ | ||
210 | *vcpu_spsr(vcpu) = cpsr; | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * kvm_inject_undefined - inject an undefined exception into the guest | ||
215 | * @vcpu: The VCPU to receive the undefined exception | ||
216 | * | ||
217 | * It is assumed that this code is called from the VCPU thread and that the | ||
218 | * VCPU therefore is not currently executing guest code. | ||
219 | * | ||
220 | * Modelled after TakeUndefInstrException() pseudocode. | ||
221 | */ | ||
222 | void kvm_inject_undefined(struct kvm_vcpu *vcpu) | ||
223 | { | ||
224 | unsigned long cpsr = *vcpu_cpsr(vcpu); | ||
225 | bool is_thumb = (cpsr & PSR_T_BIT); | ||
226 | u32 vect_offset = 4; | ||
227 | u32 return_offset = (is_thumb) ? 2 : 4; | ||
228 | |||
229 | kvm_update_psr(vcpu, UND_MODE); | ||
230 | *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; | ||
231 | |||
232 | /* Branch to exception vector */ | ||
233 | *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | * Modelled after TakeDataAbortException() and TakePrefetchAbortException | ||
238 | * pseudocode. | ||
239 | */ | ||
240 | static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) | ||
241 | { | ||
242 | u32 vect_offset; | ||
243 | u32 return_offset = (is_pabt) ? 4 : 8; | ||
244 | bool is_lpae; | ||
245 | |||
246 | kvm_update_psr(vcpu, ABT_MODE); | ||
247 | *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; | ||
248 | |||
249 | if (is_pabt) | ||
250 | vect_offset = 12; | ||
251 | else | ||
252 | vect_offset = 16; | ||
253 | |||
254 | /* Branch to exception vector */ | ||
255 | *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; | ||
256 | |||
257 | if (is_pabt) { | ||
258 | /* Set IFAR and IFSR */ | ||
259 | vcpu_cp15(vcpu, c6_IFAR) = addr; | ||
260 | is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31); | ||
261 | /* Always give debug fault for now - should give guest a clue */ | ||
262 | if (is_lpae) | ||
263 | vcpu_cp15(vcpu, c5_IFSR) = 1 << 9 | 0x22; | ||
264 | else | ||
265 | vcpu_cp15(vcpu, c5_IFSR) = 2; | ||
266 | } else { /* !iabt */ | ||
267 | /* Set DFAR and DFSR */ | ||
268 | vcpu_cp15(vcpu, c6_DFAR) = addr; | ||
269 | is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31); | ||
270 | /* Always give debug fault for now - should give guest a clue */ | ||
271 | if (is_lpae) | ||
272 | vcpu_cp15(vcpu, c5_DFSR) = 1 << 9 | 0x22; | ||
273 | else | ||
274 | vcpu_cp15(vcpu, c5_DFSR) = 2; | ||
275 | } | ||
276 | |||
277 | } | ||
278 | |||
279 | /** | ||
280 | * kvm_inject_dabt - inject a data abort into the guest | ||
281 | * @vcpu: The VCPU to receive the undefined exception | ||
282 | * @addr: The address to report in the DFAR | ||
283 | * | ||
284 | * It is assumed that this code is called from the VCPU thread and that the | ||
285 | * VCPU therefore is not currently executing guest code. | ||
286 | */ | ||
287 | void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr) | ||
288 | { | ||
289 | inject_abt(vcpu, false, addr); | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * kvm_inject_pabt - inject a prefetch abort into the guest | ||
294 | * @vcpu: The VCPU to receive the undefined exception | ||
295 | * @addr: The address to report in the DFAR | ||
296 | * | ||
297 | * It is assumed that this code is called from the VCPU thread and that the | ||
298 | * VCPU therefore is not currently executing guest code. | ||
299 | */ | ||
300 | void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr) | ||
301 | { | ||
302 | inject_abt(vcpu, true, addr); | ||
303 | } | ||
304 | |||
305 | /** | 168 | /** |
306 | * kvm_inject_vabt - inject an async abort / SError into the guest | 169 | * kvm_inject_vabt - inject an async abort / SError into the guest |
307 | * @vcpu: The VCPU to receive the exception | 170 | * @vcpu: The VCPU to receive the exception |