NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

PR/60539 CVS commit: src/sys/arch/amd64/amd64



The following reply was made to PR kern/60539; it has been noted by GNATS.

From: "Taylor R Campbell" <riastradh%netbsd.org@localhost>
To: gnats-bugs%gnats.NetBSD.org@localhost
Cc: 
Subject: PR/60539 CVS commit: src/sys/arch/amd64/amd64
Date: Sat, 19 Sep 2026 15:18:30 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Sat Sep 19 15:18:30 UTC 2026
 
 Modified Files:
 	src/sys/arch/amd64/amd64: machdep.c
 
 Log Message:
 amd64: Make XSAVE area overlap mcontext_t on signal delivery.
 
 Additionally, if the stack pointer is already such that pushing a
 struct sigframe_siginfo would make it congruent to -8 modulo the
 stack alignment, as the signal handler expects (-8 for the return
 address on an aligned stack frame), don't re-align it again -- it's
 just fine as is.
 
 Previously, for NetBSD 11.0, we would copy out an XSAVE area
 separately from ucontext_t, and copy out the FXSAVE content twice in
 two different places on the stack -- one in the ucontext_t for
 compatibility so older applications can still read x87/SSE registers,
 and one in the XSAVE area:
 
           +-----------------------+ \
           | (other XSAVE stuff)   |  |
           | --------------------- |  |
           | Hi16_ZMM              |  |
           | --------------------- |  |
           | ZMM_Hi256             |  > XSAVE
           | --------------------- |  |
           | YMM_Hi128             |  |
           | --------------------- |  |
           | FXSAVE in XSAVE       |  |
           +-----------------------+ /
           | (opt. padding bytes)  |
           +-----------------------+ \
           | FXSAVE in ucontext_t  |  |
           | --------------------- |  > ucontext_t
           | rest of ucontext_t    |  |
           +-----------------------+ /
           | siginfo_t             |
           +-----------------------+
           | return address        |
           +-----------------------+ <--- rsp on signal handler entry
 
 But the 11.0 layout could, in theory, break older applications with
 signal handlers that _write_ the x87/SSE registers -- even if they
 use VZEROUPPER or VZEROALL as is customary -- if some other part of
 the application (e.g., an optimized AVX512 crypto routine in OpenSSL)
 has _ever_ used the high 16 ZMM registers, which _isn't_ customarily
 followed by VZEROUPPER/VZEROALL.
 
 With this change, we move the XSAVE area so that its FXSAVE part
 overlaps with the ucontext_t, obviating the need to copy out the
 FXSAVE content twice, and restoring compatibility for x87/SSE
 register writeback in signal handlers:
 
         / +-----------------------+
        |  | (other XSAVE stuff)   |
        |  | --------------------- |
        |  | Hi16_ZMM              |
        |  | --------------------- |
  XSAVE <  | ZMM_Hi256             |
        |  | --------------------- |
        |  | YMM_Hi128             |
        |  *-----------------------* \
        |  | FXSAVE in ucontext_t  |  |
         \ *-----------------------*  > ucontext_t
           | rest of ucontext_t    |  |
           +-----------------------+ /
           | siginfo_t             |
           +-----------------------+ =0 (mod 16)
           | return address        |
           +-----------------------+ <--- rsp on signal handler entry
 
 This way:
 
 1. We copy out 512 bytes fewer.
 
 2. There is only one place where the x87/SSE registers are written to
    -- and, more importantly, where they might be read from on return
    from signal.
 
 3. Existing applications that write to the mcontext_t's FXSAVE area
    to change x87/SSE register content in threads that are using
    extended CPU state like the AVX registers will still work.  This
    may happen even if use of AVX registers is always ended by
    VZEROUPPER or VZEROALL, if an AVX-512 subroutine ever uses the
    high 16 ZMM registers -- those are _not_ zeroed by VZEROUPPER or
    VZEROALL, and remain persistently in the XSAVE state.
 
 4. Newly adjusted applications that use 11.0's XSAVE area pointer
    embedded in a padding cabinet in disused lavatory with a sign on
    it saying `BEWARE OF LEOPARD --Intel' in the mcontext_t's FXSAVE
    area will still work.
 
 Unfortunately, we can't do the same for i386, because mcontext_t has
 extra stuff in it after the FXSAVE area:
 
     115 typedef struct {
     116         __gregset_t     __gregs;
     117         __fpregset_t    __fpregs;
     118         __greg_t        _mc_tlsbase;
     119 } mcontext_t;
 
 https://nxr.netbsd.org/xref/src/sys/arch/i386/include/mcontext.h?r=1.20#115
 
 Fortunately, the high 16 ZMM registers do not exist in 32-bit mode!
 In fact there are only eight ZMM registers.  So as long as
 application making use of the high 128-bit halves of the YMM
 registers or the high 256-bit halves of the ZMM registers use
 VZEROUPPER/VZEROALL when they're done -- as is customary in the ABI
 -- any signal handlers that read and write x87/SSE state, in sections
 of code using only x87/SSE state, were not broken in 11.0 with the
 separate copies of FXSAVE content in the split XSAVE and ucontext_t
 areas.
 
 PR kern/60539: XSAVE changes break ucontext userspace API
 
 
 To generate a diff of this commit:
 cvs rdiff -u -r1.380 -r1.381 src/sys/arch/amd64/amd64/machdep.c
 
 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.
 



Home | Main Index | Thread Index | Old Index