On 6/21/25 16:49, Richard Henderson wrote:
> Pipe the value through from SMCR_ELx through hflags
> and into the disassembly context.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> target/arm/cpu.h | 2 ++
> target/arm/tcg/translate.h | 1 +
> target/arm/cpu.c | 3 +++
> target/arm/tcg/hflags.c | 34 +++++++++++++++++++++++++++++++++-
> target/arm/tcg/translate-a64.c | 1 +
> 5 files changed, 40 insertions(+), 1 deletion(-)
Missing update to smcr_write to enable the EZT0 bit.
r~
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 465fc188d0..fae253e567 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1497,6 +1497,7 @@ FIELD(SVCR, ZA, 1, 1)
>
> /* Fields for SMCR_ELx. */
> FIELD(SMCR, LEN, 0, 4)
> +FIELD(SMCR, EZT0, 30, 1)
> FIELD(SMCR, FA64, 31, 1)
>
> /* Write a new value to v7m.exception, thus transitioning into or out
> @@ -3067,6 +3068,7 @@ FIELD(TBFLAG_A64, NV2_MEM_E20, 35, 1)
> FIELD(TBFLAG_A64, NV2_MEM_BE, 36, 1)
> FIELD(TBFLAG_A64, AH, 37, 1) /* FPCR.AH */
> FIELD(TBFLAG_A64, NEP, 38, 1) /* FPCR.NEP */
> +FIELD(TBFLAG_A64, ZT0EXC_EL, 39, 2)
>
> /*
> * Helpers for using the above. Note that only the A64 accessors use
> diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
> index 1bfdb0fb9b..5153824a49 100644
> --- a/target/arm/tcg/translate.h
> +++ b/target/arm/tcg/translate.h
> @@ -70,6 +70,7 @@ typedef struct DisasContext {
> int fp_excp_el; /* FP exception EL or 0 if enabled */
> int sve_excp_el; /* SVE exception EL or 0 if enabled */
> int sme_excp_el; /* SME exception EL or 0 if enabled */
> + int zt0_excp_el; /* ZT0 exception EL or 0 if enabled */
> int vl; /* current vector length in bytes */
> int svl; /* current streaming vector length in bytes */
> bool vfp_enabled; /* FP enabled via FPSCR.EN */
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index f7cbdd6814..3ceb8d87f4 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -635,6 +635,9 @@ void arm_emulate_firmware_reset(CPUState *cpustate, int target_el)
> env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK;
> env->cp15.scr_el3 |= SCR_ENTP2;
> env->vfp.smcr_el[3] = 0xf;
> + if (cpu_isar_feature(aa64_sme2, cpu)) {
> + env->vfp.smcr_el[3] |= R_SMCR_EZT0_MASK;
> + }
> }
> if (cpu_isar_feature(aa64_hcx, cpu)) {
> env->cp15.scr_el3 |= SCR_HXEN;
> diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
> index 1ccec63bbd..59ab526375 100644
> --- a/target/arm/tcg/hflags.c
> +++ b/target/arm/tcg/hflags.c
> @@ -214,6 +214,31 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
> return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
> }
>
> +/*
> + * Return the exception level to which exceptions should be taken for ZT0.
> + * C.f. the ARM pseudocode function CheckSMEZT0Enabled, after the ZA check.
> + */
> +static int zt0_exception_el(CPUARMState *env, int el)
> +{
> +#ifndef CONFIG_USER_ONLY
> + if (el <= 1
> + && !el_is_in_host(env, el)
> + && !FIELD_EX64(env->vfp.smcr_el[1], SMCR, EZT0)) {
> + return 1;
> + }
> + if (el <= 2
> + && arm_is_el2_enabled(env)
> + && !FIELD_EX64(env->vfp.smcr_el[2], SMCR, EZT0)) {
> + return 2;
> + }
> + if (arm_feature(env, ARM_FEATURE_EL3)
> + && !FIELD_EX64(env->vfp.smcr_el[3], SMCR, EZT0)) {
> + return 3;
> + }
> +#endif
> + return 0;
> +}
> +
> static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
> ARMMMUIdx mmu_idx)
> {
> @@ -269,7 +294,14 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
> DP_TBFLAG_A64(flags, PSTATE_SM, 1);
> DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el));
> }
> - DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA));
> +
> + if (FIELD_EX64(env->svcr, SVCR, ZA)) {
> + DP_TBFLAG_A64(flags, PSTATE_ZA, 1);
> + if (cpu_isar_feature(aa64_sme2, env_archcpu(env))) {
> + int zt0_el = zt0_exception_el(env, el);
> + DP_TBFLAG_A64(flags, ZT0EXC_EL, zt0_el);
> + }
> + }
> }
>
> sctlr = regime_sctlr(env, stage1);
> diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
> index ac80f572a2..f7737f5d86 100644
> --- a/target/arm/tcg/translate-a64.c
> +++ b/target/arm/tcg/translate-a64.c
> @@ -10128,6 +10128,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
> dc->trap_eret = EX_TBFLAG_A64(tb_flags, TRAP_ERET);
> dc->sve_excp_el = EX_TBFLAG_A64(tb_flags, SVEEXC_EL);
> dc->sme_excp_el = EX_TBFLAG_A64(tb_flags, SMEEXC_EL);
> + dc->zt0_excp_el = EX_TBFLAG_A64(tb_flags, ZT0EXC_EL);
> dc->vl = (EX_TBFLAG_A64(tb_flags, VL) + 1) * 16;
> dc->svl = (EX_TBFLAG_A64(tb_flags, SVL) + 1) * 16;
> dc->pauth_active = EX_TBFLAG_A64(tb_flags, PAUTH_ACTIVE);