diff options
| author | Yelninei <yelninei@tutamail.com> | 2025-10-17 18:57:58 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2025-11-03 17:18:38 +0100 |
| commit | 7d488fec76c8fc36b2d6d058e172fc37f72f9787 (patch) | |
| tree | cbbae5559300de176feb84bbd358387c90d251b8 /gnu | |
| parent | e639447fc156b65a84a92d476b4d78d24cdd7788 (diff) | |
gnu: glibc/hurd: Add patches from glibc 2.42.
* gnu/packages/base.scm (glibc/hurd): Remove intr-msg-clobber.patch, add
signal-fpe-exception.patch and xstate.patch.
gnu/packages/patches/glibc-hurd-signal-fpe-exception.patch, gnu/packages/patches/glibc-hurd-xstate.patch : New patches
* gnu/local.mk (dist_patch_DATA): Register them.
Change-Id: Ib5b38f1fb8b43d76ec236232be8ff7552dad7422
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'gnu')
| -rw-r--r-- | gnu/local.mk | 2 | ||||
| -rw-r--r-- | gnu/packages/base.scm | 13 | ||||
| -rw-r--r-- | gnu/packages/patches/glibc-hurd-signal-fpe-exception.patch | 67 | ||||
| -rw-r--r-- | gnu/packages/patches/glibc-hurd-xstate.patch | 813 |
4 files changed, 894 insertions, 1 deletions
diff --git a/gnu/local.mk b/gnu/local.mk index ec0efb1a0a9..82a6577562b 100644 --- a/gnu/local.mk +++ b/gnu/local.mk | |||
| @@ -1465,10 +1465,12 @@ dist_patch_DATA = \ | |||
| 1465 | %D%/packages/patches/glibc-hurd-gettyent.patch \ | 1465 | %D%/packages/patches/glibc-hurd-gettyent.patch \ |
| 1466 | %D%/packages/patches/glibc-hurd-mach-print.patch \ | 1466 | %D%/packages/patches/glibc-hurd-mach-print.patch \ |
| 1467 | %D%/packages/patches/glibc-hurd-pthread_setcancelstate.patch \ | 1467 | %D%/packages/patches/glibc-hurd-pthread_setcancelstate.patch \ |
| 1468 | %D%/packages/patches/glibc-hurd-signal-fpe-exception.patch \ | ||
| 1468 | %D%/packages/patches/glibc-hurd-signal-sa-siginfo.patch \ | 1469 | %D%/packages/patches/glibc-hurd-signal-sa-siginfo.patch \ |
| 1469 | %D%/packages/patches/glibc-hurd-2.41-pthread-once.patch \ | 1470 | %D%/packages/patches/glibc-hurd-2.41-pthread-once.patch \ |
| 1470 | %D%/packages/patches/glibc-hurd-2.41-pthread-sigmask.patch \ | 1471 | %D%/packages/patches/glibc-hurd-2.41-pthread-sigmask.patch \ |
| 1471 | %D%/packages/patches/glibc-hurd-2.41-symlink.patch \ | 1472 | %D%/packages/patches/glibc-hurd-2.41-symlink.patch \ |
| 1473 | %D%/packages/patches/glibc-hurd-xstate.patch \ | ||
| 1472 | %D%/packages/patches/glibc-hurd64-gcc-14.2-tls-bug.patch \ | 1474 | %D%/packages/patches/glibc-hurd64-gcc-14.2-tls-bug.patch \ |
| 1473 | %D%/packages/patches/glibc-hurd64-intr-msg-clobber.patch \ | 1475 | %D%/packages/patches/glibc-hurd64-intr-msg-clobber.patch \ |
| 1474 | %D%/packages/patches/glibc-ldd-powerpc.patch \ | 1476 | %D%/packages/patches/glibc-ldd-powerpc.patch \ |
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm index 26096743192..79810bccd10 100644 --- a/gnu/packages/base.scm +++ b/gnu/packages/base.scm | |||
| @@ -1548,7 +1548,18 @@ variety of options. It is an alternative to the shell \"type\" built-in | |||
| 1548 | command.") | 1548 | command.") |
| 1549 | (license gpl3+))) ; some files are under GPLv2+ | 1549 | (license gpl3+))) ; some files are under GPLv2+ |
| 1550 | 1550 | ||
| 1551 | (define-public glibc/hurd glibc) | 1551 | (define-public glibc/hurd |
| 1552 | (hidden-package | ||
| 1553 | (package/inherit glibc | ||
| 1554 | (source | ||
| 1555 | (origin | ||
| 1556 | (inherit (package-source glibc)) | ||
| 1557 | (patches | ||
| 1558 | (append (map search-patch | ||
| 1559 | (delete "glibc-hurd64-intr-msg-clobber.patch" %glibc-patches)) | ||
| 1560 | (search-patches | ||
| 1561 | "glibc-hurd-signal-fpe-exception.patch" | ||
| 1562 | "glibc-hurd-xstate.patch")))))))) | ||
| 1552 | 1563 | ||
| 1553 | (define-public glibc/hurd-headers | 1564 | (define-public glibc/hurd-headers |
| 1554 | (package/inherit glibc/hurd | 1565 | (package/inherit glibc/hurd |
diff --git a/gnu/packages/patches/glibc-hurd-signal-fpe-exception.patch b/gnu/packages/patches/glibc-hurd-signal-fpe-exception.patch new file mode 100644 index 00000000000..fefd9f693c0 --- /dev/null +++ b/gnu/packages/patches/glibc-hurd-signal-fpe-exception.patch | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | Cherry picked from glibc-2.42 | ||
| 2 | |||
| 3 | 0d99714680 * hurd: Clear FP exceptions before calling signal handler | ||
| 4 | |||
| 5 | From 0d9971468087c77e8727638123ae4aa60724e0ff Mon Sep 17 00:00:00 2001 | ||
| 6 | From: Samuel Thibault <samuel.thibault@ens-lyon.org> | ||
| 7 | Date: Mon, 21 Apr 2025 19:58:04 +0200 | ||
| 8 | Subject: [PATCH] hurd: Clear FP exceptions before calling signal handler | ||
| 9 | |||
| 10 | This avoids SIGFPE handlers (or code longjmp-ed to) getting disturbed by the | ||
| 11 | exception that generated it. | ||
| 12 | |||
| 13 | Note: gcc's unwinding depends on the rpc_wait_trampoline/trampoline exact | ||
| 14 | code, so we here avoid breaking it. | ||
| 15 | --- | ||
| 16 | sysdeps/mach/hurd/x86/trampoline.c | 14 ++++++++++---- | ||
| 17 | 1 file changed, 10 insertions(+), 4 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/sysdeps/mach/hurd/x86/trampoline.c b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 20 | index 02510b178c..6f23c567da 100644 | ||
| 21 | --- a/sysdeps/mach/hurd/x86/trampoline.c | ||
| 22 | +++ b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 23 | @@ -461,7 +461,10 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 24 | - in gdb: gdb/i386-gnu-tdep.c gnu_sigtramp_code. */ | ||
| 25 | |||
| 26 | #ifdef __x86_64__ | ||
| 27 | -asm ("rpc_wait_trampoline:\n" | ||
| 28 | +asm ("trampoline:\n" | ||
| 29 | + "fnclex\n" /* Clear any pending exception. */ | ||
| 30 | + "jmp _trampoline\n" | ||
| 31 | + "rpc_wait_trampoline:\n" | ||
| 32 | /* This is the entry point when we have an RPC reply message to receive | ||
| 33 | before running the handler. The MACH_MSG_SEND bit has already been | ||
| 34 | cleared in the OPTION argument in our %rsi. The interrupted user | ||
| 35 | @@ -480,7 +483,7 @@ asm ("rpc_wait_trampoline:\n" | ||
| 36 | /* Switch to the signal stack. */ | ||
| 37 | "movq %rbx, %rsp\n" | ||
| 38 | |||
| 39 | - "trampoline:\n" | ||
| 40 | + "_trampoline:\n" | ||
| 41 | /* Entry point for running the handler normally. The arguments to the | ||
| 42 | handler function are on the top of the stack, same as in the i386 | ||
| 43 | version: | ||
| 44 | @@ -506,7 +509,10 @@ asm ("rpc_wait_trampoline:\n" | ||
| 45 | "movq 16(%rsp), %rdi\n" | ||
| 46 | "ret"); | ||
| 47 | #else | ||
| 48 | -asm ("rpc_wait_trampoline:\n"); | ||
| 49 | +asm ("trampoline:\n" | ||
| 50 | + "fnclex\n" /* Clear any pending exception. */ | ||
| 51 | + "jmp _trampoline\n" | ||
| 52 | + "rpc_wait_trampoline:\n"); | ||
| 53 | /* This is the entry point when we have an RPC reply message to receive | ||
| 54 | before running the handler. The MACH_MSG_SEND bit has already been | ||
| 55 | cleared in the OPTION argument on our stack. The interrupted user | ||
| 56 | @@ -526,7 +532,7 @@ asm (/* Retry the interrupted mach_msg system call. */ | ||
| 57 | /* Switch to the signal stack. */ | ||
| 58 | "movl %ebx, %esp\n"); | ||
| 59 | |||
| 60 | - asm ("trampoline:\n"); | ||
| 61 | +asm ("_trampoline:\n"); | ||
| 62 | /* Entry point for running the handler normally. The arguments to the | ||
| 63 | handler function are already on the top of the stack: | ||
| 64 | |||
| 65 | -- | ||
| 66 | 2.51.0 | ||
| 67 | |||
diff --git a/gnu/packages/patches/glibc-hurd-xstate.patch b/gnu/packages/patches/glibc-hurd-xstate.patch new file mode 100644 index 00000000000..f46a84adb21 --- /dev/null +++ b/gnu/packages/patches/glibc-hurd-xstate.patch | |||
| @@ -0,0 +1,813 @@ | |||
| 1 | Cherry picked from glibc 2.42 | ||
| 2 | |||
| 3 | 6d6a6e2dd2 * hurd: save xstate during signal handling | ||
| 4 | 8d54b428cf * hurd: Do not restore xstate when it is not initialized | ||
| 5 | 0f2df19d95 * hurd: Do not check for xstate level if it was not initialized | ||
| 6 | |||
| 7 | From 6d6a6e2dd2133908e3f5cb8a2ed817ccb2a0bb06 Mon Sep 17 00:00:00 2001 | ||
| 8 | From: Luca Dariz <luca@orpolo.org> | ||
| 9 | Date: Wed, 19 Mar 2025 18:11:18 +0100 | ||
| 10 | Subject: [PATCH] hurd: save xstate during signal handling | ||
| 11 | |||
| 12 | * hurd/Makefile: add new tests | ||
| 13 | * hurd/test-sig-rpc-interrupted.c: check xstate save and restore in | ||
| 14 | the case where a signal is delivered to a thread which is waiting | ||
| 15 | for an rpc. This test implements the rpc interruption protocol used | ||
| 16 | by the hurd servers. It was so far passing on Debian thanks to the | ||
| 17 | local-intr-msg-clobber.diff patch, which is now obsolete. | ||
| 18 | * hurd/test-sig-xstate.c: check xstate save and restore in the case | ||
| 19 | where a signal is delivered to a running thread, making sure that | ||
| 20 | the xstate is modified in the signal handler. | ||
| 21 | * hurd/test-xstate.h: add helpers to test xstate | ||
| 22 | * sysdeps/mach/hurd/i386/bits/sigcontext.h: add xstate to the | ||
| 23 | sigcontext structure. | ||
| 24 | + sysdeps/mach/hurd/i386/sigreturn.c: restore xstate from the saved | ||
| 25 | context | ||
| 26 | * sysdeps/mach/hurd/x86/trampoline.c: save xstate if | ||
| 27 | supported. Otherwise we fall back to the previous behaviour of | ||
| 28 | ignoring xstate. | ||
| 29 | * sysdeps/mach/hurd/x86_64/bits/sigcontext.h: add xstate to the | ||
| 30 | sigcontext structure. | ||
| 31 | * sysdeps/mach/hurd/x86_64/sigreturn.c: restore xstate from the saved | ||
| 32 | context | ||
| 33 | |||
| 34 | Signed-off-by: Luca Dariz <luca@orpolo.org> | ||
| 35 | Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> | ||
| 36 | Message-ID: <20250319171118.142163-1-luca@orpolo.org> | ||
| 37 | --- | ||
| 38 | hurd/Makefile | 5 + | ||
| 39 | hurd/test-sig-rpc-interrupted.c | 185 +++++++++++++++++++++ | ||
| 40 | hurd/test-sig-xstate.c | 94 +++++++++++ | ||
| 41 | hurd/test-xstate.h | 40 +++++ | ||
| 42 | sysdeps/mach/hurd/i386/bits/sigcontext.h | 2 + | ||
| 43 | sysdeps/mach/hurd/i386/sigreturn.c | 32 +++- | ||
| 44 | sysdeps/mach/hurd/x86/trampoline.c | 91 ++++++++-- | ||
| 45 | sysdeps/mach/hurd/x86_64/bits/sigcontext.h | 2 + | ||
| 46 | sysdeps/mach/hurd/x86_64/sigreturn.c | 32 +++- | ||
| 47 | 9 files changed, 458 insertions(+), 25 deletions(-) | ||
| 48 | create mode 100644 hurd/test-sig-rpc-interrupted.c | ||
| 49 | create mode 100644 hurd/test-sig-xstate.c | ||
| 50 | create mode 100644 hurd/test-xstate.h | ||
| 51 | |||
| 52 | diff --git a/hurd/Makefile b/hurd/Makefile | ||
| 53 | index cf70b8c65c..cbc3c23b1f 100644 | ||
| 54 | --- a/hurd/Makefile | ||
| 55 | +++ b/hurd/Makefile | ||
| 56 | @@ -19,6 +19,11 @@ subdir := hurd | ||
| 57 | |||
| 58 | include ../Makeconfig | ||
| 59 | |||
| 60 | +tests := test-sig-xstate \ | ||
| 61 | + test-sig-rpc-interrupted | ||
| 62 | +$(objpfx)test-sig-xstate: $(shared-thread-library) | ||
| 63 | +$(objpfx)test-sig-rpc-interrupted: $(shared-thread-library) $(objdir)/hurd/libhurduser.so | ||
| 64 | + | ||
| 65 | headers = \ | ||
| 66 | $(interface-headers) \ | ||
| 67 | hurd.h \ | ||
| 68 | diff --git a/hurd/test-sig-rpc-interrupted.c b/hurd/test-sig-rpc-interrupted.c | ||
| 69 | new file mode 100644 | ||
| 70 | index 0000000000..a89d70e5a4 | ||
| 71 | --- /dev/null | ||
| 72 | +++ b/hurd/test-sig-rpc-interrupted.c | ||
| 73 | @@ -0,0 +1,185 @@ | ||
| 74 | +/* Test the state save/restore procedures during signal handling when an | ||
| 75 | + interruptible RPC is restarted. | ||
| 76 | + | ||
| 77 | + Copyright (C) 2024 Free Software Foundation, Inc. | ||
| 78 | + This file is part of the GNU C Library. | ||
| 79 | + | ||
| 80 | + The GNU C Library is free software; you can redistribute it and/or | ||
| 81 | + modify it under the terms of the GNU Lesser General Public | ||
| 82 | + License as published by the Free Software Foundation; either | ||
| 83 | + version 2.1 of the License, or (at your option) any later version. | ||
| 84 | + | ||
| 85 | + The GNU C Library is distributed in the hope that it will be useful, | ||
| 86 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 87 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 88 | + Lesser General Public License for more details. | ||
| 89 | + | ||
| 90 | + You should have received a copy of the GNU Lesser General Public | ||
| 91 | + License along with the GNU C Library; if not, see | ||
| 92 | + <https://www.gnu.org/licenses/>. */ | ||
| 93 | + | ||
| 94 | + | ||
| 95 | +#include <assert.h> | ||
| 96 | +#include <pthread.h> | ||
| 97 | +#include <signal.h> | ||
| 98 | +#include <stdbool.h> | ||
| 99 | +#include <stdio.h> | ||
| 100 | +#include <stdlib.h> | ||
| 101 | +#include <string.h> | ||
| 102 | +#include <unistd.h> | ||
| 103 | + | ||
| 104 | +#include <mach/message.h> | ||
| 105 | +#include <mach/gnumach.h> | ||
| 106 | +#include <mach/mach_traps.h> | ||
| 107 | +#include <mach/mig_errors.h> | ||
| 108 | +#include <mach-shortcuts.h> | ||
| 109 | +#include <mach_init.h> | ||
| 110 | +#include <hurd/io.h> | ||
| 111 | +#include <hurd/io_reply.h> | ||
| 112 | + | ||
| 113 | +#include <support/check.h> | ||
| 114 | +#include <support/xthread.h> | ||
| 115 | + | ||
| 116 | +#include "test-xstate.h" | ||
| 117 | + | ||
| 118 | +void handler (int signum, siginfo_t *info, void *context) | ||
| 119 | +{ | ||
| 120 | + printf ("signal %d setting a different CPU state\n", signum); | ||
| 121 | + char buf3[XSTATE_BUFFER_SIZE]; | ||
| 122 | + memset (buf3, 0x77, XSTATE_BUFFER_SIZE); | ||
| 123 | + SET_XSTATE (buf3); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +static const mach_msg_type_t RetCodeCheck = { | ||
| 127 | + .msgt_name = (unsigned char) MACH_MSG_TYPE_INTEGER_32, | ||
| 128 | + .msgt_size = 32, | ||
| 129 | + .msgt_number = 1, | ||
| 130 | + .msgt_inline = TRUE, | ||
| 131 | + .msgt_longform = FALSE, | ||
| 132 | + .msgt_deallocate = FALSE, | ||
| 133 | + .msgt_unused = 0 | ||
| 134 | +}; | ||
| 135 | + | ||
| 136 | + | ||
| 137 | +/* Helper thread to simulate a proper RPC interruption during dignal handling */ | ||
| 138 | +void* fake_interruptor (void *arg) | ||
| 139 | +{ | ||
| 140 | + int err; | ||
| 141 | + sigset_t ss; | ||
| 142 | + TEST_COMPARE (sigemptyset (&ss), 0); | ||
| 143 | + TEST_COMPARE (sigaddset (&ss, SIGUSR1), 0); | ||
| 144 | + TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss, NULL), 0); | ||
| 145 | + | ||
| 146 | + struct { | ||
| 147 | + mach_msg_header_t Head; | ||
| 148 | + } request; | ||
| 149 | + mach_port_t rxport = *((mach_port_t*)arg); | ||
| 150 | + err = mach_msg (&request.Head, MACH_RCV_MSG, 0, sizeof (request), rxport, | ||
| 151 | + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | ||
| 152 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 153 | + TEST_COMPARE (request.Head.msgh_bits, 0x1112); | ||
| 154 | + TEST_COMPARE (request.Head.msgh_size, sizeof (request.Head)); | ||
| 155 | + TEST_COMPARE (request.Head.msgh_id, 33000); | ||
| 156 | + | ||
| 157 | + mig_reply_header_t reply; | ||
| 158 | + reply.Head = request.Head; | ||
| 159 | + reply.Head.msgh_id += 100; | ||
| 160 | + reply.RetCodeType = RetCodeCheck; | ||
| 161 | + reply.RetCode = KERN_SUCCESS; | ||
| 162 | + err = mach_msg (&reply.Head, MACH_SEND_MSG, sizeof (reply), 0, MACH_PORT_NULL, | ||
| 163 | + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | ||
| 164 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 165 | + | ||
| 166 | + return NULL; | ||
| 167 | +} | ||
| 168 | + | ||
| 169 | + | ||
| 170 | +/* Helper thread to send a signal to the main thread in the middle of | ||
| 171 | + * an interruptible rpc */ | ||
| 172 | +void* signal_sender (void *arg) | ||
| 173 | +{ | ||
| 174 | + int err; | ||
| 175 | + sigset_t ss; | ||
| 176 | + TEST_COMPARE (sigemptyset (&ss), 0); | ||
| 177 | + TEST_COMPARE (sigaddset (&ss, SIGUSR1), 0); | ||
| 178 | + TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss, NULL), 0); | ||
| 179 | + | ||
| 180 | + /* Receive the first request, we won't answer to this. */ | ||
| 181 | + struct { | ||
| 182 | + mach_msg_header_t head; | ||
| 183 | + char data[64]; | ||
| 184 | + } m1, m2; | ||
| 185 | + mach_port_t rxport = *((mach_port_t*)arg); | ||
| 186 | + memset (&m1, 0, sizeof (m1)); | ||
| 187 | + memset (&m2, 0, sizeof (m2)); | ||
| 188 | + err = mach_msg (&m1.head, MACH_RCV_MSG, 0, sizeof (m1), rxport, | ||
| 189 | + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | ||
| 190 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 191 | + | ||
| 192 | + /* interrupt the ongoing rpc with a signal, using the | ||
| 193 | + * interruptible rpc protocol */ | ||
| 194 | + pthread_t thintr = xpthread_create (NULL, fake_interruptor, arg); | ||
| 195 | + TEST_COMPARE (kill (getpid (), SIGUSR1), 0); | ||
| 196 | + xpthread_join (thintr); | ||
| 197 | + | ||
| 198 | + /* Complete the interruption by sending EINTR */ | ||
| 199 | + mig_reply_header_t reply; | ||
| 200 | + reply.Head = m1.head; | ||
| 201 | + reply.Head.msgh_id += 100; | ||
| 202 | + reply.RetCodeType = RetCodeCheck; | ||
| 203 | + reply.RetCode = EINTR; | ||
| 204 | + err = mach_msg (&reply.Head, MACH_SEND_MSG, sizeof (reply), 0, MACH_PORT_NULL, | ||
| 205 | + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | ||
| 206 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 207 | + | ||
| 208 | + /* Receive the retried rpc, and check that it has the same payload | ||
| 209 | + * as the first one. Port names might still be different. */ | ||
| 210 | + err = mach_msg (&m2.head, MACH_RCV_MSG, 0, sizeof (m2), rxport, | ||
| 211 | + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); | ||
| 212 | + TEST_COMPARE (m1.head.msgh_bits, m2.head.msgh_bits); | ||
| 213 | + TEST_COMPARE (m1.head.msgh_size, m2.head.msgh_size); | ||
| 214 | + TEST_COMPARE (m1.head.msgh_id, m2.head.msgh_id); | ||
| 215 | + TEST_COMPARE_BLOB (m1.data, sizeof (m1.data), m2.data, sizeof (m2.data)); | ||
| 216 | + | ||
| 217 | + /* And finally make the rpc succeed by sending a valid reply */ | ||
| 218 | + err = io_read_reply (m2.head.msgh_remote_port, MACH_MSG_TYPE_MOVE_SEND_ONCE, | ||
| 219 | + KERN_SUCCESS, NULL, 0); | ||
| 220 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 221 | + | ||
| 222 | + return NULL; | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | + | ||
| 226 | +static int do_test (void) | ||
| 227 | +{ | ||
| 228 | +#if ! XSTATE_HELPERS_SUPPORTED | ||
| 229 | + FAIL_UNSUPPORTED ("Test not supported on this arch."); | ||
| 230 | +#endif | ||
| 231 | + | ||
| 232 | + /* Setup signal handling; we need to handle the signal in the main | ||
| 233 | + * thread, the other ones will explicitely block SIGUSR1. */ | ||
| 234 | + struct sigaction act = { 0 }; | ||
| 235 | + act.sa_flags = SA_RESTART; | ||
| 236 | + act.sa_sigaction = &handler; | ||
| 237 | + TEST_COMPARE (sigaction (SIGUSR1, &act, NULL), 0); | ||
| 238 | + | ||
| 239 | + mach_port_t fakeio; | ||
| 240 | + int err; | ||
| 241 | + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &fakeio); | ||
| 242 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 243 | + | ||
| 244 | + err = mach_port_insert_right (mach_task_self (), fakeio, fakeio, | ||
| 245 | + MACH_MSG_TYPE_MAKE_SEND); | ||
| 246 | + TEST_COMPARE (err, MACH_MSG_SUCCESS); | ||
| 247 | + | ||
| 248 | + pthread_t thsender = xpthread_create (NULL, signal_sender, &fakeio); | ||
| 249 | + | ||
| 250 | + char *buf; | ||
| 251 | + mach_msg_type_number_t n; | ||
| 252 | + TEST_COMPARE (io_read (fakeio, &buf, &n, 1, 2), 0); | ||
| 253 | + | ||
| 254 | + xpthread_join (thsender); | ||
| 255 | + return EXIT_SUCCESS; | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +#include <support/test-driver.c> | ||
| 259 | diff --git a/hurd/test-sig-xstate.c b/hurd/test-sig-xstate.c | ||
| 260 | new file mode 100644 | ||
| 261 | index 0000000000..0a68a44fd7 | ||
| 262 | --- /dev/null | ||
| 263 | +++ b/hurd/test-sig-xstate.c | ||
| 264 | @@ -0,0 +1,94 @@ | ||
| 265 | +/* Test the state save/restore procedures during signal handling. | ||
| 266 | + | ||
| 267 | + Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 268 | + This file is part of the GNU C Library. | ||
| 269 | + | ||
| 270 | + The GNU C Library is free software; you can redistribute it and/or | ||
| 271 | + modify it under the terms of the GNU Lesser General Public | ||
| 272 | + License as published by the Free Software Foundation; either | ||
| 273 | + version 2.1 of the License, or (at your option) any later version. | ||
| 274 | + | ||
| 275 | + The GNU C Library is distributed in the hope that it will be useful, | ||
| 276 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 277 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 278 | + Lesser General Public License for more details. | ||
| 279 | + | ||
| 280 | + You should have received a copy of the GNU Lesser General Public | ||
| 281 | + License along with the GNU C Library; if not, see | ||
| 282 | + <https://www.gnu.org/licenses/>. */ | ||
| 283 | + | ||
| 284 | + | ||
| 285 | +#include <assert.h> | ||
| 286 | +#include <pthread.h> | ||
| 287 | +#include <signal.h> | ||
| 288 | +#include <stdbool.h> | ||
| 289 | +#include <stdio.h> | ||
| 290 | +#include <stdlib.h> | ||
| 291 | +#include <string.h> | ||
| 292 | +#include <unistd.h> | ||
| 293 | + | ||
| 294 | +#include <mach/message.h> | ||
| 295 | +#include <mach/gnumach.h> | ||
| 296 | +#include <mach/mach_traps.h> | ||
| 297 | +#include <mach-shortcuts.h> | ||
| 298 | +#include <mach_init.h> | ||
| 299 | +#include <hurd/io.h> | ||
| 300 | +#include <hurd/io_reply.h> | ||
| 301 | + | ||
| 302 | +#include <support/check.h> | ||
| 303 | +#include <support/xthread.h> | ||
| 304 | + | ||
| 305 | +#include "test-xstate.h" | ||
| 306 | + | ||
| 307 | +static volatile bool loopflag = true; | ||
| 308 | + | ||
| 309 | +void handler (int signum, siginfo_t *info, void *context) | ||
| 310 | +{ | ||
| 311 | + char buf3[XSTATE_BUFFER_SIZE]; | ||
| 312 | + memset (buf3, 0x77, XSTATE_BUFFER_SIZE); | ||
| 313 | + SET_XSTATE (buf3); | ||
| 314 | + printf ("signal %d setting a different CPU state\n", signum); | ||
| 315 | + loopflag = false; | ||
| 316 | +} | ||
| 317 | + | ||
| 318 | +/* Helper thread to send a signal to the main thread */ | ||
| 319 | +void* signal_sender (void *arg) | ||
| 320 | +{ | ||
| 321 | + sigset_t ss; | ||
| 322 | + assert (! sigemptyset (&ss)); | ||
| 323 | + assert (! sigaddset (&ss, SIGUSR1)); | ||
| 324 | + assert (! sigprocmask (SIG_BLOCK, &ss, NULL)); | ||
| 325 | + | ||
| 326 | + TEST_COMPARE (kill (getpid (), SIGUSR1), 0); | ||
| 327 | + | ||
| 328 | + return NULL; | ||
| 329 | +} | ||
| 330 | + | ||
| 331 | +static int do_test (void) | ||
| 332 | +{ | ||
| 333 | +#if ! XSTATE_HELPERS_SUPPORTED | ||
| 334 | + FAIL_UNSUPPORTED ("Test not supported on this arch."); | ||
| 335 | +#endif | ||
| 336 | + | ||
| 337 | + struct sigaction act = { 0 }; | ||
| 338 | + act.sa_sigaction = &handler; | ||
| 339 | + TEST_COMPARE (sigaction (SIGUSR1, &act, NULL), 0); | ||
| 340 | + | ||
| 341 | + pthread_t thsender = xpthread_create (NULL, signal_sender, NULL); | ||
| 342 | + | ||
| 343 | + char buf1[XSTATE_BUFFER_SIZE], buf2[XSTATE_BUFFER_SIZE]; | ||
| 344 | + memset (buf1, 0x33, XSTATE_BUFFER_SIZE); | ||
| 345 | + | ||
| 346 | + SET_XSTATE (buf1); | ||
| 347 | + | ||
| 348 | + while (loopflag) | ||
| 349 | + ; | ||
| 350 | + | ||
| 351 | + GET_XSTATE (buf2); | ||
| 352 | + TEST_COMPARE_BLOB (buf1, sizeof (buf1), buf2, sizeof (buf2)); | ||
| 353 | + | ||
| 354 | + xpthread_join (thsender); | ||
| 355 | + return EXIT_SUCCESS; | ||
| 356 | +} | ||
| 357 | + | ||
| 358 | +#include <support/test-driver.c> | ||
| 359 | diff --git a/hurd/test-xstate.h b/hurd/test-xstate.h | ||
| 360 | new file mode 100644 | ||
| 361 | index 0000000000..a8185dcb07 | ||
| 362 | --- /dev/null | ||
| 363 | +++ b/hurd/test-xstate.h | ||
| 364 | @@ -0,0 +1,40 @@ | ||
| 365 | +/* Helpers to test XSTATE during signal handling | ||
| 366 | + | ||
| 367 | + Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 368 | + This file is part of the GNU C Library. | ||
| 369 | + | ||
| 370 | + The GNU C Library is free software; you can redistribute it and/or | ||
| 371 | + modify it under the terms of the GNU Lesser General Public | ||
| 372 | + License as published by the Free Software Foundation; either | ||
| 373 | + version 2.1 of the License, or (at your option) any later version. | ||
| 374 | + | ||
| 375 | + The GNU C Library is distributed in the hope that it will be useful, | ||
| 376 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 377 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 378 | + Lesser General Public License for more details. | ||
| 379 | + | ||
| 380 | + You should have received a copy of the GNU Lesser General Public | ||
| 381 | + License along with the GNU C Library; if not, see | ||
| 382 | + <https://www.gnu.org/licenses/>. */ | ||
| 383 | + | ||
| 384 | +#ifndef _TEST_XSTATE_H | ||
| 385 | +#define _TEST_XSTATE_H | ||
| 386 | + | ||
| 387 | +#if defined __x86_64__ || defined __i386__ | ||
| 388 | +#define XSTATE_HELPERS_SUPPORTED 1 | ||
| 389 | +#define XSTATE_BUFFER_SIZE 16 | ||
| 390 | +#define SET_XSTATE(b) do { \ | ||
| 391 | + asm volatile ("movups (%0),%%xmm0" :: "r" (b)); \ | ||
| 392 | + } while (0) | ||
| 393 | + | ||
| 394 | +#define GET_XSTATE(b) do { \ | ||
| 395 | + asm volatile ("movups %%xmm0,(%0)" :: "r" (b)); \ | ||
| 396 | + } while (0) | ||
| 397 | + | ||
| 398 | +#else | ||
| 399 | +#define XSTATE_HELPERS_SUPPORTED 0 | ||
| 400 | +#define XSTATE_BUFFER_SIZE 1 | ||
| 401 | +#define SET_XSTATE(b) | ||
| 402 | +#endif | ||
| 403 | + | ||
| 404 | +#endif /* _TEST_XSTATE_H */ | ||
| 405 | diff --git a/sysdeps/mach/hurd/i386/bits/sigcontext.h b/sysdeps/mach/hurd/i386/bits/sigcontext.h | ||
| 406 | index 6e5e220e9d..c44e4deac6 100644 | ||
| 407 | --- a/sysdeps/mach/hurd/i386/bits/sigcontext.h | ||
| 408 | +++ b/sysdeps/mach/hurd/i386/bits/sigcontext.h | ||
| 409 | @@ -88,6 +88,8 @@ struct sigcontext | ||
| 410 | struct i386_fp_save sc_fpsave; | ||
| 411 | struct i386_fp_regs sc_fpregs; | ||
| 412 | int sc_fpexcsr; /* FPSR including exception bits. */ | ||
| 413 | + | ||
| 414 | + struct i386_xfloat_state *xstate; | ||
| 415 | }; | ||
| 416 | |||
| 417 | /* Traditional BSD names for some members. */ | ||
| 418 | diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 419 | index ce8df8d02b..37fa984070 100644 | ||
| 420 | --- a/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 421 | +++ b/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 422 | @@ -21,6 +21,8 @@ | ||
| 423 | #include <stdlib.h> | ||
| 424 | #include <string.h> | ||
| 425 | |||
| 426 | +#include <cpuid.h> | ||
| 427 | + | ||
| 428 | /* This is run on the thread stack after restoring it, to be able to | ||
| 429 | unlock SS off sigstack. */ | ||
| 430 | static void | ||
| 431 | @@ -123,10 +125,32 @@ __sigreturn (struct sigcontext *scp) | ||
| 432 | if (scp->sc_onstack) | ||
| 433 | ss->sigaltstack.ss_flags &= ~SS_ONSTACK; | ||
| 434 | |||
| 435 | - if (scp->sc_fpused) | ||
| 436 | - /* Restore the FPU state. Mach conveniently stores the state | ||
| 437 | - in the format the i387 `frstor' instruction uses to restore it. */ | ||
| 438 | - asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); | ||
| 439 | +#ifdef i386_XFLOAT_STATE | ||
| 440 | + if ((scp->xstate) && (scp->xstate->initialized)) | ||
| 441 | + { | ||
| 442 | + unsigned eax, ebx, ecx, edx; | ||
| 443 | + __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 444 | + switch (scp->xstate->fp_save_kind) | ||
| 445 | + { | ||
| 446 | + case 0: // FNSAVE | ||
| 447 | + asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 448 | + break; | ||
| 449 | + case 1: // FXSAVE | ||
| 450 | + asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 451 | + "a" (eax), "d" (edx)); | ||
| 452 | + break; | ||
| 453 | + default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 454 | + asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 455 | + "a" (eax), "d" (edx)); | ||
| 456 | + break; | ||
| 457 | + } | ||
| 458 | + } | ||
| 459 | + else | ||
| 460 | +#endif | ||
| 461 | + if (scp->sc_fpused) | ||
| 462 | + /* Restore the FPU state. Mach conveniently stores the state | ||
| 463 | + in the format the i387 `frstor' instruction uses to restore it. */ | ||
| 464 | + asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); | ||
| 465 | |||
| 466 | { | ||
| 467 | /* There are convenient instructions to pop state off the stack, so we | ||
| 468 | diff --git a/sysdeps/mach/hurd/x86/trampoline.c b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 469 | index 8e2890f8c5..db756e8a1f 100644 | ||
| 470 | --- a/sysdeps/mach/hurd/x86/trampoline.c | ||
| 471 | +++ b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 472 | @@ -26,7 +26,11 @@ | ||
| 473 | #include "hurdfault.h" | ||
| 474 | #include <intr-msg.h> | ||
| 475 | #include <sys/ucontext.h> | ||
| 476 | - | ||
| 477 | +#ifdef __x86_64__ | ||
| 478 | +#include <mach/x86_64/mach_i386.h> | ||
| 479 | +#else | ||
| 480 | +#include <mach/i386/mach_i386.h> | ||
| 481 | +#endif | ||
| 482 | |||
| 483 | /* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers. */ | ||
| 484 | static void fill_siginfo (siginfo_t *si, int signo, | ||
| 485 | @@ -106,6 +110,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 486 | void firewall (void); | ||
| 487 | void *sigsp; | ||
| 488 | struct sigcontext *scp; | ||
| 489 | + vm_size_t xstate_size; | ||
| 490 | struct | ||
| 491 | { | ||
| 492 | union | ||
| 493 | @@ -145,6 +150,14 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 494 | struct hurd_userlink link; | ||
| 495 | ucontext_t ucontext; | ||
| 496 | siginfo_t siginfo; | ||
| 497 | +#ifdef __x86_64__ | ||
| 498 | + char _pad2[56]; | ||
| 499 | +#else | ||
| 500 | + char _pad2[20]; | ||
| 501 | +#endif | ||
| 502 | + char xstate[]; | ||
| 503 | + /* Don't add anything after xstate, as it's dynamically | ||
| 504 | + sized. */ | ||
| 505 | } *stackframe; | ||
| 506 | |||
| 507 | #ifdef __x86_64__ | ||
| 508 | @@ -170,6 +183,17 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 509 | if (! machine_get_basic_state (ss->thread, state)) | ||
| 510 | return NULL; | ||
| 511 | |||
| 512 | + /* Initialize the size of the CPU extended state, to be saved during | ||
| 513 | + * signal handling */ | ||
| 514 | +#ifdef i386_XFLOAT_STATE | ||
| 515 | + _Static_assert ((sizeof(*stackframe) + sizeof(struct i386_xfloat_state)) % 64 == 0, | ||
| 516 | + "stackframe size must be multiple of 64-byte minus " | ||
| 517 | + "sizeof(struct i386_xfloat_state), please adjust _pad2"); | ||
| 518 | + | ||
| 519 | + if (__i386_get_xstate_size(__mach_host_self(), &xstate_size)) | ||
| 520 | +#endif | ||
| 521 | + xstate_size = 0; | ||
| 522 | + | ||
| 523 | /* Save the original SP in the gratuitous `esp' slot. | ||
| 524 | We may need to reset the SP (the `uesp' slot) to avoid clobbering an | ||
| 525 | interrupted RPC frame. */ | ||
| 526 | @@ -196,14 +220,21 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 527 | #endif | ||
| 528 | } | ||
| 529 | |||
| 530 | - /* Push the arguments to call `trampoline' on the stack. */ | ||
| 531 | - sigsp -= sizeof (*stackframe); | ||
| 532 | -#ifdef __x86_64__ | ||
| 533 | - /* Align SP at 16 bytes. Coupled with the fact that sigreturn_addr is | ||
| 534 | - 16-byte aligned within the stackframe struct, this ensures that it ends | ||
| 535 | - up on a 16-byte aligned address, as required by the ABI. */ | ||
| 536 | - sigsp = (void *) ((uintptr_t) sigsp & ~15UL); | ||
| 537 | -#endif | ||
| 538 | + /* Push the arguments to call `trampoline' on the stack. | ||
| 539 | + * The extended state might have a variable size depending on the platform, | ||
| 540 | + * so we dynamically allocate it on the stack frame.*/ | ||
| 541 | + sigsp -= sizeof (*stackframe) + xstate_size; | ||
| 542 | + | ||
| 543 | + /* Align SP at 64 bytes. This is needed for two reasons: | ||
| 544 | + * - sigreturn_addr is 16-byte aligned within the stackframe | ||
| 545 | + * struct, and this ensures that it ends up on a 16-byte aligned | ||
| 546 | + * address, as required by the ABI. | ||
| 547 | + * - the XSAVE state needs to be aligned at 64 bytes (on both i386 and | ||
| 548 | + * x86_64), so we align the stackframe also at 64 bytes and add the | ||
| 549 | + * required padding at the end, see the _pad2 field. | ||
| 550 | + */ | ||
| 551 | + sigsp = (void *) ((uintptr_t) sigsp & ~63UL); | ||
| 552 | + | ||
| 553 | stackframe = sigsp; | ||
| 554 | |||
| 555 | if (_hurdsig_catch_memory_fault (stackframe)) | ||
| 556 | @@ -248,14 +279,40 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 557 | memcpy (&scp->sc_i386_thread_state, | ||
| 558 | &state->basic, sizeof (state->basic)); | ||
| 559 | |||
| 560 | - /* struct sigcontext is laid out so that starting at sc_fpkind mimics | ||
| 561 | - a struct i386_float_state. */ | ||
| 562 | - _Static_assert (offsetof (struct sigcontext, sc_i386_float_state) | ||
| 563 | - % __alignof__ (struct i386_float_state) == 0, | ||
| 564 | - "sc_i386_float_state layout mismatch"); | ||
| 565 | - ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE, | ||
| 566 | - &state->fpu, &scp->sc_i386_float_state, | ||
| 567 | - sizeof (state->fpu)); | ||
| 568 | + scp->xstate = NULL; | ||
| 569 | +#ifdef i386_XFLOAT_STATE | ||
| 570 | + if (xstate_size > 0) | ||
| 571 | + { | ||
| 572 | + mach_msg_type_number_t got = (xstate_size / sizeof (int)); | ||
| 573 | + | ||
| 574 | + ok = (! __thread_get_state (ss->thread, i386_XFLOAT_STATE, | ||
| 575 | + (thread_state_t) stackframe->xstate, &got) | ||
| 576 | + && got == (xstate_size / sizeof (int))); | ||
| 577 | + | ||
| 578 | + if (((struct i386_xfloat_state*) stackframe->xstate)->fp_save_kind > 5) | ||
| 579 | + /* We support up to XSAVES */ | ||
| 580 | + ok = 0; | ||
| 581 | + | ||
| 582 | + if (ok) | ||
| 583 | + { | ||
| 584 | + scp->xstate = (struct i386_xfloat_state*) stackframe->xstate; | ||
| 585 | + assert((uintptr_t)scp->xstate->hw_state % 64 == 0); | ||
| 586 | + } | ||
| 587 | + } | ||
| 588 | + else | ||
| 589 | +#endif | ||
| 590 | + ok = 0; | ||
| 591 | + if (!ok) | ||
| 592 | + { | ||
| 593 | + /* struct sigcontext is laid out so that starting at sc_fpkind mimics | ||
| 594 | + a struct i386_float_state. */ | ||
| 595 | + _Static_assert (offsetof (struct sigcontext, sc_i386_float_state) | ||
| 596 | + % __alignof__ (struct i386_float_state) == 0, | ||
| 597 | + "sc_i386_float_state layout mismatch"); | ||
| 598 | + ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE, | ||
| 599 | + &state->fpu, &scp->sc_i386_float_state, | ||
| 600 | + sizeof (state->fpu)); | ||
| 601 | + } | ||
| 602 | |||
| 603 | /* Set up the arguments for the signal handler. */ | ||
| 604 | stackframe->signo = signo; | ||
| 605 | diff --git a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h | ||
| 606 | index 7bac881176..d83795fcbc 100644 | ||
| 607 | --- a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h | ||
| 608 | +++ b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h | ||
| 609 | @@ -96,6 +96,8 @@ struct sigcontext | ||
| 610 | struct i386_fp_save sc_fpsave; | ||
| 611 | struct i386_fp_regs sc_fpregs; | ||
| 612 | int sc_fpexcsr; /* FPSR including exception bits. */ | ||
| 613 | + | ||
| 614 | + struct i386_xfloat_state *xstate; | ||
| 615 | }; | ||
| 616 | |||
| 617 | /* Traditional BSD names for some members. */ | ||
| 618 | diff --git a/sysdeps/mach/hurd/x86_64/sigreturn.c b/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 619 | index 81a2d3ba74..dff8e76dc8 100644 | ||
| 620 | --- a/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 621 | +++ b/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 622 | @@ -20,6 +20,8 @@ | ||
| 623 | #include <hurd/msg.h> | ||
| 624 | #include <stdlib.h> | ||
| 625 | |||
| 626 | +#include <cpuid.h> | ||
| 627 | + | ||
| 628 | /* This is run on the thread stack after restoring it, to be able to | ||
| 629 | unlock SS off sigstack. */ | ||
| 630 | void | ||
| 631 | @@ -116,10 +118,32 @@ __sigreturn (struct sigcontext *scp) | ||
| 632 | if (scp->sc_onstack) | ||
| 633 | ss->sigaltstack.ss_flags &= ~SS_ONSTACK; | ||
| 634 | |||
| 635 | - if (scp->sc_fpused) | ||
| 636 | - /* Restore the FPU state. Mach conveniently stores the state | ||
| 637 | - in the format the i387 `frstor' instruction uses to restore it. */ | ||
| 638 | - asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); | ||
| 639 | +#ifdef i386_XFLOAT_STATE | ||
| 640 | + if ((scp->xstate) && (scp->xstate->initialized)) | ||
| 641 | + { | ||
| 642 | + unsigned eax, ebx, ecx, edx; | ||
| 643 | + __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 644 | + switch (scp->xstate->fp_save_kind) | ||
| 645 | + { | ||
| 646 | + case 0: // FNSAVE | ||
| 647 | + asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 648 | + break; | ||
| 649 | + case 1: // FXSAVE | ||
| 650 | + asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 651 | + "a" (eax), "d" (edx)); | ||
| 652 | + break; | ||
| 653 | + default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 654 | + asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 655 | + "a" (eax), "d" (edx)); | ||
| 656 | + break; | ||
| 657 | + } | ||
| 658 | + } | ||
| 659 | + else | ||
| 660 | +#endif | ||
| 661 | + if (scp->sc_fpused) | ||
| 662 | + /* Restore the FPU state. Mach conveniently stores the state | ||
| 663 | + in the format the i387 `frstor' instruction uses to restore it. */ | ||
| 664 | + asm volatile ("frstor %0" : : "m" (scp->sc_fpsave)); | ||
| 665 | |||
| 666 | /* Copy the registers onto the user's stack, to be able to release the | ||
| 667 | altstack (by unlocking sigstate). Note that unless an altstack is used, | ||
| 668 | -- | ||
| 669 | 2.51.0 | ||
| 670 | |||
| 671 | From 8d54b428cfe98c21049f94c8af3bf302e44091e9 Mon Sep 17 00:00:00 2001 | ||
| 672 | From: Samuel Thibault <samuel.thibault@ens-lyon.org> | ||
| 673 | Date: Mon, 21 Apr 2025 19:42:27 +0200 | ||
| 674 | Subject: [PATCH] hurd: Do not restore xstate when it is not initialized | ||
| 675 | |||
| 676 | If the process has never used fp before getting a signal, xstate is set | ||
| 677 | (and thus the x87 state is not initialized) but xstate->initialized is still | ||
| 678 | 0, and we should not restore anything. | ||
| 679 | --- | ||
| 680 | sysdeps/mach/hurd/i386/sigreturn.c | 37 +++++++++++++++------------- | ||
| 681 | sysdeps/mach/hurd/x86_64/sigreturn.c | 37 +++++++++++++++------------- | ||
| 682 | 2 files changed, 40 insertions(+), 34 deletions(-) | ||
| 683 | |||
| 684 | diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 685 | index 37fa984070..dc57d6122c 100644 | ||
| 686 | --- a/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 687 | +++ b/sysdeps/mach/hurd/i386/sigreturn.c | ||
| 688 | @@ -126,24 +126,27 @@ __sigreturn (struct sigcontext *scp) | ||
| 689 | ss->sigaltstack.ss_flags &= ~SS_ONSTACK; | ||
| 690 | |||
| 691 | #ifdef i386_XFLOAT_STATE | ||
| 692 | - if ((scp->xstate) && (scp->xstate->initialized)) | ||
| 693 | + if (scp->xstate) | ||
| 694 | { | ||
| 695 | - unsigned eax, ebx, ecx, edx; | ||
| 696 | - __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 697 | - switch (scp->xstate->fp_save_kind) | ||
| 698 | - { | ||
| 699 | - case 0: // FNSAVE | ||
| 700 | - asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 701 | - break; | ||
| 702 | - case 1: // FXSAVE | ||
| 703 | - asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 704 | - "a" (eax), "d" (edx)); | ||
| 705 | - break; | ||
| 706 | - default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 707 | - asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 708 | - "a" (eax), "d" (edx)); | ||
| 709 | - break; | ||
| 710 | - } | ||
| 711 | + if (scp->xstate->initialized) | ||
| 712 | + { | ||
| 713 | + unsigned eax, ebx, ecx, edx; | ||
| 714 | + __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 715 | + switch (scp->xstate->fp_save_kind) | ||
| 716 | + { | ||
| 717 | + case 0: // FNSAVE | ||
| 718 | + asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 719 | + break; | ||
| 720 | + case 1: // FXSAVE | ||
| 721 | + asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 722 | + "a" (eax), "d" (edx)); | ||
| 723 | + break; | ||
| 724 | + default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 725 | + asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 726 | + "a" (eax), "d" (edx)); | ||
| 727 | + break; | ||
| 728 | + } | ||
| 729 | + } | ||
| 730 | } | ||
| 731 | else | ||
| 732 | #endif | ||
| 733 | diff --git a/sysdeps/mach/hurd/x86_64/sigreturn.c b/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 734 | index dff8e76dc8..773c00f86d 100644 | ||
| 735 | --- a/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 736 | +++ b/sysdeps/mach/hurd/x86_64/sigreturn.c | ||
| 737 | @@ -119,24 +119,27 @@ __sigreturn (struct sigcontext *scp) | ||
| 738 | ss->sigaltstack.ss_flags &= ~SS_ONSTACK; | ||
| 739 | |||
| 740 | #ifdef i386_XFLOAT_STATE | ||
| 741 | - if ((scp->xstate) && (scp->xstate->initialized)) | ||
| 742 | + if (scp->xstate) | ||
| 743 | { | ||
| 744 | - unsigned eax, ebx, ecx, edx; | ||
| 745 | - __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 746 | - switch (scp->xstate->fp_save_kind) | ||
| 747 | - { | ||
| 748 | - case 0: // FNSAVE | ||
| 749 | - asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 750 | - break; | ||
| 751 | - case 1: // FXSAVE | ||
| 752 | - asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 753 | - "a" (eax), "d" (edx)); | ||
| 754 | - break; | ||
| 755 | - default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 756 | - asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 757 | - "a" (eax), "d" (edx)); | ||
| 758 | - break; | ||
| 759 | - } | ||
| 760 | + if (scp->xstate->initialized) | ||
| 761 | + { | ||
| 762 | + unsigned eax, ebx, ecx, edx; | ||
| 763 | + __cpuid_count(0xd, 0, eax, ebx, ecx, edx); | ||
| 764 | + switch (scp->xstate->fp_save_kind) | ||
| 765 | + { | ||
| 766 | + case 0: // FNSAVE | ||
| 767 | + asm volatile("frstor %0" : : "m" (scp->xstate->hw_state)); | ||
| 768 | + break; | ||
| 769 | + case 1: // FXSAVE | ||
| 770 | + asm volatile("fxrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 771 | + "a" (eax), "d" (edx)); | ||
| 772 | + break; | ||
| 773 | + default: // XSAVE, XSAVEOPT, XSAVEC, XSAVES | ||
| 774 | + asm volatile("xrstor %0" : : "m" (scp->xstate->hw_state), \ | ||
| 775 | + "a" (eax), "d" (edx)); | ||
| 776 | + break; | ||
| 777 | + } | ||
| 778 | + } | ||
| 779 | } | ||
| 780 | else | ||
| 781 | #endif | ||
| 782 | -- | ||
| 783 | 2.51.0 | ||
| 784 | |||
| 785 | From 0f2df19d9535d234b31c65f84a6c67ac2e0bd027 Mon Sep 17 00:00:00 2001 | ||
| 786 | From: Samuel Thibault <samuel.thibault@ens-lyon.org> | ||
| 787 | Date: Mon, 21 Apr 2025 19:45:02 +0200 | ||
| 788 | Subject: [PATCH] hurd: Do not check for xstate level if it was not | ||
| 789 | initialized | ||
| 790 | |||
| 791 | If __thread_get_state failed, there is no xstate level to check. | ||
| 792 | ok is 0 already and the memory exists, but better not read uninitialized | ||
| 793 | memory. | ||
| 794 | --- | ||
| 795 | sysdeps/mach/hurd/x86/trampoline.c | 2 +- | ||
| 796 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
| 797 | |||
| 798 | diff --git a/sysdeps/mach/hurd/x86/trampoline.c b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 799 | index db756e8a1f..02510b178c 100644 | ||
| 800 | --- a/sysdeps/mach/hurd/x86/trampoline.c | ||
| 801 | +++ b/sysdeps/mach/hurd/x86/trampoline.c | ||
| 802 | @@ -289,7 +289,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, const struct sigaction *action | ||
| 803 | (thread_state_t) stackframe->xstate, &got) | ||
| 804 | && got == (xstate_size / sizeof (int))); | ||
| 805 | |||
| 806 | - if (((struct i386_xfloat_state*) stackframe->xstate)->fp_save_kind > 5) | ||
| 807 | + if (ok && ((struct i386_xfloat_state*) stackframe->xstate)->fp_save_kind > 5) | ||
| 808 | /* We support up to XSAVES */ | ||
| 809 | ok = 0; | ||
| 810 | |||
| 811 | -- | ||
| 812 | 2.51.0 | ||
| 813 | |||
