aboutsummaryrefslogtreecommitdiff
path: root/target/arm/kvm32.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/kvm32.c')
-rw-r--r--target/arm/kvm32.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
index 7b3a19e..0af46b4 100644
--- a/target/arm/kvm32.c
+++ b/target/arm/kvm32.c
@@ -559,3 +559,37 @@ void kvm_arm_pmu_init(CPUState *cs)
{
qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
}
+
+#define ARM_REG_DFSR ARM_CP15_REG32(0, 5, 0, 0)
+#define ARM_REG_TTBCR ARM_CP15_REG32(0, 2, 0, 2)
+/*
+ *DFSR:
+ * TTBCR.EAE == 0
+ * FS[4] - DFSR[10]
+ * FS[3:0] - DFSR[3:0]
+ * TTBCR.EAE == 1
+ * FS, bits [5:0]
+ */
+#define DFSR_FSC(lpae, v) \
+ ((lpae) ? ((v) & 0x3F) : (((v) >> 6) | ((v) & 0x1F)))
+
+#define DFSC_EXTABT(lpae) ((lpae) ? 0x10 : 0x08)
+
+bool kvm_arm_verify_ext_dabt_pending(CPUState *cs)
+{
+ uint32_t dfsr_val;
+
+ if (!kvm_get_one_reg(cs, ARM_REG_DFSR, &dfsr_val)) {
+ ARMCPU *cpu = ARM_CPU(cs);
+ CPUARMState *env = &cpu->env;
+ uint32_t ttbcr;
+ int lpae = 0;
+
+ if (!kvm_get_one_reg(cs, ARM_REG_TTBCR, &ttbcr)) {
+ lpae = arm_feature(env, ARM_FEATURE_LPAE) && (ttbcr & TTBCR_EAE);
+ }
+ /* The verification is based on FS filed of the DFSR reg only*/
+ return (DFSR_FSC(lpae, dfsr_val) == DFSC_EXTABT(lpae));
+ }
+ return false;
+}