Clear UINJ when taking an exception. Clear UINJ when exception return is invalid.
In both cases, perform the clear without feature check, since the bit is otherwise RES0. Reviewed-by: Peter Maydell <[email protected]> Signed-off-by: Richard Henderson <[email protected]> --- target/arm/cpu.h | 1 + target/arm/helper.c | 9 +++++++++ target/arm/tcg/helper-a64.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d36611e04a5..735e777d103 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1579,6 +1579,7 @@ void pmu_init(ARMCPU *cpu); #define PSTATE_Z (1 << 30) #define PSTATE_N (1ULL << 31) #define PSTATE_EXLOCK (1ULL << 34) +#define PSTATE_UINJ (1ULL << 36) #define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V) #define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F) #define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF | PSTATE_BTYPE) diff --git a/target/arm/helper.c b/target/arm/helper.c index c3f607e6d6b..0111cbeac03 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9606,6 +9606,15 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) env->condexec_bits = 0; } + + /* + * R_XKSNJ: If FEAT_UINJ, PSTATE.UINJ is set to 0 *and* the resulting + * value stored in SPSR_ELx is 0. The new PSTATE is automatically + * handled by construction of a new value from 0; clear it from the + * old state and as UINJ is RES0 otherwise, skip the feature check. + */ + old_mode &= ~PSTATE_UINJ; + env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode; qemu_log_mask(CPU_LOG_INT, "...with SPSR 0x%" PRIx64 "\n", old_mode); diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index 9d805231a08..f76d89990c3 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -764,10 +764,12 @@ illegal_return: * mandated behaviour: * restore NZCV and DAIF from SPSR_ELx * set PSTATE.IL + * reset PSTATE.UINJ * restore PC from ELR_ELx * no change to exception level, execution state or stack pointer */ env->pstate |= PSTATE_IL; + env->pstate &= ~PSTATE_UINJ; env->pc = new_pc; spsr &= PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT; spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT); -- 2.53.0
