aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm/emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kvm/emulate.c')
-rw-r--r--arch/arm/kvm/emulate.c137
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
168static 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 */
183static 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 */
222void 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 */
240static 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 */
287void 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 */
300void 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