* [PULL v3 01/10] linux-user/ppc: restore fp_status from FPSCR on sigreturn
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 02/10] linux-user/mips: save/restore FCSR across signal delivery Helge Deller
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
restore_user_regs() restores the PPC FPSCR with a direct assignment:
env->fpscr = (uint32_t) fpscr;
ppc_store_fpscr() exists precisely to write FPSCR and keep the derived
env->fp_status in sync: it calls fpscr_set_rounding_mode() to update
the softfloat rounding mode, and set_float_rebias_overflow/underflow()
to reflect the FP_OE/FP_UE enable bits. The direct assignment bypasses
all of this.
On sigreturn, interrupted code resumes with whatever rounding mode and
overflow/underflow-rebias state the signal handler last installed in
fp_status, rather than the state that was saved at signal delivery.
Replace the direct assign with ppc_store_fpscr(). The FPSCR_MTFS_MASK
applied inside ppc_store_fpscr() only excludes the computed FP_FEX and
FP_VX bits, which it re-derives correctly from the exception and enable
bits in the restored value.
Fixes: bcd4933a23 ("linux-user: ppc signal handling")
Cc: qemu-stable@nongnu.org
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/ppc/signal.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
index a9c10e0987..ab1afea30a 100644
--- a/linux-user/ppc/signal.c
+++ b/linux-user/ppc/signal.c
@@ -420,7 +420,7 @@ static void restore_user_regs(CPUPPCState *env,
__get_user(*fpr, &frame->mc_fregs[i]);
}
__get_user(fpscr, &frame->mc_fregs[32]);
- env->fpscr = (uint32_t) fpscr;
+ ppc_store_fpscr(env, (uint32_t) fpscr);
}
#if !defined(TARGET_PPC64)
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 02/10] linux-user/mips: save/restore FCSR across signal delivery
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
2026-05-29 21:51 ` [PULL v3 01/10] linux-user/ppc: restore fp_status from FPSCR on sigreturn Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 03/10] linux-user/sh4: preserve T/M/Q bits " Helge Deller
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
QEMU keeps the MIPS FPU control/status register (FCSR, fcr31) in
env->active_fpu.fcr31. The rounding mode, flush-to-zero (FS), and
NaN-2008 mode bits in fcr31 are reflected into the derived
env->active_fpu.fp_status via set_float_rounding_mode() and friends;
every architectural write to FCSR goes through helper_ctc1() which
calls restore_fp_status() to keep the two in sync.
Both target_sigcontext variants (O32 and N32/N64) have an sc_fpc_csr
field that holds FCSR, but setup_sigcontext() never wrote it and
restore_sigcontext() never read it. As a result:
- The signal frame always delivered sc_fpc_csr == 0 to the handler,
so sigaction(SA_SIGINFO) handlers that inspect the interrupted
context see the wrong FCSR.
- On sigreturn, active_fpu.fcr31 retained whatever value the signal
handler last installed (if any), and active_fpu.fp_status was
never resynced. Interrupted code resumed with the wrong rounding
mode, FS flag, and NaN-2008 semantics.
Fix setup_sigcontext() to save fcr31 into sc_fpc_csr. Fix
restore_sigcontext() to read it back (masked to fcr31_rw_bitmask as
the kernel does) and call cpu_mips_restore_fp_status() to resync
fp_status from the restored fcr31.
Add cpu_mips_restore_fp_status() in target/mips/fpu.c (which already
defines ieee_rm and includes fpu_helper.h), and declare it in cpu.h.
Fixes: 084d0497a0 ("mips-linux-user: Save and restore fpu and dsp from sigcontext")
Cc: qemu-stable@nongnu.org
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/mips/signal.c | 7 +++++++
target/mips/cpu.h | 3 +++
target/mips/fpu.c | 5 +++++
3 files changed, 15 insertions(+)
diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c
index d69a5d73dd..1b10012726 100644
--- a/linux-user/mips/signal.c
+++ b/linux-user/mips/signal.c
@@ -134,6 +134,7 @@ static inline void setup_sigcontext(CPUMIPSState *regs,
for (i = 0; i < 32; ++i) {
__put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
}
+ __put_user(regs->active_fpu.fcr31, &sc->sc_fpc_csr);
}
static inline void
@@ -165,6 +166,12 @@ restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
for (i = 0; i < 32; ++i) {
__get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]);
}
+ {
+ uint32_t fcr31;
+ __get_user(fcr31, &sc->sc_fpc_csr);
+ regs->active_fpu.fcr31 = fcr31 & regs->active_fpu.fcr31_rw_bitmask;
+ cpu_mips_restore_fp_status(regs);
+ }
}
/*
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 346713705a..392406aff8 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -1384,6 +1384,9 @@ void cpu_mips_clock_init(MIPSCPU *cpu);
/* helper.c */
target_ulong exception_resume_pc(CPUMIPSState *env);
+/* fpu.c */
+void cpu_mips_restore_fp_status(CPUMIPSState *env);
+
/**
* mips_cpu_create_with_clock:
* @typename: a MIPS CPU type.
diff --git a/target/mips/fpu.c b/target/mips/fpu.c
index c7c487c1f9..8b661865ca 100644
--- a/target/mips/fpu.c
+++ b/target/mips/fpu.c
@@ -17,6 +17,11 @@ const FloatRoundMode ieee_rm[4] = {
float_round_down
};
+void cpu_mips_restore_fp_status(CPUMIPSState *env)
+{
+ restore_fp_status(env);
+}
+
const char fregnames[32][4] = {
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 03/10] linux-user/sh4: preserve T/M/Q bits across signal delivery
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
2026-05-29 21:51 ` [PULL v3 01/10] linux-user/ppc: restore fp_status from FPSCR on sigreturn Helge Deller
2026-05-29 21:51 ` [PULL v3 02/10] linux-user/mips: save/restore FCSR across signal delivery Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 04/10] linux-user/sh4: restore FP rounding mode on sigreturn Helge Deller
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
QEMU keeps the SH4 T, M and Q status-register bits outside env->sr, in
the dedicated env->sr_t, env->sr_m and env->sr_q fields; cpu_read_sr()
folds them back into the architectural SR value and cpu_write_sr()
splits them back out.
setup_sigcontext() saved the bare env->sr (so the T/M/Q bits were always
zero in the signal frame) and restore_sigcontext() wrote the value
straight back into env->sr without updating sr_t/sr_m/sr_q. As a result
the T bit was never preserved across signal delivery: on sigreturn the
interrupted code resumed with whatever T value the signal handler last
left behind. Any conditional branch (or addc/subc/rotcl/div1, etc.)
immediately following the interrupted instruction could then take the
wrong path.
This is the cause of the long-standing intermittent failures of the
tests/tcg/multiarch/signals.c test on sh4, which was marked BROKEN. With
a SIGRTMIN timer firing every millisecond across many threads, the race
was hit a few percent of the time and corrupted the guest heap, surfacing
as a SIGSEGV in memset, a malloc assertion, or an rseq registration abort.
Traced on a deterministic rr recording: a cmp/hi set T=0, the timer
signal interrupted the very next instruction (a bf), the handler left
T=1, and the resumed bf took glibc calloc's MORECORE_CLEARS branch,
using the old top-chunk size as the clear length for a freshly split
small chunk and running memset off the end of the heap.
Fix setup_sigcontext()/restore_sigcontext() to use cpu_read_sr() and
cpu_write_sr() so the T, M and Q bits round-trip correctly, and drop the
BROKEN annotation on the sh4 signals test.
Fixes: c3b5bc8ab3 ("SH4: Signal handling for the user space emulator, by Magnus Damm.")
Cc: qemu-stable@nongnu.org
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/sh4/signal.c | 12 ++++++++++--
tests/tcg/sh4/Makefile.target | 7 -------
2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
index d70be24c38..cc36425c49 100644
--- a/linux-user/sh4/signal.c
+++ b/linux-user/sh4/signal.c
@@ -131,8 +131,10 @@ static void setup_sigcontext(struct target_sigcontext *sc,
COPY(gregs[14]); COPY(gregs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
- COPY(sr); COPY(pc);
+ COPY(pc);
#undef COPY
+ /* The T, M and Q bits live outside env->sr; fold them back in. */
+ __put_user(cpu_read_sr(regs), &sc->sc_sr);
for (i=0; i<16; i++) {
__put_user(regs->fregs[i], &sc->sc_fpregs[i]);
@@ -159,8 +161,14 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
COPY(gregs[14]); COPY(gregs[15]);
COPY(gbr); COPY(mach);
COPY(macl); COPY(pr);
- COPY(sr); COPY(pc);
+ COPY(pc);
#undef COPY
+ /* The T, M and Q bits live outside env->sr; unfold them. */
+ {
+ uint32_t sr;
+ __get_user(sr, &sc->sc_sr);
+ cpu_write_sr(regs, sr);
+ }
for (i=0; i<16; i++) {
__get_user(regs->fregs[i], &sc->sc_fpregs[i]);
diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target
index 7852fa62d8..b7a8737be0 100644
--- a/tests/tcg/sh4/Makefile.target
+++ b/tests/tcg/sh4/Makefile.target
@@ -3,13 +3,6 @@
# SuperH specific tweaks
#
-# This triggers failures for sh4-linux about 10% of the time.
-# Random SIGSEGV at unpredictable guest address, cause unknown.
-run-signals: signals
- $(call skip-test, $<, "BROKEN")
-run-plugin-signals-with-%:
- $(call skip-test, $<, "BROKEN")
-
VPATH += $(SRC_PATH)/tests/tcg/sh4
test-macl: CFLAGS += -O -g
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 04/10] linux-user/sh4: restore FP rounding mode on sigreturn
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (2 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 03/10] linux-user/sh4: preserve T/M/Q bits " Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 05/10] target/sh4: sync fp_status when gdb writes FPSCR Helge Deller
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
The SH4 FPSCR rounding-mode (RM) and denormal (DN) bits are not held
only in env->fpscr: they are also reflected into the derived
env->fp_status via set_float_rounding_mode()/set_flush_to_zero(). The
guest keeps the two in sync by routing every write to FPSCR through
helper_ld_fpscr().
restore_sigcontext() wrote the saved value straight into env->fpscr and
never touched env->fp_status, so on sigreturn the interrupted code
resumed with whatever FP rounding mode and flush-to-zero setting the
signal handler last installed. (regs->flags = 0 forces the FR/SZ/PR TB
flags to be recomputed, but fp_status is runtime float state, not a TB
flag, so it was left stale.) This is the FP analogue of the T/M/Q bit
problem just fixed for the integer status register.
Factor the FPSCR -> fp_status synchronisation out of helper_ld_fpscr()
into cpu_load_fpscr() and use it from restore_sigcontext() so the
rounding mode round-trips correctly across signal delivery.
Fixes: c3b5bc8ab3 ("SH4: Signal handling for the user space emulator, by Magnus Damm.")
Cc: qemu-stable@nongnu.org
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/sh4/signal.c | 7 ++++++-
target/sh4/cpu.h | 3 +++
target/sh4/op_helper.c | 7 ++++++-
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
index cc36425c49..00290d6e40 100644
--- a/linux-user/sh4/signal.c
+++ b/linux-user/sh4/signal.c
@@ -173,7 +173,12 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
for (i=0; i<16; i++) {
__get_user(regs->fregs[i], &sc->sc_fpregs[i]);
}
- __get_user(regs->fpscr, &sc->sc_fpscr);
+ /* Resync the derived float_status state, not just env->fpscr. */
+ {
+ uint32_t fpscr;
+ __get_user(fpscr, &sc->sc_fpscr);
+ cpu_load_fpscr(regs, fpscr);
+ }
__get_user(regs->fpul, &sc->sc_fpul);
regs->tra = -1; /* disable syscall checks */
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index 4b0f3f6d97..3302702376 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -379,4 +379,7 @@ static inline void cpu_write_sr(CPUSH4State *env, uint32_t sr)
env->sr = sr & ~((1u << SR_M) | (1u << SR_Q) | (1u << SR_T));
}
+/* Set FPSCR and the derived float_status rounding/flush-to-zero state. */
+void cpu_load_fpscr(CPUSH4State *env, uint32_t val);
+
#endif /* SH4_CPU_H */
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index 669bc84cb6..cf0f80e4a5 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -204,7 +204,7 @@ void helper_macw(CPUSH4State *env, int32_t arg0, int32_t arg1)
}
}
-void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
+void cpu_load_fpscr(CPUSH4State *env, uint32_t val)
{
env->fpscr = val & FPSCR_MASK;
if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
@@ -215,6 +215,11 @@ void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
}
+void helper_ld_fpscr(CPUSH4State *env, uint32_t val)
+{
+ cpu_load_fpscr(env, val);
+}
+
static void update_fpscr(CPUSH4State *env, uintptr_t retaddr)
{
int xcpt, cause, enable;
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 05/10] target/sh4: sync fp_status when gdb writes FPSCR
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (3 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 04/10] linux-user/sh4: restore FP rounding mode on sigreturn Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 06/10] linux-user/s390x: restore fpu_status rounding mode from FPC on sigreturn Helge Deller
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
sh4_cpu_gdb_write_register() wrote the incoming FPSCR value straight
into env->fpscr, leaving the derived env->fp_status (rounding mode and
flush-to-zero) stale, so a gdb-initiated FPSCR change did not take
effect for subsequent FP operations. Use cpu_load_fpscr() instead, the
same way the adjacent case already uses cpu_write_sr() for SR.
Cc: qemu-stable@nongnu.org
Reviewed-by: Yoshinori Sato <yoshinori.sato@nifty.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
target/sh4/gdbstub.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/sh4/gdbstub.c b/target/sh4/gdbstub.c
index 4f36e800d2..bdc8c1d164 100644
--- a/target/sh4/gdbstub.c
+++ b/target/sh4/gdbstub.c
@@ -113,7 +113,7 @@ int superh_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->fpul = ldl_p(mem_buf);
break;
case 24:
- env->fpscr = ldl_p(mem_buf);
+ cpu_load_fpscr(env, ldl_p(mem_buf));
break;
case 25 ... 40:
if (env->fpscr & FPSCR_FR) {
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 06/10] linux-user/s390x: restore fpu_status rounding mode from FPC on sigreturn
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (4 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 05/10] target/sh4: sync fp_status when gdb writes FPSCR Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 07/10] linux-user: Implement finer grained madivse() syscall Helge Deller
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Matt Turner, qemu-stable
From: Matt Turner <mattst88@gmail.com>
QEMU keeps the s390x floating-point control register (FPC) in env->fpc.
The rounding mode bits [2:0] of FPC are reflected into the derived
env->fpu_status via set_float_rounding_mode(); every architectural
write to FPC goes through HELPER(sfpc) which keeps the two in sync.
restore_sigregs() restored FPC with a direct assignment:
__get_user(env->fpc, &sc->fpregs.fpc);
This wrote env->fpc correctly but never updated env->fpu_status, so on
sigreturn the interrupted code resumed with whatever rounding mode the
signal handler last installed in fpu_status.
Factor the two-step "write fpc + sync fpu_status" logic out of
HELPER(sfpc) into cpu_s390x_load_fpc(), declare it in cpu.h, and call
it from restore_sigregs() in place of the direct assignment.
cpu_s390x_load_fpc() partially reuses the sanity check from
HELPER(sfpc): if the FPC value has an invalid rounding mode or reserved
bits set, it falls back to 0, matching the kernel's fpu_lfpc_safe()
behavior where a corrupt signal frame value causes a specification
exception and 0 is used instead.
HELPER(sfpc) now calls cpu_s390x_load_fpc() after its full
specification-exception check, including the FEAT_FLOATING_POINT_EXT
test that is not needed for the signal restore path.
Fixes: 2941e0fa05 ("linux-user/s390x: Save/restore fpc when handling a signal")
Cc: qemu-stable@nongnu.org
Signed-off-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/s390x/signal.c | 6 +++++-
target/s390x/cpu.h | 1 +
target/s390x/tcg/fpu_helper.c | 20 ++++++++++++++------
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index 96d1c8d11c..28ad80bde4 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -332,7 +332,11 @@ static void restore_sigregs(CPUS390XState *env, target_sigregs *sc)
for (i = 0; i < 16; i++) {
__get_user(env->aregs[i], &sc->regs.acrs[i]);
}
- __get_user(env->fpc, &sc->fpregs.fpc);
+ {
+ uint32_t fpc;
+ __get_user(fpc, &sc->fpregs.fpc);
+ cpu_s390x_load_fpc(env, fpc);
+ }
for (i = 0; i < 16; i++) {
__get_user(*get_freg(env, i), &sc->fpregs.fprs[i]);
}
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 3acbe83f0f..f55b79ef8a 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -895,6 +895,7 @@ void s390_init_sigp(void);
/* helper.c */
void s390_cpu_set_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
uint64_t s390_cpu_get_psw_mask(CPUS390XState *env);
+void cpu_s390x_load_fpc(CPUS390XState *env, uint32_t fpc);
/* outside of target/s390x/ */
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
diff --git a/target/s390x/tcg/fpu_helper.c b/target/s390x/tcg/fpu_helper.c
index 6ca0b7162b..107025e675 100644
--- a/target/s390x/tcg/fpu_helper.c
+++ b/target/s390x/tcg/fpu_helper.c
@@ -1087,6 +1087,19 @@ static const int fpc_to_rnd[8] = {
float_round_to_odd,
};
+void cpu_s390x_load_fpc(CPUS390XState *env, uint32_t fpc)
+{
+ /*
+ * Mimic kernel fpu_lfpc_safe(): a corrupt signal frame value that would
+ * trigger a specification exception instead results in FPC being set to 0.
+ */
+ if (fpc_to_rnd[fpc & 0x7] == -1 || fpc & 0x03030088u) {
+ fpc = 0;
+ }
+ env->fpc = fpc;
+ set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
+}
+
/* set fpc */
void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
{
@@ -1094,12 +1107,7 @@ void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
(!s390_has_feat(S390_FEAT_FLOATING_POINT_EXT) && fpc & 0x4)) {
tcg_s390_program_interrupt(env, PGM_SPECIFICATION, GETPC());
}
-
- /* Install everything in the main FPC. */
- env->fpc = fpc;
-
- /* Install the rounding mode in the shadow fpu_status. */
- set_float_rounding_mode(fpc_to_rnd[fpc & 0x7], &env->fpu_status);
+ cpu_s390x_load_fpc(env, fpc);
}
/* set fpc and signal */
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 07/10] linux-user: Implement finer grained madivse() syscall
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (5 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 06/10] linux-user/s390x: restore fpu_status rounding mode from FPC on sigreturn Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 08/10] linux-user: Fix typo in function documentation for pgb_addr_set() Helge Deller
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo
Although most madvise() values are hints, some are important and are
checked by userspace, especially by security-relevant applications like
BoringSLL. So, return -EINVAL for those functions which we don't emulate.
Signed-off-by: Helge Deller <deller@gmx.de>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3489
---
linux-user/mmap.c | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index b4b7b3e5cc..55277f7c3e 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1282,7 +1282,7 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
case TARGET_MADV_KEEPONFORK: /* parisc */
advice = MADV_KEEPONFORK;
break;
- /* we do not care about the other MADV_xxx values yet */
+ /* all other MADV_xxx values are the same across architectures */
}
/*
@@ -1307,6 +1307,19 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
*/
mmap_lock();
switch (advice) {
+ case MADV_NORMAL:
+ case MADV_RANDOM:
+ case MADV_SEQUENTIAL:
+ case MADV_WILLNEED:
+ case MADV_DOFORK:
+ case MADV_FREE:
+ case MADV_COLD:
+ case MADV_PAGEOUT:
+ ret = 0; /* OK */
+ break;
+ case MADV_REMOVE:
+ ret = -EOPNOTSUPP;
+ break;
case MADV_DONTDUMP:
page_set_flags(start, start + len - 1, PAGE_DONTDUMP, 0);
break;
@@ -1324,6 +1337,25 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
page_reset_target_data(start, start + len - 1);
}
}
+ break;
+ case MADV_DONTFORK:
+ case MADV_HWPOISON:
+ case MADV_MERGEABLE:
+ case MADV_UNMERGEABLE:
+ case MADV_HUGEPAGE:
+ case MADV_NOHUGEPAGE:
+ case MADV_POPULATE_READ:
+ case MADV_POPULATE_WRITE:
+#ifdef MADV_COLLAPSE
+ case MADV_COLLAPSE:
+#endif
+ case -1: /* BoringSSL uses -1 to check if the environment is broken */
+ ret = -EINVAL;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unhandled madvise(%d) call.\n", advice);
+ ret = -EINVAL; /* not yet known advise */
+ break;
}
mmap_unlock();
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 08/10] linux-user: Fix typo in function documentation for pgb_addr_set()
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (6 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 07/10] linux-user: Implement finer grained madivse() syscall Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 09/10] linux-user: Move init_main_thread() prototype to user-internals.h Helge Deller
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Peter Maydell, Alex Bennée
The third parameter is called guest_hiaddr.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/elfload.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0e757787d2..f7625c0952 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -848,7 +848,7 @@ static bool pgb_try_mmap_set(const PGBAddrs *ga, uintptr_t base, uintptr_t brk)
* pgb_addr_set:
* @ga: output set of guest addrs
* @guest_loaddr: guest image low address
- * @guest_loaddr: guest image high address
+ * @guest_hiaddr: guest image high address
* @identity: create for identity mapping
*
* Fill in @ga with the image, COMMPAGE and NULL page.
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 09/10] linux-user: Move init_main_thread() prototype to user-internals.h
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (7 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 08/10] linux-user: Fix typo in function documentation for pgb_addr_set() Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-05-29 21:51 ` [PULL v3 10/10] linux-user: Move cpu_copy() " Helge Deller
2026-06-01 14:00 ` [PULL v3 00/10] Linux user next patches Stefan Hajnoczi
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
The init_main_thread() prototype is needed only by code internal to
linux-user/, so it doesn't need to be in qemu.h (which is also pulled
in by various files outside linux-user/).
Move the prototype to user-internals.h, and give it a documentation
comment.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/qemu.h | 2 --
linux-user/user-internals.h | 15 +++++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 7f98fb2607..474489f046 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -371,6 +371,4 @@ void *lock_user_string(abi_ulong guest_addr);
/* Clone cpu state */
CPUArchState *cpu_copy(CPUArchState *env);
-void init_main_thread(CPUState *cs, struct image_info *info);
-
#endif /* QEMU_H */
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index 21daf422b7..fbfd12237f 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -194,6 +194,21 @@ static inline void begin_parallel_context(CPUState *cs)
}
}
+/**
+ * init_main_thread: Set CPU state for main thread
+ * @cs: CPU context to set
+ * @info: information about the image being loaded
+ *
+ * This function must be provided by the per-target code. It should
+ * set the initial CPU state based on the information about the
+ * starting binary in @image_info. This will be at a minimum setting
+ * the initial guest program counter and stack pointer; it should
+ * also set up any other guest register values where the Linux ABI
+ * defines that they start set to some other value than what the
+ * guest CPU architecture gives you out of reset.
+ */
+void init_main_thread(CPUState *cs, struct image_info *info);
+
/*
* Include target-specific struct and function definitions;
* they may need access to the target-independent structures
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PULL v3 10/10] linux-user: Move cpu_copy() to user-internals.h
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (8 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 09/10] linux-user: Move init_main_thread() prototype to user-internals.h Helge Deller
@ 2026-05-29 21:51 ` Helge Deller
2026-06-01 14:00 ` [PULL v3 00/10] Linux user next patches Stefan Hajnoczi
10 siblings, 0 replies; 12+ messages in thread
From: Helge Deller @ 2026-05-29 21:51 UTC (permalink / raw)
To: qemu-devel
Cc: Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier, Richard Henderson,
Cornelia Huck, David Hildenbrand, qemu-s390x, Eric Farman,
Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo, Peter Maydell
From: Peter Maydell <peter.maydell@linaro.org>
We only use cpu_copy() inside linux-user, so we don't need to have
the prototype in qemu.h available to code outside linux-user; move it
to user-internals.h.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/qemu.h | 3 ---
linux-user/user-internals.h | 3 +++
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 474489f046..07fe801628 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -368,7 +368,4 @@ void *lock_user_string(abi_ulong guest_addr);
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
-/* Clone cpu state */
-CPUArchState *cpu_copy(CPUArchState *env);
-
#endif /* QEMU_H */
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
index fbfd12237f..0380d44fe9 100644
--- a/linux-user/user-internals.h
+++ b/linux-user/user-internals.h
@@ -209,6 +209,9 @@ static inline void begin_parallel_context(CPUState *cs)
*/
void init_main_thread(CPUState *cs, struct image_info *info);
+/* Clone cpu state */
+CPUArchState *cpu_copy(CPUArchState *env);
+
/*
* Include target-specific struct and function definitions;
* they may need access to the target-independent structures
--
2.54.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PULL v3 00/10] Linux user next patches
2026-05-29 21:51 [PULL v3 00/10] Linux user next patches Helge Deller
` (9 preceding siblings ...)
2026-05-29 21:51 ` [PULL v3 10/10] linux-user: Move cpu_copy() " Helge Deller
@ 2026-06-01 14:00 ` Stefan Hajnoczi
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Hajnoczi @ 2026-06-01 14:00 UTC (permalink / raw)
To: Helge Deller
Cc: qemu-devel, Jiaxun Yang, Ilya Leoshkevich, Laurent Vivier,
Richard Henderson, Cornelia Huck, David Hildenbrand, qemu-s390x,
Eric Farman, Aurelien Jarno, Matthew Rosato, Helge Deller,
Philippe Mathieu-Daudé, Yoshinori Sato, Pierrick Bouvier,
Aleksandar Rikalo
[-- Attachment #1: Type: text/plain, Size: 116 bytes --]
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread