On 5/26/26 17:10, Helge Deller wrote:
On 5/26/26 17:05, Matt Turner wrote:
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: [email protected]
Signed-off-by: Matt Turner <[email protected]>
---
  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 ./linux-user/s390x/signal.c ./linux-user/s390x/signal.c
index 96d1c8d11c..28ad80bde4 100644
--- ./linux-user/s390x/signal.c
+++ ./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;

to avoid putting this block into braces, can't fpc be moved some lines above,
where the other variables are declared?

Forget this. ^^^
I see it's used like this in various places across architectures, so
let's keep it like you have in this patch here.

Helge

Reply via email to