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