summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-10-29 02:18:09 +0000
committerChristoffer Dall <christoffer.dall@linaro.org>2017-11-06 16:23:20 +0100
commit74a64a981662ab34289b3c90f6f964aa38ec1d9f (patch)
tree2b50e644fc682bade8e028ef495e54da5c683668 /arch/arm
parent3eb4271b4ab6d38a3c113a19f358f606702e08ef (diff)
KVM: arm/arm64: Unify 32bit fault injection
Both arm and arm64 implementations are capable of injecting faults, and yet have completely divergent implementations, leading to different bugs and reduced maintainability. Let's elect the arm64 version as the canonical one and move it into aarch32.c, which is common to both architectures. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/include/asm/kvm_emulate.h36
-rw-r--r--arch/arm/kvm/emulate.c139
2 files changed, 33 insertions, 142 deletions
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 98089ffd91bb..dcae3970148d 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -25,7 +25,22 @@
#include <asm/kvm_arm.h>
#include <asm/cputype.h>
+/* arm64 compatibility macros */
+#define COMPAT_PSR_MODE_ABT ABT_MODE
+#define COMPAT_PSR_MODE_UND UND_MODE
+#define COMPAT_PSR_T_BIT PSR_T_BIT
+#define COMPAT_PSR_I_BIT PSR_I_BIT
+#define COMPAT_PSR_A_BIT PSR_A_BIT
+#define COMPAT_PSR_E_BIT PSR_E_BIT
+#define COMPAT_PSR_IT_MASK PSR_IT_MASK
+
unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
+
+static inline unsigned long *vcpu_reg32(struct kvm_vcpu *vcpu, u8 reg_num)
+{
+ return vcpu_reg(vcpu, reg_num);
+}
+
unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu);
static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
@@ -42,10 +57,25 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
-void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_undef32(struct kvm_vcpu *vcpu);
+void kvm_inject_dabt32(struct kvm_vcpu *vcpu, unsigned long addr);
+void kvm_inject_pabt32(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_vabt(struct kvm_vcpu *vcpu);
-void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
-void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
+
+static inline void kvm_inject_undefined(struct kvm_vcpu *vcpu)
+{
+ kvm_inject_undef32(vcpu);
+}
+
+static inline void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+ kvm_inject_dabt32(vcpu, addr);
+}
+
+static inline void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
+{
+ kvm_inject_pabt32(vcpu, addr);
+}
static inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
{
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index 0064b86a2c87..cdff963f133a 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -165,145 +165,6 @@ unsigned long *vcpu_spsr(struct kvm_vcpu *vcpu)
* Inject exceptions into the guest
*/
-static u32 exc_vector_base(struct kvm_vcpu *vcpu)
-{
- u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR);
- u32 vbar = vcpu_cp15(vcpu, c12_VBAR);
-
- if (sctlr & SCTLR_V)
- return 0xffff0000;
- else /* always have security exceptions */
- return vbar;
-}
-
-/*
- * Switch to an exception mode, updating both CPSR and SPSR. Follow
- * the logic described in AArch32.EnterMode() from the ARMv8 ARM.
- */
-static void kvm_update_psr(struct kvm_vcpu *vcpu, unsigned long mode)
-{
- unsigned long cpsr = *vcpu_cpsr(vcpu);
- u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR);
-
- *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | mode;
-
- switch (mode) {
- case FIQ_MODE:
- *vcpu_cpsr(vcpu) |= PSR_F_BIT;
- /* Fall through */
- case ABT_MODE:
- case IRQ_MODE:
- *vcpu_cpsr(vcpu) |= PSR_A_BIT;
- /* Fall through */
- default:
- *vcpu_cpsr(vcpu) |= PSR_I_BIT;
- }
-
- *vcpu_cpsr(vcpu) &= ~(PSR_IT_MASK | PSR_J_BIT | PSR_E_BIT | PSR_T_BIT);
-
- if (sctlr & SCTLR_TE)
- *vcpu_cpsr(vcpu) |= PSR_T_BIT;
- if (sctlr & SCTLR_EE)
- *vcpu_cpsr(vcpu) |= PSR_E_BIT;
-
- /* Note: These now point to the mode banked copies */
- *vcpu_spsr(vcpu) = cpsr;
-}
-
-/**
- * kvm_inject_undefined - inject an undefined exception into the guest
- * @vcpu: The VCPU to receive the undefined exception
- *
- * It is assumed that this code is called from the VCPU thread and that the
- * VCPU therefore is not currently executing guest code.
- *
- * Modelled after TakeUndefInstrException() pseudocode.
- */
-void kvm_inject_undefined(struct kvm_vcpu *vcpu)
-{
- unsigned long cpsr = *vcpu_cpsr(vcpu);
- bool is_thumb = (cpsr & PSR_T_BIT);
- u32 vect_offset = 4;
- u32 return_offset = (is_thumb) ? 2 : 4;
-
- kvm_update_psr(vcpu, UND_MODE);
- *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset;
-
- /* Branch to exception vector */
- *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
-}
-
-/*
- * Modelled after TakeDataAbortException() and TakePrefetchAbortException
- * pseudocode.
- */
-static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr)
-{
- unsigned long cpsr = *vcpu_cpsr(vcpu);
- bool is_thumb = (cpsr & PSR_T_BIT);
- u32 vect_offset;
- u32 return_offset = (is_thumb) ? 4 : 0;
- bool is_lpae;
-
- kvm_update_psr(vcpu, ABT_MODE);
- *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
-
- if (is_pabt)
- vect_offset = 12;
- else
- vect_offset = 16;
-
- /* Branch to exception vector */
- *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset;
-
- if (is_pabt) {
- /* Set IFAR and IFSR */
- vcpu_cp15(vcpu, c6_IFAR) = addr;
- is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31);
- /* Always give debug fault for now - should give guest a clue */
- if (is_lpae)
- vcpu_cp15(vcpu, c5_IFSR) = 1 << 9 | 0x22;
- else
- vcpu_cp15(vcpu, c5_IFSR) = 2;
- } else { /* !iabt */
- /* Set DFAR and DFSR */
- vcpu_cp15(vcpu, c6_DFAR) = addr;
- is_lpae = (vcpu_cp15(vcpu, c2_TTBCR) >> 31);
- /* Always give debug fault for now - should give guest a clue */
- if (is_lpae)
- vcpu_cp15(vcpu, c5_DFSR) = 1 << 9 | 0x22;
- else
- vcpu_cp15(vcpu, c5_DFSR) = 2;
- }
-
-}
-
-/**
- * kvm_inject_dabt - inject a data abort into the guest
- * @vcpu: The VCPU to receive the undefined exception
- * @addr: The address to report in the DFAR
- *
- * It is assumed that this code is called from the VCPU thread and that the
- * VCPU therefore is not currently executing guest code.
- */
-void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr)
-{
- inject_abt(vcpu, false, addr);
-}
-
-/**
- * kvm_inject_pabt - inject a prefetch abort into the guest
- * @vcpu: The VCPU to receive the undefined exception
- * @addr: The address to report in the DFAR
- *
- * It is assumed that this code is called from the VCPU thread and that the
- * VCPU therefore is not currently executing guest code.
- */
-void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
-{
- inject_abt(vcpu, true, addr);
-}
-
/**
* kvm_inject_vabt - inject an async abort / SError into the guest
* @vcpu: The VCPU to receive the exception