PR/60426 CVS commit: src
"Taylor R Campbell" <[email protected]>
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
The following reply was made to PR kern/60426; it has been noted by GNATS. From: "Taylor R Campbell" <[email protected]> To: [email protected] Cc: Subject: PR/60426 CVS commit: src Date: Fri, 10 Jul 2026 15:11:26 +0000 Module Name: src Committed By: riastradh Date: Fri Jul 10 15:11:25 UTC 2026 Modified Files: src/sys/arch/amd64/amd64: machdep.c netbsd32_machdep.c src/sys/arch/amd64/include: mcontext.h src/sys/arch/i386/i386: machdep.c src/sys/arch/i386/include: mcontext.h src/sys/arch/x86/include: cpu_extended_state.h fpu.h specialreg.h src/sys/arch/x86/x86: fpu.c identcpu.c src/tests/kernel: t_signal_and_fpu.c Log Message: x86: Save and restore all supported extended CPU state on signals. While here, disable Intel AMX, whose state size (>>8 KiB) exceeds MINSIGSTKSZ (8 KiB), until we are ready to safely update the ABI for sigaltstack(2). This isn't a regression: we've never had a release with Intel AMX support. Previously, on signal delivery, we would only save and restore at most what FXSAVE does, which is the x87 and SSE registers that always exist on amd64. To save and restore the upper halves of the YMM or ZMM registers (AVX/AVX2/AVX512), or the AVX512 registers ZMM16..ZMM31, or the enormous AMX state, we need to do more. And we need to do that even if the signal handler doesn't use AVX instructions, because an SSE instruction modifying xmmN (e.g., in a vectorized memcpy) will, as a side effect, zero the high half of ymmN. Fortunately, the x86 architecture has an extensible mechanism for saving and restoring extended CPU state, the XSAVE/XRSTOR instruction family, so we don't need to update this code for every extension -- just handling the generic XSAVE/XRSTOR mechanism will work for a while. When delivering a signal to a thread that has actually made use of these extended registers, we: 1. allocate a separate space on the user's stack for an XSAVE area of whatever size is necessary (as long as it fits in the sigaltstack, if one was provided), and 2. store a pointer to and the length of the separate XSAVE area in an architecturally unused section of the FXSAVE area of the mcontext_t, with the _UC_XSAVE bit set. This way existing applications that have SA_SIGINFO signal handlers and expect to find an FXSAVE area in the mcontext_t with x87 and SSE register content will continue to work, but if the thread has used any state beyond that like AVX registers requiring XSAVE/XRSTOR, on return from signal it can restore everything. Unfortunately, the _size_ that XSAVE needs is variable and might be expanded by architectural extensions, such as Intel AMX. So the minimum stack size to store it all might exceed MINSIGSTKSZ. The current MINSIGSTKSZ is plenty for AVX/AVX2/AVX-512. But before raising MINSIGSTKSZ to support larger XSAVE sizes by adding them to XCR0_FPU, we need to make sure that older binaries built with the old MINSIGSTKSZ continue to work -- of course, they won't be able to use (e.g.) Intel AMX state. To make sure we don't break the ABI accidentally, I've added some __CTASSERTs relating XSAVE_MAX_BYTES, the maximum supported XSAVE area size, and MINSIGSTKSZ, and a panic at boot if the CPU advertises an XSAVE size larger than XSAVE_MAX_BYTES, which would mean either: (a) the CPU's advertised size for various architecturally defined extended CPU state does not match the documentation, or (b) we have inadvertently bitten off more extended state CPU state than we can chew in XCR0_FPU and we have to adjust the ABI and add compatibility for userland programs. Fortunately for getcontext(2), all of the registers in question are caller-saves, so it doesn't need to store any extra state. PR kern/60426: Signal handler corrupts AVX (YMM) registers To generate a diff of this commit: cvs rdiff -u -r1.379 -r1.380 src/sys/arch/amd64/amd64/machdep.c cvs rdiff -u -r1.142 -r1.143 src/sys/arch/amd64/amd64/netbsd32_machdep.c cvs rdiff -u -r1.24 -r1.25 src/sys/arch/amd64/include/mcontext.h cvs rdiff -u -r1.851 -r1.852 src/sys/arch/i386/i386/machdep.c cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/include/mcontext.h cvs rdiff -u -r1.19 -r1.20 src/sys/arch/x86/include/cpu_extended_state.h cvs rdiff -u -r1.23 -r1.24 src/sys/arch/x86/include/fpu.h cvs rdiff -u -r1.221 -r1.222 src/sys/arch/x86/include/specialreg.h cvs rdiff -u -r1.94 -r1.95 src/sys/arch/x86/x86/fpu.c cvs rdiff -u -r1.139 -r1.140 src/sys/arch/x86/x86/identcpu.c cvs rdiff -u -r1.1 -r1.2 src/tests/kernel/t_signal_and_fpu.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.