* [PULL 1/4] linux-user: add preadv2/preadv2
2026-06-12 15:50 [PULL 0/4] Linux user patches Helge Deller
@ 2026-06-12 15:50 ` Helge Deller
2026-06-12 15:50 ` [PULL 2/4] linux-user: Implement /proc/cpuinfo for ppc cpus Helge Deller
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-12 15:50 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: Helge Deller, Pierrick Bouvier, Laurent Vivier, Max Filippov,
Dominique Martinet
From: Dominique Martinet <dominique.martinet@atmark-techno.com>
Some programs apparently use these, like the python test suite.
The flags argument (rwf_t) is an int, with values shared on all arches
and does not need translating.
This was tested manually with the following python script:
```
import os
fd = os.open('test', os.O_RDWR|os.O_CREAT)
os.pwritev(fd, [b'test', b'ok'], 0, os.RWF_HIPRI)
buf = [bytearray(3), bytearray(10)]
os.preadv(fd, buf, 0, os.RWF_HIPRI)
print(buf[0])
print(buf[1])
```
Signed-off-by: Dominique Martinet <dominique.martinet@atmark-techno.com>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/syscall.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 37ede95510..fbe357b7e0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -741,6 +741,11 @@ safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
unsigned long, pos_l, unsigned long, pos_h)
safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
unsigned long, pos_l, unsigned long, pos_h)
+safe_syscall6(ssize_t, preadv2, int, fd, const struct iovec *, iov, int, iovcnt,
+ unsigned long, pos_l, unsigned long, pos_h, __kernel_rwf_t, flags)
+safe_syscall6(ssize_t, pwritev2, int, fd, const struct iovec *, iov,
+ int, iovcnt, unsigned long, pos_l, unsigned long, pos_h,
+ __kernel_rwf_t, flags)
safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
socklen_t, addrlen)
safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
@@ -11907,6 +11912,39 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
}
}
return ret;
+#endif
+#if defined(TARGET_NR_preadv2)
+ case TARGET_NR_preadv2:
+ {
+ struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
+ if (vec != NULL) {
+ unsigned long low, high;
+
+ target_to_host_low_high(arg4, arg5, &low, &high);
+ ret = get_errno(safe_preadv2(arg1, vec, arg3, low, high, arg6));
+ unlock_iovec(vec, arg2, arg3, 1);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
+ }
+ return ret;
+#endif
+#if defined(TARGET_NR_pwritev2)
+ case TARGET_NR_pwritev2:
+ {
+ struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
+ if (vec != NULL) {
+ unsigned long low, high;
+
+ target_to_host_low_high(arg4, arg5, &low, &high);
+ ret = get_errno(safe_pwritev2(arg1, vec, arg3, low, high,
+ arg6));
+ unlock_iovec(vec, arg2, arg3, 0);
+ } else {
+ ret = -host_to_target_errno(errno);
+ }
+ }
+ return ret;
#endif
case TARGET_NR_getsid:
return get_errno(getsid(arg1));
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PULL 2/4] linux-user: Implement /proc/cpuinfo for ppc cpus
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 ` 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 ` [PULL 4/4] linux-user/xtensa: save/restore FP registers across signal delivery Helge Deller
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-12 15:50 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: Helge Deller, Pierrick Bouvier, Laurent Vivier, Max Filippov,
Richard Henderson
From: Helge Deller <deller@gmx.de>
Mimic the entries for /proc/cpuinfo to what can be seen on two debian
porterboxes (ppc64 and ppc64le), which are running via KVM/QEMU.
The "timebase" value in /proc/cpuinfo is used by glibc on power, but only if
the __kernel_get_tbfreq vdso call isn't implemented. So switch
cpu_ppc_load_tbl() for linux-user to get_clock(), as suggested by Richard, and
report timebase = 1GHz in /proc/cpuinfo, which will make the vdso
implementation simple too.
v4: change timebase to 1GHz and use get_clock()
v3: drop another colon, indenting fixes
v2: drop colon, add clock output, refine pvr calculation
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/ppc/cpu_loop.c | 2 +-
linux-user/ppc/target_proc.h | 91 +++++++++++++++++++++++++++++++++++-
2 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 1f9ee20bd0..7c53e25a93 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -26,7 +26,7 @@
static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env)
{
- return cpu_get_host_ticks();
+ return get_clock();
}
uint64_t cpu_ppc_load_tbl(CPUPPCState *env)
diff --git a/linux-user/ppc/target_proc.h b/linux-user/ppc/target_proc.h
index 43fe29ca72..0a48fd65e9 100644
--- a/linux-user/ppc/target_proc.h
+++ b/linux-user/ppc/target_proc.h
@@ -1 +1,90 @@
-/* No target-specific /proc support */
+/*
+ * ppc specific proc functions for linux-user
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef PPC_TARGET_PROC_H
+#define PPC_TARGET_PROC_H
+
+#include <time.h>
+
+#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
+#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
+#define PVR_MAJ(pvr) (((pvr) >> 4) & 0xF) /* Major revision field */
+#define PVR_MIN(pvr) (((pvr) >> 0) & 0xF) /* Minor revision field */
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+ struct timespec res;
+ double freq_mhz;
+ int i, num_cpus;
+ unsigned int maj, min, pvr;
+
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(env_cpu(cpu_env));
+ DeviceClass *dc = DEVICE_CLASS(ppc_cpu_get_family_class(pcc));
+
+ pvr = pcc->pvr;
+
+ /* Taken from Linux kernel: */
+ /* If we are a Freescale core do a simple check so
+ * we don't have to keep adding cases in the future */
+ if (PVR_VER(pvr) & 0x8000) {
+ switch (PVR_VER(pvr)) {
+ case 0x8000: /* 7441/7450/7451, Voyager */
+ case 0x8001: /* 7445/7455, Apollo 6 */
+ case 0x8002: /* 7447/7457, Apollo 7 */
+ case 0x8003: /* 7447A, Apollo 7 PM */
+ case 0x8004: /* 7448, Apollo 8 */
+ case 0x800c: /* 7410, Nitro */
+ maj = ((pvr >> 8) & 0xF);
+ min = PVR_MIN(pvr);
+ break;
+ default: /* e500/book-e */
+ maj = PVR_MAJ(pvr);
+ min = PVR_MIN(pvr);
+ break;
+ }
+ } else {
+ switch (PVR_VER(pvr)) {
+ case 0x1008: /* 740P/750P ?? */
+ maj = ((pvr >> 8) & 0xFF) - 1;
+ min = pvr & 0xFF;
+ break;
+ case 0x004e: /* POWER9 bits 12-15 give chip type */
+ case 0x0080: /* POWER10 bit 12 gives SMT8/4 */
+ maj = (pvr >> 8) & 0x0F;
+ min = pvr & 0xFF;
+ break;
+ default:
+ maj = (pvr >> 8) & 0xFF;
+ min = pvr & 0xFF;
+ break;
+ }
+ }
+
+ if (clock_getres(CLOCK_REALTIME, &res) == -1) {
+ res.tv_nsec = 1;
+ }
+ freq_mhz = 1000.0 / res.tv_nsec;
+
+ num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ for (i = 0; i < num_cpus; i++) {
+ dprintf(fd, "processor\t: %d\n", i);
+ dprintf(fd, "cpu\t\t: %s%s\n",
+ dc->desc,
+ pcc->insns_flags & PPC_ALTIVEC ? ", altivec supported":"");
+ dprintf(fd, "clock\t\t: %.3fMHz\n", freq_mhz);
+ dprintf(fd, "revision\t: %d.%d (pvr %04x %04x)\n\n",
+ maj, min, PVR_VER(pvr), PVR_REV(pvr));
+ }
+
+ dprintf(fd, "timebase\t: 1000000000\n");
+ dprintf(fd, "platform\t: pSeries\n");
+ dprintf(fd, "model\t\t: IBM pSeries (QEMU user v" QEMU_VERSION ")\n");
+ dprintf(fd, "machine\t\t: CHRP IBM pSeries\n");
+
+ return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
+#endif /* PPC_TARGET_PROC_H */
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PULL 3/4] target/xtensa: add cpu_set_fcr/fsr helpers to sync fp_status
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 ` Helge Deller
2026-06-12 15:50 ` [PULL 4/4] linux-user/xtensa: save/restore FP registers across signal delivery Helge Deller
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-12 15:50 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: Helge Deller, Pierrick Bouvier, Laurent Vivier, Max Filippov,
Matt Turner, Richard Henderson
From: Matt Turner <mattst88@gmail.com>
Factor FCR→fp_status and FSR→fp_status synchronisation out of the
wur_fpu{2k,}_fcr/wur_fpu_fsr helpers into cpu_set_fcr(), cpu_set_fsr(),
and cpu_get_fsr(). Signal delivery code needs to restore the FP rounding
mode and exception flags without duplicating the flag-mapping tables.
cpu_set_fcr() applies the union mask 0xfffff07f (superset of the
wur_fpu_fcr mask 0x0000007f and the wur_fpu2k_fcr mask 0xfffff07f) so
that FCR bits valid only on fpu2k configs are preserved while MBZ bits
7-11 are always cleared.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
target/xtensa/cpu.h | 4 +++
target/xtensa/fpu_helper.c | 71 +++++++++++++++++++++-----------------
2 files changed, 44 insertions(+), 31 deletions(-)
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 75cfeee6e3..442e98bd1b 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -642,6 +642,10 @@ static inline void xtensa_select_static_vectors(CPUXtensaState *env,
}
void xtensa_runstall(CPUXtensaState *env, bool runstall);
+uint32_t cpu_get_fsr(CPUXtensaState *env);
+void cpu_set_fcr(CPUXtensaState *env, uint32_t v);
+void cpu_set_fsr(CPUXtensaState *env, uint32_t v);
+
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
#define XTENSA_OPTION_ALL (~(uint64_t)0)
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
index 5358060c50..2e51cabe3f 100644
--- a/target/xtensa/fpu_helper.c
+++ b/target/xtensa/fpu_helper.c
@@ -64,46 +64,39 @@ void xtensa_use_first_nan(CPUXtensaState *env, bool use_first)
&env->fp_status);
}
-void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
+uint32_t cpu_get_fsr(CPUXtensaState *env)
{
- static const int rounding_mode[] = {
- float_round_nearest_even,
- float_round_to_zero,
- float_round_up,
- float_round_down,
- };
+ uint32_t flags = 0;
+ int fef = get_float_exception_flags(&env->fp_status);
+ unsigned i;
- env->uregs[FCR] = v & 0xfffff07f;
- set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
+ for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
+ if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
+ flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
+ }
+ }
+ return flags << XTENSA_FSR_FLAGS_SHIFT;
}
-void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
+void cpu_set_fcr(CPUXtensaState *env, uint32_t v)
{
- static const int rounding_mode[] = {
+ static const FloatRoundMode rounding_mode[] = {
float_round_nearest_even,
float_round_to_zero,
float_round_up,
float_round_down,
};
- if (v & 0xfffff000) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "MBZ field of FCR is written non-zero: %08x\n", v);
- }
- env->uregs[FCR] = v & 0x0000007f;
+ env->uregs[FCR] = v & 0xfffff07f;
set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
}
-void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
+void cpu_set_fsr(CPUXtensaState *env, uint32_t v)
{
uint32_t flags = v >> XTENSA_FSR_FLAGS_SHIFT;
int fef = 0;
unsigned i;
- if (v & 0xfffff000) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "MBZ field of FSR is written non-zero: %08x\n", v);
- }
env->uregs[FSR] = v & 0x00000f80;
for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
if (flags & xtensa_fp_flag_map[i].xtensa_fp_flag) {
@@ -113,19 +106,35 @@ void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
set_float_exception_flags(fef, &env->fp_status);
}
-uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
+void HELPER(wur_fpu2k_fcr)(CPUXtensaState *env, uint32_t v)
{
- uint32_t flags = 0;
- int fef = get_float_exception_flags(&env->fp_status);
- unsigned i;
+ cpu_set_fcr(env, v);
+}
- for (i = 0; i < ARRAY_SIZE(xtensa_fp_flag_map); ++i) {
- if (fef & xtensa_fp_flag_map[i].softfloat_fp_flag) {
- flags |= xtensa_fp_flag_map[i].xtensa_fp_flag;
- }
+void HELPER(wur_fpu_fcr)(CPUXtensaState *env, uint32_t v)
+{
+ if (v & 0xfffff000) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "MBZ field of FCR is written non-zero: %08x\n", v);
}
- env->uregs[FSR] = flags << XTENSA_FSR_FLAGS_SHIFT;
- return flags << XTENSA_FSR_FLAGS_SHIFT;
+ cpu_set_fcr(env, v & 0x0000007f);
+}
+
+void HELPER(wur_fpu_fsr)(CPUXtensaState *env, uint32_t v)
+{
+ if (v & 0xfffff000) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "MBZ field of FSR is written non-zero: %08x\n", v);
+ }
+ cpu_set_fsr(env, v);
+}
+
+uint32_t HELPER(rur_fpu_fsr)(CPUXtensaState *env)
+{
+ uint32_t fsr = cpu_get_fsr(env);
+
+ env->uregs[FSR] = fsr;
+ return fsr;
}
float64 HELPER(abs_d)(float64 v)
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PULL 4/4] linux-user/xtensa: save/restore FP registers across signal delivery
2026-06-12 15:50 [PULL 0/4] Linux user patches Helge Deller
` (2 preceding siblings ...)
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
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-12 15:50 UTC (permalink / raw)
To: Stefan Hajnoczi, qemu-devel
Cc: Helge Deller, Pierrick Bouvier, Laurent Vivier, Max Filippov,
Matt Turner, Richard Henderson
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
^ permalink raw reply related [flat|nested] 5+ messages in thread