From: Richard Henderson <[email protected]> Prepare to perform access checks for direct and indirect uses of FPMR.
Reviewed-by: Peter Maydell <[email protected]> Signed-off-by: Richard Henderson <[email protected]> Message-id: [email protected] Signed-off-by: Peter Maydell <[email protected]> --- target/arm/cpu.h | 1 + target/arm/tcg/hflags.c | 42 ++++++++++++++++++++++++++++++++++ target/arm/tcg/translate-a64.c | 1 + target/arm/tcg/translate.h | 2 ++ 4 files changed, 46 insertions(+) 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; -- 2.43.0
