Hello,

So it works as your additional test shows, but it is fragile.

Luca Dariz, le mer. 19 mars 2025 18:11:18 +0100, a ecrit:
> diff --git a/sysdeps/mach/hurd/i386/sigreturn.c 
> b/sysdeps/mach/hurd/i386/sigreturn.c
> index ce8df8d02b..618cb74196 100644
> --- a/sysdeps/mach/hurd/i386/sigreturn.c
> +++ b/sysdeps/mach/hurd/i386/sigreturn.c
> @@ -123,10 +125,27 @@ __sigreturn (struct sigcontext *scp)
>    if (scp->sc_onstack)
>      ss->sigaltstack.ss_flags &= ~SS_ONSTACK;
>  
> +#ifdef i386_XFLOAT_STATE
> +  if ((scp->xstate) && (scp->xstate->initialized))
> +    {
> +      unsigned eax, ebx, ecx, edx;
> +      __cpuid_count(0xd, 0, eax, ebx, ecx, edx);
> +      switch (scp->xstate->fp_save_kind)
> +        {
> +        case 0: // FNSAVE
> +          asm volatile("frstor %0" : : "m" (scp->xstate->hw_state));
> +          break;
> +        case 1: // FXSAVE
> +          asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state),    \
> +                       "a" (eax), "d" (edx));
> +          break;
> +        default: // XSAVE
> +          asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state),     \
> +                       "a" (eax), "d" (edx));
> +          break;
> +        }
> +    }
> +  else
> +#endif
>      if (scp->sc_fpused)
>        /* Restore the FPU state.  Mach conveniently stores the state
>           in the format the i387 `frstor' instruction uses to restore it.  */
>        asm volatile ("frstor %0" : : "m" (scp->sc_fpsave));
[...]
>      memcpy (usp -= 12, &scp->sc_i386_thread_state, 12 * sizeof (int));
[...]
>      sigreturn_trampoline (usp);

The original code was restoring FP state relatively early, before
calling memcpy etc. because it assumed that FP would not be used by libc
itself. But memcpy may use it, it's only luck that the call above gets
inlined as mere copying.

And then __sigreturn2 too calls various functions which might use SSE.

Rather than chasing these, it'd be better to make sigreturn2_trampoline
do the restoration. That should be not very hard, by adding just a
few more bits: in struct sigcontext, add an fpstate_size field that
stores the size of the FP state (and default to sizeof sc_fpsave if
xstate is not set), and at the end of __sigreturn copy the FP state
onto additional space on the usp stack, below the i386 thread state, as
well as the content of scp->xstate->fp_save_kind (or 0 if xstate is not
set) and fpstate_size. sigreturn2_trampoline can then easily test that
fp_save_kind value to determine whether it should use frstor, xrstor, or
xrstor to restore the FP state, pop that state, and continue with
restoring general state.

Samuel

Reply via email to