Remove the restrictions that make this a M-profile only operation and enable the instructions for all Arm profiles. Reviewed-by: Richard Henderson Signed-off-by: Alex Bennée --- v3 - restrict SEV to M profile plus - restrict SEVL to V8 v2 - fix alignment in a32.decode - set bool directly, defend with QEMU_BUILD_BUG_ON - s/instructions/profiles/ - share get_event_reg between translate/translate-a64 --- target/arm/tcg/translate.h | 18 ++++++++++++++++++ target/arm/tcg/a32.decode | 5 ++--- target/arm/tcg/a64.decode | 5 ++--- target/arm/tcg/t16.decode | 4 +--- target/arm/tcg/t32.decode | 4 +--- target/arm/tcg/op_helper.c | 4 +--- target/arm/tcg/translate-a64.c | 17 +++++++++++++++++ target/arm/tcg/translate.c | 20 +++++++++++++++++--- 8 files changed, 59 insertions(+), 18 deletions(-) diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h index 462d4c1c74f..83b413ee368 100644 --- a/target/arm/tcg/translate.h +++ b/target/arm/tcg/translate.h @@ -860,6 +860,24 @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst) gen_helper_set_rmode(old, old, fpst); } +/* + * Event Register signalling. + * + * A bunch of activities trigger events, we just need to latch on to + * true. The event eventually gets consumed by WFE/WFET. + * + * user-mode treats these as NOPs. + */ + +static inline void gen_event_reg(void) +{ +#ifndef CONFIG_USER_ONLY + TCGv_i32 set_event = tcg_constant_i32(1); + QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, event_register) != 1); + tcg_gen_st8_i32(set_event, tcg_env, offsetof(CPUARMState, event_register)); +#endif +} + /* * Helpers for implementing sets of trans_* functions. * Defer the implementation of NAME to FUNC, with optional extra arguments. diff --git a/target/arm/tcg/a32.decode b/target/arm/tcg/a32.decode index f2ca4809495..547aa2b1490 100644 --- a/target/arm/tcg/a32.decode +++ b/target/arm/tcg/a32.decode @@ -192,9 +192,8 @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn WFE ---- 0011 0010 0000 1111 ---- 0000 0010 WFI ---- 0011 0010 0000 1111 ---- 0000 0011 - # TODO: Implement SEV, SEVL; may help SMP performance. - # SEV ---- 0011 0010 0000 1111 ---- 0000 0100 - # SEVL ---- 0011 0010 0000 1111 ---- 0000 0101 + SEV ---- 0011 0010 0000 1111 ---- 0000 0100 + SEVL ---- 0011 0010 0000 1111 ---- 0000 0101 ESB ---- 0011 0010 0000 1111 ---- 0001 0000 ] diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode index 28cd1faf61a..81070dac0a6 100644 --- a/target/arm/tcg/a64.decode +++ b/target/arm/tcg/a64.decode @@ -250,9 +250,8 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB YIELD 1101 0101 0000 0011 0010 0000 001 11111 WFE 1101 0101 0000 0011 0010 0000 010 11111 WFI 1101 0101 0000 0011 0010 0000 011 11111 - # We implement WFE to never block, so our SEV/SEVL are NOPs - # SEV 1101 0101 0000 0011 0010 0000 100 11111 - # SEVL 1101 0101 0000 0011 0010 0000 101 11111 + SEV 1101 0101 0000 0011 0010 0000 100 11111 + SEVL 1101 0101 0000 0011 0010 0000 101 11111 # Our DGL is a NOP because we don't merge memory accesses anyway. # DGL 1101 0101 0000 0011 0010 0000 110 11111 XPACLRI 1101 0101 0000 0011 0010 0000 111 11111 diff --git a/target/arm/tcg/t16.decode b/target/arm/tcg/t16.decode index 778fbf16275..9a8f89538ac 100644 --- a/target/arm/tcg/t16.decode +++ b/target/arm/tcg/t16.decode @@ -228,10 +228,8 @@ REVSH 1011 1010 11 ... ... @rdm WFE 1011 1111 0010 0000 WFI 1011 1111 0011 0000 - # M-profile SEV is implemented. - # TODO: Implement SEV for other profiles, and SEVL for all profiles; may help SMP performance. SEV 1011 1111 0100 0000 - # SEVL 1011 1111 0101 0000 + SEVL 1011 1111 0101 0000 # The canonical nop has the second nibble as 0000, but the whole of the # rest of the space is a reserved hint, behaves as nop. diff --git a/target/arm/tcg/t32.decode b/target/arm/tcg/t32.decode index 49b8d0037ec..8ae277fe112 100644 --- a/target/arm/tcg/t32.decode +++ b/target/arm/tcg/t32.decode @@ -369,10 +369,8 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm WFE 1111 0011 1010 1111 1000 0000 0000 0010 WFI 1111 0011 1010 1111 1000 0000 0000 0011 - # M-profile SEV is implemented. - # TODO: Implement SEV for other profiles, and SEVL for all profiles; may help SMP performance. SEV 1111 0011 1010 1111 1000 0000 0000 0100 - # SEVL 1111 0011 1010 1111 1000 0000 0000 0101 + SEVL 1111 0011 1010 1111 1000 0000 0000 0101 ESB 1111 0011 1010 1111 1000 0000 0001 0000 ] diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index 9f9ea39be5a..d15062e155f 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -477,9 +477,7 @@ void HELPER(sev)(CPUARMState *env) CPUState *cs = env_cpu(env); CPU_FOREACH(cs) { ARMCPU *target_cpu = ARM_CPU(cs); - if (arm_feature(&target_cpu->env, ARM_FEATURE_M)) { - target_cpu->env.event_register = true; - } + target_cpu->env.event_register = true; if (!qemu_cpu_is_self(cs)) { qemu_cpu_kick(cs); } diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 227719ef25b..df5bac22acd 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -2142,6 +2142,23 @@ static bool trans_WFI(DisasContext *s, arg_WFI *a) return true; } +static bool trans_SEV(DisasContext *s, arg_SEV *a) +{ + /* + * SEV is a NOP for user-mode emulation. + */ +#ifndef CONFIG_USER_ONLY + gen_helper_sev(tcg_env); +#endif + return true; +} + +static bool trans_SEVL(DisasContext *s, arg_SEV *a) +{ + gen_event_reg(); + return true; +} + static bool trans_WFE(DisasContext *s, arg_WFI *a) { /* diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c index c744b163453..9079458a297 100644 --- a/target/arm/tcg/translate.c +++ b/target/arm/tcg/translate.c @@ -3246,17 +3246,31 @@ static bool trans_YIELD(DisasContext *s, arg_YIELD *a) static bool trans_SEV(DisasContext *s, arg_SEV *a) { /* - * Currently SEV is a NOP for non-M-profile and in user-mode emulation. - * For system-mode M-profile, it sets the event register. + * SEV is a NOP for user-mode emulation. For v6T2 and earlier + * non-M-profile cores this encoding is a NOP hint. */ #ifndef CONFIG_USER_ONLY - if (arm_dc_feature(s, ARM_FEATURE_M)) { + if (arm_dc_feature(s, ARM_FEATURE_M) || + arm_dc_feature(s, ARM_FEATURE_V7)) { gen_helper_sev(tcg_env); } #endif return true; } +static bool trans_SEVL(DisasContext *s, arg_SEV *a) +{ + /* + * SEVL only exists for v8A; for M-profile and v7A and earlier + * this encoding is an unallocated must-NOP hint. + */ + if (!arm_dc_feature(s, ARM_FEATURE_M) && + arm_dc_feature(s, ARM_FEATURE_V8)) { + gen_event_reg(); + } + return true; +} + static bool trans_WFE(DisasContext *s, arg_WFE *a) { /* -- 2.47.3