Message ID | 20240228092946.1768728-5-ruanjinjie@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | target/arm: Implement FEAT_NMI and FEAT_GICv3_NMI | expand |
On 2/27/24 23:29, Jinjie Ruan via wrote: > Add ALLINT MSR (immediate) to decodetree, in which the CRm is 0b000x. The > EL0 check is necessary to ALLINT, and the EL1 check is necessary when > imm == 1. So implement it inline for EL2/3, or EL1 with imm==0. Avoid the > unconditional write to pc and use raise_exception_ra to unwind. > > Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> > --- > v4: > - Fix the ALLINT MSR (immediate) decodetree implementation. > - Remove arm_is_el2_enabled() check in allint_check(). > - Update env->allint to env->pstate. > - Only call allint_check() when imm == 1. > - Simplify the allint_check() to not pass "op" and extract. > - Implement it inline for EL2/3, or EL1 with imm==0. > - Pass (a->imm & 1) * PSTATE_ALLINT (i64) to simplfy the ALLINT set/clear. > v3: > - Remove EL0 check in allint_check(). > - Add TALLINT check for EL1 in allint_check(). > - Remove unnecessarily arm_rebuild_hflags() in msr_i_allint helper. > --- > target/arm/tcg/a64.decode | 1 + > target/arm/tcg/helper-a64.c | 16 ++++++++++++++++ > target/arm/tcg/helper-a64.h | 1 + > target/arm/tcg/translate-a64.c | 19 +++++++++++++++++++ > 4 files changed, 37 insertions(+) > > diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode > index 8a20dce3c8..0e7656fd15 100644 > --- a/target/arm/tcg/a64.decode > +++ b/target/arm/tcg/a64.decode > @@ -207,6 +207,7 @@ MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i > MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i > MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i > MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i > +MSR_i_ALLINT 1101 0101 0000 0 001 0100 000 imm:1 000 11111 Good. > +static void allint_check(CPUARMState *env, uintptr_t ra) > +{ > + /* ALLINT update to PSTATE. */ > + if (arm_current_el(env) == 1 && (arm_hcrx_el2_eff(env) & HCRX_TALLINT)) { You know this will only be called for EL1. Since the function is only used once, might as well merge... > + raise_exception_ra(env, EXCP_UDEF, > + syn_aa64_sysregtrap(0, 1, 0, 4, 1, 0x1f, 0), > + exception_target_el(env), ra); > + } > +} > + > +void HELPER(msr_i_allint)(CPUARMState *env, uint64_t val) > +{ > + allint_check(env, GETPC()); ... with the only caller. > + env->pstate = (env->pstate & ~PSTATE_ALLINT) | (val & PSTATE_ALLINT); You know that val always equals PSTATE_ALLINT, so this simplifies to env->pstate |= PSTATE_ALLINT; I suggest a rename to msr_set_allint_el1. > +static bool trans_MSR_i_ALLINT(DisasContext *s, arg_i *a) > +{ > + if (!dc_isar_feature(aa64_nmi, s) || s->current_el == 0) { > + return false; > + } > + > + if ((a->imm & 1) == 0) { imm is only one bit, per decode, so you can drop the & 1 here. > + clear_pstate_bits(PSTATE_ALLINT); > + } else if (s->current_el > 1) { > + set_pstate_bits(PSTATE_ALLINT); > + } else { > + gen_helper_msr_i_allint(tcg_env, > + tcg_constant_tl((a->imm & 1) * PSTATE_ALLINT)); Because you've already eliminated imm == 0, you know imm is always 1, so that simplifies the entire function definition, per above. r~
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode index 8a20dce3c8..0e7656fd15 100644 --- a/target/arm/tcg/a64.decode +++ b/target/arm/tcg/a64.decode @@ -207,6 +207,7 @@ MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i +MSR_i_ALLINT 1101 0101 0000 0 001 0100 000 imm:1 000 11111 MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111 # MRS, MSR (register), SYS, SYSL. These are all essentially the diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index ebaa7f00df..3d912febc3 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -66,6 +66,22 @@ void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm) update_spsel(env, imm); } +static void allint_check(CPUARMState *env, uintptr_t ra) +{ + /* ALLINT update to PSTATE. */ + if (arm_current_el(env) == 1 && (arm_hcrx_el2_eff(env) & HCRX_TALLINT)) { + raise_exception_ra(env, EXCP_UDEF, + syn_aa64_sysregtrap(0, 1, 0, 4, 1, 0x1f, 0), + exception_target_el(env), ra); + } +} + +void HELPER(msr_i_allint)(CPUARMState *env, uint64_t val) +{ + allint_check(env, GETPC()); + env->pstate = (env->pstate & ~PSTATE_ALLINT) | (val & PSTATE_ALLINT); +} + static void daif_check(CPUARMState *env, uint32_t op, uint32_t imm, uintptr_t ra) { diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h index 575a5dab7d..64351f20f3 100644 --- a/target/arm/tcg/helper-a64.h +++ b/target/arm/tcg/helper-a64.h @@ -22,6 +22,7 @@ DEF_HELPER_FLAGS_1(rbit64, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_2(msr_i_spsel, void, env, i32) DEF_HELPER_2(msr_i_daifset, void, env, i32) DEF_HELPER_2(msr_i_daifclear, void, env, i32) +DEF_HELPER_2(msr_i_allint, void, env, i64) DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr) DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr) DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr) diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 340265beb0..9ef2ba912d 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -2036,6 +2036,25 @@ static bool trans_MSR_i_DAIFCLEAR(DisasContext *s, arg_i *a) return true; } +static bool trans_MSR_i_ALLINT(DisasContext *s, arg_i *a) +{ + if (!dc_isar_feature(aa64_nmi, s) || s->current_el == 0) { + return false; + } + + if ((a->imm & 1) == 0) { + clear_pstate_bits(PSTATE_ALLINT); + } else if (s->current_el > 1) { + set_pstate_bits(PSTATE_ALLINT); + } else { + gen_helper_msr_i_allint(tcg_env, + tcg_constant_tl((a->imm & 1) * PSTATE_ALLINT)); + } + + s->base.is_jmp = DISAS_TOO_MANY; + return true; +} + static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a) { if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
Add ALLINT MSR (immediate) to decodetree, in which the CRm is 0b000x. The EL0 check is necessary to ALLINT, and the EL1 check is necessary when imm == 1. So implement it inline for EL2/3, or EL1 with imm==0. Avoid the unconditional write to pc and use raise_exception_ra to unwind. Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com> --- v4: - Fix the ALLINT MSR (immediate) decodetree implementation. - Remove arm_is_el2_enabled() check in allint_check(). - Update env->allint to env->pstate. - Only call allint_check() when imm == 1. - Simplify the allint_check() to not pass "op" and extract. - Implement it inline for EL2/3, or EL1 with imm==0. - Pass (a->imm & 1) * PSTATE_ALLINT (i64) to simplfy the ALLINT set/clear. v3: - Remove EL0 check in allint_check(). - Add TALLINT check for EL1 in allint_check(). - Remove unnecessarily arm_rebuild_hflags() in msr_i_allint helper. --- target/arm/tcg/a64.decode | 1 + target/arm/tcg/helper-a64.c | 16 ++++++++++++++++ target/arm/tcg/helper-a64.h | 1 + target/arm/tcg/translate-a64.c | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+)