diff options
-rw-r--r-- | target/arm/cpu.h | 1 | ||||
-rw-r--r-- | target/arm/helper-a64.c | 1 | ||||
-rw-r--r-- | target/arm/helper.c | 8 | ||||
-rw-r--r-- | target/arm/syndrome.h | 5 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 11 | ||||
-rw-r--r-- | target/arm/translate.c | 21 | ||||
-rw-r--r-- | target/arm/translate.h | 2 |
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. |