Commit cc04352a1f for qemu.org
commit cc04352a1f100c64d0a467bc678cae16713da4b8
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Fri May 22 15:02:14 2026 -0700
target/arm: Add FPMR_EL to TBFLAGS
Prepare to perform access checks for direct and
indirect uses of FPMR.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20260522220306.235200-13-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index e9e261eb2a..2a93de4132 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2567,6 +2567,7 @@ FIELD(TBFLAG_A64, ZT0EXC_EL, 39, 2)
FIELD(TBFLAG_A64, GCS_EN, 41, 1)
FIELD(TBFLAG_A64, GCS_RVCEN, 42, 1)
FIELD(TBFLAG_A64, GCSSTR_EL, 43, 2)
+FIELD(TBFLAG_A64, FPMR_EL, 45, 2)
/*
* Helpers for using the above. Note that only the A64 accessors use
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
index 7e6f8d3647..794cdf00b2 100644
--- a/target/arm/tcg/hflags.c
+++ b/target/arm/tcg/hflags.c
@@ -237,6 +237,44 @@ static int zt0_exception_el(CPUARMState *env, int el)
return 0;
}
+/*
+ * Return the exception level to which exceptions should be taken for FPMR.
+ * Compare the EnFPM bits in the "Accessing FPMR" pseudocode. Note that
+ * the floating-point enabled check will be handled separately.
+ */
+static int fpmr_exception_el(CPUARMState *env, int el)
+{
+ switch (el) {
+ case 0:
+ if (el_is_in_host(env, 0)) {
+ if (!(env->cp15.sctlr_el[2] & SCTLR_EnFPM)) {
+ return 2;
+ }
+ break;
+ }
+ if (!(env->cp15.sctlr_el[1] & SCTLR_EnFPM)) {
+ return 1;
+ }
+ /* fall through */
+ case 1:
+ if (!(arm_hcrx_el2_eff(env) & HCRX_ENFPM)) {
+ return 2;
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ return 0;
+ default:
+ g_assert_not_reached();
+ }
+ if (arm_feature(env, ARM_FEATURE_EL3)
+ && !(env->cp15.scr_el3 & SCR_ENFPM)) {
+ return 3;
+ }
+ return 0;
+}
+
static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
ARMMMUIdx mmu_idx)
{
@@ -500,6 +538,10 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
}
}
+ if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
+ DP_TBFLAG_A64(flags, FPMR_EL, fpmr_exception_el(env, el));
+ }
+
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
}
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index b5f953ab0a..d1a581acfd 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -10723,6 +10723,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->gcs_en = EX_TBFLAG_A64(tb_flags, GCS_EN);
dc->gcs_rvcen = EX_TBFLAG_A64(tb_flags, GCS_RVCEN);
dc->gcsstr_el = EX_TBFLAG_A64(tb_flags, GCSSTR_EL);
+ dc->fpmr_el = EX_TBFLAG_A64(tb_flags, FPMR_EL);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;
diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 2a586321c8..d4bcc5bad4 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -199,6 +199,8 @@ typedef struct DisasContext {
uint8_t gm_blocksize;
/* True if the current insn_start has been updated. */
bool insn_start_updated;
+ /* FPMR access exception EL or 0 if enabled. */
+ uint8_t fpmr_el;
/* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */
uint32_t nv2_redirect_offset;
} DisasContext;