aboutsummaryrefslogtreecommitdiff
path: root/target/arm/helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2022-05-06 13:02:33 -0500
committerPeter Maydell <peter.maydell@linaro.org>2022-05-09 11:47:54 +0100
commit3c29632feba7724be447b621f3527136e5c32744 (patch)
treebbdc55c73c601aef2dbf7dfb9f445719866daaa1 /target/arm/helper.c
parentda3d8b13624246702f7b8b88e37ee525a2f39ad2 (diff)
target/arm: Implement virtual SError exceptions
Virtual SError exceptions are raised by setting HCR_EL2.VSE, and are routed to EL1 just like other virtual exceptions. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220506180242.216785-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b6faebf4a7..4857d2dbb8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1863,7 +1863,12 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
}
- /* External aborts are not possible in QEMU so A bit is always clear */
+ if (hcr_el2 & HCR_AMO) {
+ if (cs->interrupt_request & CPU_INTERRUPT_VSERR) {
+ ret |= CPSR_A;
+ }
+ }
+
return ret;
}
@@ -5175,6 +5180,7 @@ static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
g_assert(qemu_mutex_iothread_locked());
arm_cpu_update_virq(cpu);
arm_cpu_update_vfiq(cpu);
+ arm_cpu_update_vserr(cpu);
}
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
@@ -9331,6 +9337,7 @@ void arm_log_exception(CPUState *cs)
[EXCP_LSERR] = "v8M LSERR UsageFault",
[EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
[EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
+ [EXCP_VSERR] = "Virtual SERR",
};
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
@@ -9843,6 +9850,31 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs)
mask = CPSR_A | CPSR_I | CPSR_F;
offset = 4;
break;
+ case EXCP_VSERR:
+ {
+ /*
+ * Note that this is reported as a data abort, but the DFAR
+ * has an UNKNOWN value. Construct the SError syndrome from
+ * AET and ExT fields.
+ */
+ ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal, };
+
+ if (extended_addresses_enabled(env)) {
+ env->exception.fsr = arm_fi_to_lfsc(&fi);
+ } else {
+ env->exception.fsr = arm_fi_to_sfsc(&fi);
+ }
+ env->exception.fsr |= env->cp15.vsesr_el2 & 0xd000;
+ A32_BANKED_CURRENT_REG_SET(env, dfsr, env->exception.fsr);
+ qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x\n",
+ env->exception.fsr);
+
+ new_mode = ARM_CPU_MODE_ABT;
+ addr = 0x10;
+ mask = CPSR_A | CPSR_I;
+ offset = 8;
+ }
+ break;
case EXCP_SMC:
new_mode = ARM_CPU_MODE_MON;
addr = 0x08;
@@ -10063,6 +10095,12 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
case EXCP_VFIQ:
addr += 0x100;
break;
+ case EXCP_VSERR:
+ addr += 0x180;
+ /* Construct the SError syndrome from IDS and ISS fields. */
+ env->exception.syndrome = syn_serror(env->cp15.vsesr_el2 & 0x1ffffff);
+ env->cp15.esr_el[new_el] = env->exception.syndrome;
+ break;
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
}