A recent change to the kernel (Linux commit b376108e1f88
"arm64/fpsimd: signal: Clear TPIDR2 when delivering signals") updated
the signal-handler entry code to always clear TPIDR2_EL0.
This is necessary for the userspace ZA lazy saving scheme to work
correctly when unwinding exceptions across a signal boundary.
(For the essay-length description of the incorrect behaviour and
why this is the correct fix, see the commit message for the
kernel commit.)
Make QEMU also clear TPIDR2_EL0 on signal entry, applying the
equivalent bugfix to our implementation.
Note that getting this unwinding to work correctly also requires
changes to the userspace code, e.g. as implemented in gcc in
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b5ffc8e75a8
This change is technically an ABI change; from the kernel's
point of view SME was never enabled (it was hidden behind
CONFIG_BROKEN) before the change. From QEMU's point of view
our SME-related signal handling was broken anyway as we weren't
saving and restoring TPIDR2_EL0.
Cc: qemu-stable@nongnu.org
Fixes: 78011586b90d1 ("target/arm: Enable SME for user-only")
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/aarch64/signal.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index d50cab78d83..6514b73ad98 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -666,8 +666,12 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
env->btype = 2;
}
- /* Invoke the signal handler with both SM and ZA disabled. */
+ /*
+ * Invoke the signal handler with a clean SME state: both SM and ZA
+ * disabled and TPIDR2_EL0 cleared.
+ */
aarch64_set_svcr(env, 0, R_SVCR_SM_MASK | R_SVCR_ZA_MASK);
+ env->cp15.tpidr2_el0 = 0;
if (info) {
frame->info = *info;
--
2.43.0
On 25.07.2025 20:55, Peter Maydell wrote:
> A recent change to the kernel (Linux commit b376108e1f88
> "arm64/fpsimd: signal: Clear TPIDR2 when delivering signals") updated
> the signal-handler entry code to always clear TPIDR2_EL0.
>
> This is necessary for the userspace ZA lazy saving scheme to work
> correctly when unwinding exceptions across a signal boundary.
> (For the essay-length description of the incorrect behaviour and
> why this is the correct fix, see the commit message for the
> kernel commit.)
>
> Make QEMU also clear TPIDR2_EL0 on signal entry, applying the
> equivalent bugfix to our implementation.
>
> Note that getting this unwinding to work correctly also requires
> changes to the userspace code, e.g. as implemented in gcc in
> https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b5ffc8e75a8
>
> This change is technically an ABI change; from the kernel's
> point of view SME was never enabled (it was hidden behind
> CONFIG_BROKEN) before the change. From QEMU's point of view
> our SME-related signal handling was broken anyway as we weren't
> saving and restoring TPIDR2_EL0.
>
> Cc: qemu-stable@nongnu.org
> Fixes: 78011586b90d1 ("target/arm: Enable SME for user-only")
Is it worth the efforts to apply this one to qemu 7.2.x branch?
If yes, I'd love to have it back-ported to that one :)
Thanks,
/mjt
On Mon, 28 Jul 2025 at 17:10, Michael Tokarev <mjt@tls.msk.ru> wrote:
>
> On 25.07.2025 20:55, Peter Maydell wrote:
> > A recent change to the kernel (Linux commit b376108e1f88
> > "arm64/fpsimd: signal: Clear TPIDR2 when delivering signals") updated
> > the signal-handler entry code to always clear TPIDR2_EL0.
> >
> > This is necessary for the userspace ZA lazy saving scheme to work
> > correctly when unwinding exceptions across a signal boundary.
> > (For the essay-length description of the incorrect behaviour and
> > why this is the correct fix, see the commit message for the
> > kernel commit.)
> >
> > Make QEMU also clear TPIDR2_EL0 on signal entry, applying the
> > equivalent bugfix to our implementation.
> >
> > Note that getting this unwinding to work correctly also requires
> > changes to the userspace code, e.g. as implemented in gcc in
> > https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b5ffc8e75a8
> >
> > This change is technically an ABI change; from the kernel's
> > point of view SME was never enabled (it was hidden behind
> > CONFIG_BROKEN) before the change. From QEMU's point of view
> > our SME-related signal handling was broken anyway as we weren't
> > saving and restoring TPIDR2_EL0.
> >
> > Cc: qemu-stable@nongnu.org
> > Fixes: 78011586b90d1 ("target/arm: Enable SME for user-only")
>
> Is it worth the efforts to apply this one to qemu 7.2.x branch?
Well, it's an easy backport since it's a one-liner, and
it's not a complicated change so it's pretty safe. There's
no point unless you're also backporting patch 2 of this series,
though.
In the 7.2.x version of target_setup_frame() the "clear
SVCR bits" code is a little different, but it's still there;
the change should go after this part:
if (env->svcr) {
env->svcr = 0;
arm_rebuild_hflags(env);
}
(there isn't actually an ordering requirement, so it's
just neater to put it in the same logical place)
-- PMM
On 7/25/25 10:55 AM, Peter Maydell wrote:
> A recent change to the kernel (Linux commit b376108e1f88
> "arm64/fpsimd: signal: Clear TPIDR2 when delivering signals") updated
> the signal-handler entry code to always clear TPIDR2_EL0.
>
> This is necessary for the userspace ZA lazy saving scheme to work
> correctly when unwinding exceptions across a signal boundary.
> (For the essay-length description of the incorrect behaviour and
> why this is the correct fix, see the commit message for the
> kernel commit.)
>
> Make QEMU also clear TPIDR2_EL0 on signal entry, applying the
> equivalent bugfix to our implementation.
>
> Note that getting this unwinding to work correctly also requires
> changes to the userspace code, e.g. as implemented in gcc in
> https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b5ffc8e75a8
>
> This change is technically an ABI change; from the kernel's
> point of view SME was never enabled (it was hidden behind
> CONFIG_BROKEN) before the change. From QEMU's point of view
> our SME-related signal handling was broken anyway as we weren't
> saving and restoring TPIDR2_EL0.
>
> Cc: qemu-stable@nongnu.org
> Fixes: 78011586b90d1 ("target/arm: Enable SME for user-only")
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/aarch64/signal.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
© 2016 - 2025 Red Hat, Inc.