diff mbox series

[v2,017/101] target/arm: Add zt0_excp_el to DisasContext

Message ID 20250621235037.74091-18-richard.henderson@linaro.org
State New
Headers show
Series target/arm: Implement FEAT_SME2p1 | expand

Commit Message

Richard Henderson June 21, 2025, 11:49 p.m. UTC
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(-)

Comments

Richard Henderson June 22, 2025, 8:21 p.m. UTC | #1
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);
diff mbox series

Patch

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);