@samitouri / QOSamiQemu / commits / 60e7ee5bb7

target/arm: implements SEV/SEVL for all modes

Remove the restrictions that make this a M-profile only operation and enable the instructions for all Arm profiles. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Message-id: 20260624103049.884930-6-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Alex Bennée committed Jun 24, 2026 at 11:30 UTC 60e7ee5bb7cde8a91f196dff0279774cd46ba70a
8 files changed +59 -18
target/arm/tcg/a32.decode
+2 -3
@@ -192,9 +192,8 @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn
192 WFE ---- 0011 0010 0000 1111 ---- 0000 0010
193 WFI ---- 0011 0010 0000 1111 ---- 0000 0011
194
195 - # TODO: Implement SEV, SEVL; may help SMP performance.
196 - # SEV ---- 0011 0010 0000 1111 ---- 0000 0100
197 - # SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
195 + SEV ---- 0011 0010 0000 1111 ---- 0000 0100
196 + SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
197
198 ESB ---- 0011 0010 0000 1111 ---- 0001 0000
199 ]
target/arm/tcg/a64.decode
+2 -3
@@ -250,9 +250,8 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
250 YIELD 1101 0101 0000 0011 0010 0000 001 11111
251 WFE 1101 0101 0000 0011 0010 0000 010 11111
252 WFI 1101 0101 0000 0011 0010 0000 011 11111
253 - # We implement WFE to never block, so our SEV/SEVL are NOPs
254 - # SEV 1101 0101 0000 0011 0010 0000 100 11111
255 - # SEVL 1101 0101 0000 0011 0010 0000 101 11111
253 + SEV 1101 0101 0000 0011 0010 0000 100 11111
254 + SEVL 1101 0101 0000 0011 0010 0000 101 11111
255 # Our DGL is a NOP because we don't merge memory accesses anyway.
256 # DGL 1101 0101 0000 0011 0010 0000 110 11111
257 XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
target/arm/tcg/op_helper.c
+1 -3
@@ -477,9 +477,7 @@ void HELPER(sev)(CPUARMState *env)
477 CPUState *cs = env_cpu(env);
478 CPU_FOREACH(cs) {
479 ARMCPU *target_cpu = ARM_CPU(cs);
480 - if (arm_feature(&target_cpu->env, ARM_FEATURE_M)) {
481 - target_cpu->env.event_register = true;
482 - }
480 + target_cpu->env.event_register = true;
481 if (!qemu_cpu_is_self(cs)) {
482 qemu_cpu_kick(cs);
483 }
target/arm/tcg/t16.decode
+1 -3
@@ -228,10 +228,8 @@ REVSH 1011 1010 11 ... ... @rdm
228 WFE 1011 1111 0010 0000
229 WFI 1011 1111 0011 0000
230
231 - # M-profile SEV is implemented.
232 - # TODO: Implement SEV for other profiles, and SEVL for all profiles; may help SMP performance.
231 SEV 1011 1111 0100 0000
234 - # SEVL 1011 1111 0101 0000
232 + SEVL 1011 1111 0101 0000
233
234 # The canonical nop has the second nibble as 0000, but the whole of the
235 # rest of the space is a reserved hint, behaves as nop.
target/arm/tcg/t32.decode
+1 -3
@@ -369,10 +369,8 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
369 WFE 1111 0011 1010 1111 1000 0000 0000 0010
370 WFI 1111 0011 1010 1111 1000 0000 0000 0011
371
372 - # M-profile SEV is implemented.
373 - # TODO: Implement SEV for other profiles, and SEVL for all profiles; may help SMP performance.
372 SEV 1111 0011 1010 1111 1000 0000 0000 0100
375 - # SEVL 1111 0011 1010 1111 1000 0000 0000 0101
373 + SEVL 1111 0011 1010 1111 1000 0000 0000 0101
374
375 ESB 1111 0011 1010 1111 1000 0000 0001 0000
376 ]
target/arm/tcg/translate-a64.c
+17
@@ -2142,6 +2142,23 @@ static bool trans_WFI(DisasContext *s, arg_WFI *a)
2142 return true;
2143 }
2144
2145 +static bool trans_SEV(DisasContext *s, arg_SEV *a)
2146 +{
2147 + /*
2148 + * SEV is a NOP for user-mode emulation.
2149 + */
2150 +#ifndef CONFIG_USER_ONLY
2151 + gen_helper_sev(tcg_env);
2152 +#endif
2153 + return true;
2154 +}
2155 +
2156 +static bool trans_SEVL(DisasContext *s, arg_SEV *a)
2157 +{
2158 + gen_event_reg();
2159 + return true;
2160 +}
2161 +
2162 static bool trans_WFE(DisasContext *s, arg_WFI *a)
2163 {
2164 /*
target/arm/tcg/translate.c
+17 -3
@@ -3246,17 +3246,31 @@ static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
3246 static bool trans_SEV(DisasContext *s, arg_SEV *a)
3247 {
3248 /*
3249 - * Currently SEV is a NOP for non-M-profile and in user-mode emulation.
3250 - * For system-mode M-profile, it sets the event register.
3249 + * SEV is a NOP for user-mode emulation. For v6T2 and earlier
3250 + * non-M-profile cores this encoding is a NOP hint.
3251 */
3252 #ifndef CONFIG_USER_ONLY
3253 - if (arm_dc_feature(s, ARM_FEATURE_M)) {
3253 + if (arm_dc_feature(s, ARM_FEATURE_M) ||
3254 + arm_dc_feature(s, ARM_FEATURE_V7)) {
3255 gen_helper_sev(tcg_env);
3256 }
3257 #endif
3258 return true;
3259 }
3260
3261 +static bool trans_SEVL(DisasContext *s, arg_SEV *a)
3262 +{
3263 + /*
3264 + * SEVL only exists for v8A; for M-profile and v7A and earlier
3265 + * this encoding is an unallocated must-NOP hint.
3266 + */
3267 + if (!arm_dc_feature(s, ARM_FEATURE_M) &&
3268 + arm_dc_feature(s, ARM_FEATURE_V8)) {
3269 + gen_event_reg();
3270 + }
3271 + return true;
3272 +}
3273 +
3274 static bool trans_WFE(DisasContext *s, arg_WFE *a)
3275 {
3276 /*
target/arm/tcg/translate.h
+18
@@ -860,6 +860,24 @@ static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
860 gen_helper_set_rmode(old, old, fpst);
861 }
862
863 +/*
864 + * Event Register signalling.
865 + *
866 + * A bunch of activities trigger events, we just need to latch on to
867 + * true. The event eventually gets consumed by WFE/WFET.
868 + *
869 + * user-mode treats these as NOPs.
870 + */
871 +
872 +static inline void gen_event_reg(void)
873 +{
874 +#ifndef CONFIG_USER_ONLY
875 + TCGv_i32 set_event = tcg_constant_i32(1);
876 + QEMU_BUILD_BUG_ON(sizeof_field(CPUARMState, event_register) != 1);
877 + tcg_gen_st8_i32(set_event, tcg_env, offsetof(CPUARMState, event_register));
878 +#endif
879 +}
880 +
881 /*
882 * Helpers for implementing sets of trans_* functions.
883 * Defer the implementation of NAME to FUNC, with optional extra arguments.