From: Helge Deller <deller@kernel.org>
To: Stefan Hajnoczi <stefanha@gmail.com>, qemu-devel@nongnu.org
Cc: Helge Deller <deller@gmx.de>,
Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>,
Laurent Vivier <laurent@vivier.eu>,
Max Filippov <jcmvbkbc@gmail.com>,
Matt Turner <mattst88@gmail.com>,
Richard Henderson <richard.henderson@linaro.org>
Subject: [PULL 4/4] linux-user/xtensa: save/restore FP registers across signal delivery
Date: Fri, 12 Jun 2026 17:50:43 +0200 [thread overview]
Message-ID: <20260612155043.3552-5-deller@kernel.org> (raw)
In-Reply-To: <20260612155043.3552-1-deller@kernel.org>
From: Matt Turner <mattst88@gmail.com>
Add support for saving and restoring f0-f15 across signal delivery.
The target_xtensa_xtregs_fp struct carries 32-bit f-regs for cores
with XTENSA_OPTION_FP_COPROCESSOR; target_xtensa_xtregs_dfp carries
64-bit f-regs for cores with XTENSA_OPTION_DFP_COPROCESSOR.
Lock the xtregs region via lock_user before reading on sigreturn,
since sc_xtregs is a user-space pointer that may lie outside the
locked sigframe.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/xtensa/signal.c | 96 ++++++++++++++++++++++++++++++++++----
1 file changed, 88 insertions(+), 8 deletions(-)
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index ef8b0c3a27..e3f9da322b 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -21,6 +21,7 @@
#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
+#include "target/xtensa/cpu.h"
struct target_sigcontext {
abi_ulong sc_pc;
@@ -43,10 +44,25 @@ struct target_ucontext {
target_sigset_t tuc_sigmask;
};
+struct target_xtensa_xtregs_fp {
+ uint32_t f[16];
+ uint32_t fcr;
+ uint32_t fsr;
+};
+
+struct target_xtensa_xtregs_dfp {
+ uint64_t f[16];
+ uint32_t fcr;
+ uint32_t fsr;
+};
+
struct target_rt_sigframe {
target_siginfo_t info;
struct target_ucontext uc;
- /* TODO: xtregs */
+ union {
+ struct target_xtensa_xtregs_fp fp;
+ struct target_xtensa_xtregs_dfp dfp;
+ } xtregs;
uint8_t retcode[6];
abi_ulong window[4];
};
@@ -107,6 +123,7 @@ static int flush_window_regs(CPUXtensaState *env)
}
static int setup_sigcontext(struct target_rt_sigframe *frame,
+ abi_ulong frame_addr,
CPUXtensaState *env)
{
struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
@@ -123,8 +140,25 @@ static int setup_sigcontext(struct target_rt_sigframe *frame,
for (i = 0; i < 16; ++i) {
__put_user(env->regs[i], sc->sc_a + i);
}
- __put_user(0, &sc->sc_xtregs);
- /* TODO: xtregs */
+ if (xtensa_option_enabled(env->config, XTENSA_OPTION_DFP_COPROCESSOR)) {
+ for (i = 0; i < 16; ++i) {
+ __put_user(env->fregs[i].f64, &frame->xtregs.dfp.f[i]);
+ }
+ __put_user(env->uregs[FCR], &frame->xtregs.dfp.fcr);
+ __put_user(cpu_get_fsr(env), &frame->xtregs.dfp.fsr);
+ __put_user(frame_addr + offsetof(struct target_rt_sigframe, xtregs),
+ &sc->sc_xtregs);
+ } else if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) {
+ for (i = 0; i < 16; ++i) {
+ __put_user(env->fregs[i].f32[FP_F32_LOW], &frame->xtregs.fp.f[i]);
+ }
+ __put_user(env->uregs[FCR], &frame->xtregs.fp.fcr);
+ __put_user(cpu_get_fsr(env), &frame->xtregs.fp.fsr);
+ __put_user(frame_addr + offsetof(struct target_rt_sigframe, xtregs),
+ &sc->sc_xtregs);
+ } else {
+ __put_user(0, &sc->sc_xtregs);
+ }
return 1;
}
@@ -190,7 +224,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(0, &frame->uc.tuc_flags);
__put_user(0, &frame->uc.tuc_link);
target_save_altstack(&frame->uc.tuc_stack, env);
- if (!setup_sigcontext(frame, env)) {
+ if (!setup_sigcontext(frame, frame_addr, env)) {
unlock_user_struct(frame, frame_addr, 0);
goto give_sigsegv;
}
@@ -243,8 +277,8 @@ give_sigsegv:
force_sigsegv(sig);
}
-static void restore_sigcontext(CPUXtensaState *env,
- struct target_rt_sigframe *frame)
+static int restore_sigcontext(CPUXtensaState *env,
+ struct target_rt_sigframe *frame)
{
struct target_sigcontext *sc = &frame->uc.tuc_mcontext;
uint32_t ps;
@@ -266,7 +300,51 @@ static void restore_sigcontext(CPUXtensaState *env,
for (i = 0; i < 16; ++i) {
__get_user(env->regs[i], sc->sc_a + i);
}
- /* TODO: xtregs */
+ {
+ abi_ulong xtregs_addr;
+
+ __get_user(xtregs_addr, &sc->sc_xtregs);
+ if (xtregs_addr) {
+ if (xtensa_option_enabled(env->config,
+ XTENSA_OPTION_DFP_COPROCESSOR)) {
+ struct target_xtensa_xtregs_dfp *xtregs;
+ uint32_t fcr, fsr;
+
+ xtregs = lock_user(VERIFY_READ, xtregs_addr,
+ sizeof(*xtregs), 1);
+ if (!xtregs) {
+ return 0;
+ }
+ for (i = 0; i < 16; ++i) {
+ __get_user(env->fregs[i].f64, &xtregs->f[i]);
+ }
+ __get_user(fcr, &xtregs->fcr);
+ __get_user(fsr, &xtregs->fsr);
+ unlock_user(xtregs, xtregs_addr, 0);
+ cpu_set_fcr(env, fcr);
+ cpu_set_fsr(env, fsr);
+ } else if (xtensa_option_enabled(env->config,
+ XTENSA_OPTION_FP_COPROCESSOR)) {
+ struct target_xtensa_xtregs_fp *xtregs;
+ uint32_t fcr, fsr;
+
+ xtregs = lock_user(VERIFY_READ, xtregs_addr,
+ sizeof(*xtregs), 1);
+ if (!xtregs) {
+ return 0;
+ }
+ for (i = 0; i < 16; ++i) {
+ __get_user(env->fregs[i].f32[FP_F32_LOW], &xtregs->f[i]);
+ }
+ __get_user(fcr, &xtregs->fcr);
+ __get_user(fsr, &xtregs->fsr);
+ unlock_user(xtregs, xtregs_addr, 0);
+ cpu_set_fcr(env, fcr);
+ cpu_set_fsr(env, fsr);
+ }
+ }
+ }
+ return 1;
}
long do_rt_sigreturn(CPUXtensaState *env)
@@ -282,7 +360,9 @@ long do_rt_sigreturn(CPUXtensaState *env)
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
set_sigmask(&set);
- restore_sigcontext(env, frame);
+ if (!restore_sigcontext(env, frame)) {
+ goto badframe;
+ }
target_restore_altstack(&frame->uc.tuc_stack, env);
unlock_user_struct(frame, frame_addr, 0);
--
2.54.0
prev parent reply other threads:[~2026-06-12 15:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-12 15:50 [PULL 0/4] Linux user patches Helge Deller
2026-06-12 15:50 ` [PULL 1/4] linux-user: add preadv2/preadv2 Helge Deller
2026-06-12 15:50 ` [PULL 2/4] linux-user: Implement /proc/cpuinfo for ppc cpus Helge Deller
2026-06-12 15:50 ` [PULL 3/4] target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status Helge Deller
2026-06-12 15:50 ` Helge Deller [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260612155043.3552-5-deller@kernel.org \
--to=deller@kernel.org \
--cc=deller@gmx.de \
--cc=jcmvbkbc@gmail.com \
--cc=laurent@vivier.eu \
--cc=mattst88@gmail.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=stefanha@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.