Skip to content

Commit 520d162

Browse files
committed
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 <[email protected]> Signed-off-by: Richard Henderson <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-id: [email protected] Message-Id: <[email protected]> Reviewed-by: Richard Henderson <[email protected]> [rth: Added missing returns; set IL bit in syndrome] Signed-off-by: Richard Henderson <[email protected]>
1 parent 0a93293 commit 520d162

File tree

7 files changed

+49
-0
lines changed

7 files changed

+49
-0
lines changed

target/arm/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,6 +3455,7 @@ FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
34553455
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
34563456
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
34573457
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
3458+
FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
34583459

34593460
/*
34603461
* Bit usage when in AArch32 state, both A- and M-profile.

target/arm/helper-a64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,7 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
10711071
if (!arm_singlestep_active(env)) {
10721072
env->pstate &= ~PSTATE_SS;
10731073
}
1074+
helper_rebuild_hflags_a64(env, cur_el);
10741075
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
10751076
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
10761077
}

target/arm/helper.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13462,6 +13462,10 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
1346213462
DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1);
1346313463
}
1346413464

13465+
if (env->uncached_cpsr & CPSR_IL) {
13466+
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
13467+
}
13468+
1346513469
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
1346613470
}
1346713471

@@ -13556,6 +13560,10 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
1355613560
}
1355713561
}
1355813562

13563+
if (env->pstate & PSTATE_IL) {
13564+
DP_TBFLAG_ANY(flags, PSTATE__IL, 1);
13565+
}
13566+
1355913567
if (cpu_isar_feature(aa64_mte, env_archcpu(env))) {
1356013568
/*
1356113569
* Set MTE_ACTIVE if any access may be Checked, and leave clear

target/arm/syndrome.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,9 @@ static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit)
277277
(cv << 24) | (cond << 20) | ti;
278278
}
279279

280+
static inline uint32_t syn_illegalstate(void)
281+
{
282+
return (EC_ILLEGALSTATE << ARM_EL_EC_SHIFT) | ARM_EL_IL;
283+
}
284+
280285
#endif /* TARGET_ARM_SYNDROME_H */

target/arm/translate-a64.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14662,6 +14662,16 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
1466214662
s->fp_access_checked = false;
1466314663
s->sve_access_checked = false;
1466414664

14665+
if (s->pstate_il) {
14666+
/*
14667+
* Illegal execution state. This has priority over BTI
14668+
* exceptions, but comes after instruction abort exceptions.
14669+
*/
14670+
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
14671+
syn_illegalstate(), default_exception_el(s));
14672+
return;
14673+
}
14674+
1466514675
if (dc_isar_feature(aa64_bti, s)) {
1466614676
if (s->base.num_insns == 1) {
1466714677
/*
@@ -14780,6 +14790,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
1478014790
#endif
1478114791
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
1478214792
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
14793+
dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
1478314794
dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
1478414795
dc->sve_len = (EX_TBFLAG_A64(tb_flags, ZCR_LEN) + 1) * 16;
1478514796
dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);

target/arm/translate.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9090,6 +9090,16 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
90909090
return;
90919091
}
90929092

9093+
if (s->pstate_il) {
9094+
/*
9095+
* Illegal execution state. This has priority over BTI
9096+
* exceptions, but comes after instruction abort exceptions.
9097+
*/
9098+
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
9099+
syn_illegalstate(), default_exception_el(s));
9100+
return;
9101+
}
9102+
90939103
if (cond == 0xf) {
90949104
/* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
90959105
* 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)
93589368
#endif
93599369
dc->fp_excp_el = EX_TBFLAG_ANY(tb_flags, FPEXC_EL);
93609370
dc->align_mem = EX_TBFLAG_ANY(tb_flags, ALIGN_MEM);
9371+
dc->pstate_il = EX_TBFLAG_ANY(tb_flags, PSTATE__IL);
93619372

93629373
if (arm_feature(env, ARM_FEATURE_M)) {
93639374
dc->vfp_enabled = 1;
@@ -9621,6 +9632,16 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
96219632
}
96229633
dc->insn = insn;
96239634

9635+
if (dc->pstate_il) {
9636+
/*
9637+
* Illegal execution state. This has priority over BTI
9638+
* exceptions, but comes after instruction abort exceptions.
9639+
*/
9640+
gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
9641+
syn_illegalstate(), default_exception_el(dc));
9642+
return;
9643+
}
9644+
96249645
if (dc->eci) {
96259646
/*
96269647
* For M-profile continuable instructions, ECI/ICI handling

target/arm/translate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ typedef struct DisasContext {
9898
bool hstr_active;
9999
/* True if memory operations require alignment */
100100
bool align_mem;
101+
/* True if PSTATE.IL is set */
102+
bool pstate_il;
101103
/*
102104
* >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
103105
* < 0, set by the current instruction.

0 commit comments

Comments
 (0)