summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell2021-09-13 17:07:24 +0200
committerPeter Maydell2021-09-13 22:01:08 +0200
commit520d1621de30eecd0869dfd51ae1ff1a9ba988d9 (patch)
tree1ad02ee6e3e8734f3b9f219ef243d739073591d6
parenttests/data/acpi/virt: Update IORT files for ITS (diff)
downloadqemu-520d1621de30eecd0869dfd51ae1ff1a9ba988d9.tar.gz
qemu-520d1621de30eecd0869dfd51ae1ff1a9ba988d9.tar.xz
qemu-520d1621de30eecd0869dfd51ae1ff1a9ba988d9.zip
target/arm: Take an exception if PSTATE.IL is set
In v8A, the PSTATE.IL bit is set for various kinds of illegal exception return or mode-change attempts. We already set PSTATE.IL (or its AArch32 equivalent CPSR.IL) in all those cases, but we weren't implementing the part of the behaviour where attempting to execute an instruction with PSTATE.IL takes an immediate exception with an appropriate syndrome value. Add a new TB flags bit tracking PSTATE.IL/CPSR.IL, and generate code to take an exception instead of whatever the instruction would have been. PSTATE.IL and CPSR.IL change only on exception entry, attempted exception exit, and various AArch32 mode changes via cpsr_write(). These places generally already rebuild the hflags, so the only place we need an extra rebuild_hflags call is in the illegal-return codepath of the AArch64 exception_return helper. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210821195958.41312-2-richard.henderson@linaro.org Message-Id: <20210817162118.24319-1-peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> [rth: Added missing returns; set IL bit in syndrome] Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--target/arm/cpu.h1
-rw-r--r--target/arm/helper-a64.c1
-rw-r--r--target/arm/helper.c8
-rw-r--r--target/arm/syndrome.h5
-rw-r--r--target/arm/translate-a64.c11
-rw-r--r--target/arm/translate.c21
-rw-r--r--target/arm/translate.h2
7 files changed, 49 insertions, 0 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 6a987f65e4..fb0ef1ee2c 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3455,6 +3455,7 @@ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
+FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
/*
* Bit usage when in AArch32 state, both A- and M-profile.
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 26f79f9141..19445b3c94 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1071,6 +1071,7 @@ illegal_return:
if (!arm_singlestep_active(env)) {
env->pstate &= ~PSTATE_SS;
}
+ helper_rebuild_hflags_a64(env, cur_el);
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
}
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a7ae78146d..b210da2bc2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -13462,6 +13462,10 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
}
+ if (env->uncached_cpsr & CPSR_IL) {
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
+ }
+
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
}
@@ -13556,6 +13560,10 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
}
}
+ if (env->pstate & PSTATE_IL) {
+ DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
+ }
+
if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
/*
* Set MTE_ACTIVE if any access may be Checked, and leave clear
diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h
index 8dd88a0cb1..f30f4130a2 100644
--- a/target/arm/syndrome.h
+++ b/target/arm/syndrome.h
@@ -277,4 +277,9 @@ static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
(cv << 24) | (cond << 20) | ti;
}
+static inline uint32_t syn_illegalstate(void)
+{
+ return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
#endif /* TARGET_ARM_SYNDROME_H */
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 422e2ac0c9..230cc8d83b 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -14662,6 +14662,16 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
s->fp_access_checked = false;
s->sve_access_checked = false;
+ if (s->pstate_il) {
+ /*
+ * Illegal execution state. This has priority over BTI
+ * exceptions, but comes after instruction abort exceptions.
+ */
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+ syn_illegalstate(), default_exception_el(s));
+ return;
+ }
+
if (dc_isar_feature(aa64_bti, s)) {
if (s->base.num_insns == 1) {
/*
@@ -14780,6 +14790,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
#endif
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
dc->sve_len = (EX_TBFLAG_A64(tb_flags, ZCR_LEN) + 1) * 16;
dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 24b7f49d76..435c659723 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9090,6 +9090,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
return;
}
+ if (s->pstate_il) {
+ /*
+ * Illegal execution state. This has priority over BTI
+ * exceptions, but comes after instruction abort exceptions.
+ */
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
+ syn_illegalstate(), default_exception_el(s));
+ return;
+ }
+
if (cond == 0xf) {
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
* choose to UNDEF. In ARMv5 and above the space is used
@@ -9358,6 +9368,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
#endif
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
+ dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
if (arm_feature(env, ARM_FEATURE_M)) {
dc->vfp_enabled = 1;
@@ -9621,6 +9632,16 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
}
dc->insn = insn;
+ if (dc->pstate_il) {
+ /*
+ * Illegal execution state. This has priority over BTI
+ * exceptions, but comes after instruction abort exceptions.
+ */
+ gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
+ syn_illegalstate(), default_exception_el(dc));
+ return;
+ }
+
if (dc->eci) {
/*
* For M-profile continuable instructions, ECI/ICI handling
diff --git a/target/arm/translate.h b/target/arm/translate.h
index 8636c20c3b..605d1f2e33 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -98,6 +98,8 @@ typedef struct DisasContext {
bool hstr_active;
/* True if memory operations require alignment */
bool align_mem;
+ /* True if PSTATE.IL is set */
+ bool pstate_il;
/*
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
* < 0, set by the current instruction.