Commit 14a27b0fd8 for qemu.org

commit 14a27b0fd8c0b1a901348b0a6d374e82c63cff24
Author: Matt Turner <mattst88@gmail.com>
Date:   Wed Jun 3 12:18:50 2026 -0400

    linux-user/sparc: restore L/I registers from RSA in sparc64_set_context

    The kernel's do_rt_sigreturn loads L and I registers from the register
    save area (RSA) at the restored O6+STACK_BIAS.  QEMU lacks the kernel's
    window-fill path, so restore L0-L7 and I0-I5 explicitly from the RSA.
    I6 and I7 are already restored from mc_fp/mc_i7.

    Signed-off-by: Matt Turner <mattst88@gmail.com>
    Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
    Signed-off-by: Helge Deller <deller@gmx.de>

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index d339f89928..fda5508c48 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -656,6 +656,24 @@ void sparc64_set_context(CPUSPARCState *env)
     __get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp));
     __get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7));

+    /*
+     * The kernel's do_rt_sigreturn loads L and I registers from the
+     * register save area (RSA) at the new O6+STACK_BIAS.  Unlike the
+     * kernel, QEMU has no kernel-mode path that triggers a window fill,
+     * so we must do it explicitly here.  I6 and I7 are already restored
+     * from mc_fp and mc_i7 above; restore L0-L7 and I0-I5 from the RSA.
+     */
+    {
+        abi_ulong sp_ptr = env->regwptr[WREG_O6];
+        /* LP64 O6 is biased (8-byte-aligned - 2047); low bit set. ILP32 O6 is 4-byte-aligned. */
+        if (sp_ptr & 3)
+            sp_ptr += TARGET_STACK_BIAS;
+        for (i = 0; i < 8; i++)
+            get_user_ual(env->regwptr[WREG_L0 + i], sp_ptr + i * 8);
+        for (i = 0; i < 6; i++)  /* I0-I5; I6=FP and I7 already restored */
+            get_user_ual(env->regwptr[WREG_I0 + i], sp_ptr + 64 + i * 8);
+    }
+
     fpup = &ucp->tuc_mcontext.mc_fpregs;

     __get_user(fenab, &(fpup->mcfpu_enab));