gnu: glibc/hurd: Add patches for the 64bit Hurd.

These patches fix:

  * Statically linked tar to hang/segfault upon issuing the "--mtime=@1"
  warning; this is also applicable for the 32bit Hurd using glibc-2.39!

See <https://lists.gnu.org/archive/html/bug-hurd/2024-11/msg00115.html>.

  * Shell replacement problems for the 64bit Hurd.

See <https://lists.debian.org/debian-hurd/2024/07/msg00063.html>.

  * Findutil's gnulib-tests/test-sigaction failure.

* gnu/packages/patches/glibc-hurd-pthread_setcancelstate.patch,
gnu/packages/patches/glibc-hurd64-fault.patch,
gnu/packages/patches/glibc-hurd64-intr-msg-clobber.patch,
gnu/packages/patches/glibc-hurd64-sgms-context.patch: New file.
* gnu/local.mk (dist_patch_DATA): Register them.
* gnu/packages/base.scm (glibc/hurd): Use them.

Change-Id: I9ee65983876cd22ad1dc01aabb41a34074631599
This commit is contained in:
Janneke Nieuwenhuizen 2024-11-16 17:55:21 +01:00
parent cb765c4218
commit a9005279d0
No known key found for this signature in database
GPG key ID: F3C1A0D9C1D65273
6 changed files with 706 additions and 1 deletions

View file

@ -1439,7 +1439,11 @@ dist_patch_DATA = \
%D%/packages/patches/glibc-hurd-getauxval.patch \
%D%/packages/patches/glibc-hurd-gettyent.patch \
%D%/packages/patches/glibc-hurd-mach-print.patch \
%D%/packages/patches/glibc-hurd-pthread_setcancelstate.patch \
%D%/packages/patches/glibc-hurd-signal-sa-siginfo.patch \
%D%/packages/patches/glibc-hurd64-fault.patch \
%D%/packages/patches/glibc-hurd64-intr-msg-clobber.patch \
%D%/packages/patches/glibc-hurd64-sgms-context.patch \
%D%/packages/patches/glibc-ldd-powerpc.patch \
%D%/packages/patches/glibc-ldd-x86_64.patch \
%D%/packages/patches/glibc-locales.patch \

View file

@ -1588,7 +1588,17 @@ variety of options. It is an alternative to the shell \"type\" built-in
command.")
(license gpl3+))) ; some files are under GPLv2+
(define-public glibc/hurd glibc)
(define-public glibc/hurd
(package/inherit glibc
(source
(origin
(inherit (package-source glibc))
(patches
(append (origin-patches (package-source glibc))
(search-patches "glibc-hurd-pthread_setcancelstate.patch"
"glibc-hurd64-fault.patch"
"glibc-hurd64-intr-msg-clobber.patch"
"glibc-hurd64-sgms-context.patch")))))))
(define-public glibc/hurd-headers
(package/inherit glibc/hurd

View file

@ -0,0 +1,92 @@
Upstream-status: Taken from <https://salsa.debian.org/glibc-team/glibc/-/blob/25a0a47767fe7dc5151eb36afaade17218728efe/debian/patches/hurd-i386/local-static_pthread_setcancelstate.diff>.
This is needed for the 64bit Hurd statically linked tar non to hang when
issuing a warning.
since the move of libpthread functions to libc, glibc dropped the use
of __libc_ptf_call. But htl hasn't made the move yet, so we have to use
__libc_ptf_call there for now.
Index: glibc-2.36/misc/error.c
===================================================================
--- glibc-2.36.orig/misc/error.c
+++ glibc-2.36/misc/error.c
@@ -240,7 +240,8 @@ __error_internal (int status, int errnum
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
- __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
+ __libc_ptf_call (__pthread_setcancelstate,
+ (PTHREAD_CANCEL_DISABLE, &state), 0);
#endif
flush_stdout ();
@@ -262,7 +263,7 @@ __error_internal (int status, int errnum
#ifdef _LIBC
_IO_funlockfile (stderr);
- __pthread_setcancelstate (state, NULL);
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
#endif
}
@@ -306,7 +307,9 @@ __error_at_line_internal (int status, in
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
- __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
+ __libc_ptf_call (__pthread_setcancelstate,
+ (PTHREAD_CANCEL_DISABLE, &state),
+ 0);
#endif
flush_stdout ();
@@ -336,7 +339,7 @@ __error_at_line_internal (int status, in
#ifdef _LIBC
_IO_funlockfile (stderr);
- __pthread_setcancelstate (state, NULL);
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
#endif
}
Index: glibc-2.36/libio/iopopen.c
===================================================================
--- glibc-2.36.orig/libio/iopopen.c
+++ glibc-2.36/libio/iopopen.c
@@ -281,9 +281,10 @@ _IO_new_proc_close (FILE *fp)
do
{
int state;
- __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
+ __libc_ptf_call (__pthread_setcancelstate,
+ (PTHREAD_CANCEL_DISABLE, &state), 0);
wait_pid = __waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
- __pthread_setcancelstate (state, NULL);
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
}
while (wait_pid == -1 && errno == EINTR);
if (wait_pid == -1)
Index: glibc-2.36/stdlib/fmtmsg.c
===================================================================
--- glibc-2.36.orig/stdlib/fmtmsg.c
+++ glibc-2.36/stdlib/fmtmsg.c
@@ -124,7 +124,8 @@ fmtmsg (long int classification, const c
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
- __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
+ __libc_ptf_call (__pthread_setcancelstate,
+ (PTHREAD_CANCEL_DISABLE, &state), 0);
__libc_lock_lock (lock);
@@ -193,7 +194,7 @@ fmtmsg (long int classification, const c
__libc_lock_unlock (lock);
- __pthread_setcancelstate (state, NULL);
+ __libc_ptf_call (__pthread_setcancelstate, (state, NULL), 0);
return result;
}

View file

@ -0,0 +1,32 @@
Upstream-status: Taken from: <https://salsa.debian.org/glibc-team/glibc/-/blob/c36c87acb1a35d6e06db6cef1e28cf2f405e1a9e/debian/patches/hurd-i386/git-fault-64bit.diff>.
See <https://lists.gnu.org/archive/html/bug-hurd/2024-11/msg00115.html>.
commit 11ad033e1c09c8b8e7bbaa72420f41ab8bcf0f63
Author: Flavio Cruz <flaviocruz@gmail.com>
Date: Tue Jul 30 00:51:20 2024 -0400
x86_64 hurd: ensure we have a large enough buffer to receive exception_raise requests.
Message-ID: <gtxd6s4s7fi7hdrlb7zayq3akij7x6jqawwq3zfl3v4nqspulo@euucuzeonrl6>
diff --git a/hurd/hurdfault.c b/hurd/hurdfault.c
index 5110c6030f..1fe973f54d 100644
--- a/hurd/hurdfault.c
+++ b/hurd/hurdfault.c
@@ -121,7 +121,14 @@ faulted (void)
struct
{
mach_msg_header_t head;
- char buf[64];
+ /* This is the size of the exception_raise request
+ * including mach_msg_header_t.
+ * See generated code in faultexc_server.c. */
+#ifdef __LP64__
+ char buf[112];
+#else
+ char buf[64];
+#endif
} request;
mig_reply_header_t reply;
extern int _hurdsig_fault_exc_server (mach_msg_header_t *,

View file

@ -0,0 +1,62 @@
Upstream-status: Taken from <https://salsa.debian.org/glibc-team/glibc/-/blob/c36c87acb1a35d6e06db6cef1e28cf2f405e1a9e/debian/patches/hurd-i386/git-intr-msg-clobber.diff>.
See <https://lists.gnu.org/archive/html/bug-hurd/2024-11/msg00115.html>,
and <https://lists.debian.org/debian-hurd/2024/07/msg00063.html>.
Commited for 2.40
commit c8b4ce0b368115714bd4cce131e1683759471099
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date: Sat Jul 13 17:00:55 2024 +0200
hurd: Fix restoring message to be retried
save_data stores the start of the original message to be retried,
overwritten by the EINTR reply. In 64b builds the overwrite is however
rounded up to the 64b pointer size, so we have to save more than just
the 32b err.
Thanks a lot to Luca Dariz for the investigation!
diff --git a/hurd/intr-msg.c b/hurd/intr-msg.c
index 2c2e7dc463..424c1fc700 100644
--- a/hurd/intr-msg.c
+++ b/hurd/intr-msg.c
@@ -42,7 +42,10 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
struct clobber
{
mach_msg_type_t type;
- error_t err;
+ union {
+ error_t err;
+ uintptr_t align;
+ };
};
union msg
{
Taken from: <https://salsa.debian.org/glibc-team/glibc/-/blob/027f94215a633cbf53794d4b48675fde36706e35/debian/patches/hurd-i386/local-intr-msg-clobber.diff>
Force putting save_data on the stack rather than in SSE register
The signal management does not yet properly save SSE state, so that save_data
would get overwritten by signal handlers, notably leading to `` shell
replacement getting empty content because then the io_read RPC retry gets an
MIG_BAD_ARGUMENTS error.
XXX: This is only temporary to fix the common shll replacement issue, and is
waiting for proper SSE state restoration.
Index: glibc-2.38/hurd/intr-msg.c
===================================================================
--- glibc-2.38.orig/hurd/intr-msg.c
+++ glibc-2.38/hurd/intr-msg.c
@@ -79,7 +79,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header
mach_msg_bits_t msgh_bits;
mach_port_t remote_port;
mach_msg_id_t msgid;
- struct clobber save_data;
+ volatile struct clobber save_data;
if ((option & (MACH_SEND_MSG|MACH_RCV_MSG)) != (MACH_SEND_MSG|MACH_RCV_MSG)
|| _hurd_msgport_thread == MACH_PORT_NULL)

View file

@ -0,0 +1,505 @@
Upstream-status: Taken from <https://salsa.debian.org/glibc-team/glibc/-/blob/62c59900cfdf6b9af187f4ae03addcd7cd226bfc/debian/patches/hurd-i386/git-context.diff>.
commit 88b771ab5e1169e746dbf4a990d90cffc5fa54ea
Author: Flavio Cruz <flaviocruz@gmail.com>
Date: Sat Feb 17 15:25:35 2024 -0500
Implement setcontext/getcontext/makecontext/swapcontext for Hurd x86_64
Tested with the tests provided by glibc plus some other toy examples.
Message-ID: <20240217202535.1860803-1-flaviocruz@gmail.com>
diff --git a/sysdeps/mach/hurd/x86_64/Makefile b/sysdeps/mach/hurd/x86_64/Makefile
index 80cf2eb6dc..2b43f5d625 100644
--- a/sysdeps/mach/hurd/x86_64/Makefile
+++ b/sysdeps/mach/hurd/x86_64/Makefile
@@ -3,3 +3,7 @@ ifeq ($(subdir),conform)
# (missing SA_NOCLDWAIT)
conformtest-xfail-conds += x86_64-gnu
endif
+
+ifeq ($(subdir),stdlib)
+sysdep_routines += __start_context
+endif
diff --git a/sysdeps/mach/hurd/x86_64/__start_context.S b/sysdeps/mach/hurd/x86_64/__start_context.S
new file mode 100644
index 0000000000..3cb4c6b5a9
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/__start_context.S
@@ -0,0 +1,49 @@
+/* Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+/* This is the helper code which gets called if a function which is
+ registered with 'makecontext' returns. In this case we have to
+ install the context listed in the uc_link element of the context
+ 'makecontext' manipulated at the time of the 'makecontext' call.
+ If the pointer is NULL the process must terminate. */
+
+
+ENTRY(__start_context)
+ /* This removes the parameters passed to the function given to
+ 'makecontext' from the stack. RBX contains the address
+ on the stack pointer for the next context. */
+ movq %rbx, %rsp
+
+ /* Don't use pop here so that stack is aligned to 16 bytes. */
+ movq (%rsp), %rdi /* This is the next context. */
+ testq %rdi, %rdi
+ je 2f /* If it is zero exit. */
+
+ call __setcontext
+ /* If this returns (which can happen if __sigprocmask fails) we'll
+ exit the program with the return error value (-1). */
+ movq %rax,%rdi
+
+2:
+ call HIDDEN_JUMPTARGET(exit)
+ /* The 'exit' call should never return. In case it does cause
+ the process to terminate. */
+L(hlt):
+ hlt
+END(__start_context)
diff --git a/sysdeps/mach/hurd/x86_64/getcontext.S b/sysdeps/mach/hurd/x86_64/getcontext.S
new file mode 100644
index 0000000000..ef431be1a3
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/getcontext.S
@@ -0,0 +1,68 @@
+/* Save current context.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__getcontext)
+ /* Save the preserved registers, the registers used for passing
+ args, and the return address. */
+ movq %rbx, oRBX(%rdi)
+ movq %rbp, oRBP(%rdi)
+ movq %r12, oR12(%rdi)
+ movq %r13, oR13(%rdi)
+ movq %r14, oR14(%rdi)
+ movq %r15, oR15(%rdi)
+
+ movq %rdi, oRDI(%rdi)
+ movq %rsi, oRSI(%rdi)
+ movq %rdx, oRDX(%rdi)
+ movq %rcx, oRCX(%rdi)
+ movq %r8, oR8(%rdi)
+ movq %r9, oR9(%rdi)
+
+ movq (%rsp), %rcx
+ movq %rcx, oRIP(%rdi)
+ leaq 8(%rsp), %rcx /* Exclude the return address. */
+ movq %rcx, oRSP(%rdi)
+
+ /* We have separate floating-point register content memory on the
+ stack. We use the __fpregs_mem block in the context. Set the
+ links up correctly. */
+
+ leaq oFPREGSMEM(%rdi), %rcx
+ movq %rcx, oFPREGS(%rdi)
+ /* Save the floating-point environment. */
+ fnstenv (%rcx)
+ fldenv (%rcx)
+ stmxcsr oMXCSR(%rdi)
+
+ /* Save the current signal mask with
+ * __sigprocmask(SIG_BLOCK, NULL, oSIGMASK(%rdi)); */
+ leaq oSIGMASK(%rdi), %rdx
+ movq $0, %rsi
+ movl $SIG_BLOCK, %edi
+ call HIDDEN_JUMPTARGET (__sigprocmask)
+
+ /* Propagate %rax (and errno, in case). */
+ ret
+PSEUDO_END(__getcontext)
+
+weak_alias (__getcontext, getcontext)
diff --git a/sysdeps/mach/hurd/x86_64/makecontext.c b/sysdeps/mach/hurd/x86_64/makecontext.c
new file mode 100644
index 0000000000..6990a7775c
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/makecontext.c
@@ -0,0 +1,119 @@
+/* Create new context.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <ucontext.h>
+
+#include "ucontext_i.h"
+
+/* This implementation can handle any ARGC value but only
+ normal integer parameters.
+ makecontext sets up a stack and the registers for the
+ user context. The stack looks like this:
+ +-----------------------+
+ | next context |
+ +-----------------------+
+ | parameter 7-n |
+ +-----------------------+
+ | trampoline address |
+ %rsp -> +-----------------------+
+
+ The registers are set up like this:
+ %rdi,%rsi,%rdx,%rcx,%r8,%r9: parameter 1 to 6
+ %rbx : address of next context
+ %rsp : stack pointer.
+*/
+
+/* XXX: This implementation currently only handles integer arguments.
+ To handle long int and pointer arguments the va_arg arguments needs
+ to be changed to long and also the stdlib/tst-setcontext.c file needs
+ to be changed to pass long arguments to makecontext. */
+
+
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ extern void __start_context (void) attribute_hidden;
+ greg_t *sp;
+ unsigned int idx_uc_link;
+ va_list ap;
+ int i;
+
+ /* Generate room on stack for parameter if needed and uc_link. */
+ sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp
+ + ucp->uc_stack.ss_size);
+ sp -= (argc > 6 ? argc - 6 : 0) + 1;
+ /* Align stack and make space for trampoline address. */
+ sp = (greg_t *) ((((uintptr_t) sp) & -16L) - 8);
+
+ idx_uc_link = (argc > 6 ? argc - 6 : 0) + 1;
+
+ /* Setup context ucp. */
+ /* Address to jump to. */
+ ucp->uc_mcontext.gregs[REG_RIP] = (uintptr_t) func;
+ /* Setup rbx.*/
+ ucp->uc_mcontext.gregs[REG_RBX] = (uintptr_t) &sp[idx_uc_link];
+ ucp->uc_mcontext.gregs[REG_RSP] = (uintptr_t) sp;
+
+ /* Setup stack. */
+ sp[0] = (uintptr_t) &__start_context;
+ sp[idx_uc_link] = (uintptr_t) ucp->uc_link;
+
+ va_start (ap, argc);
+ /* Handle arguments.
+
+ The standard says the parameters must all be int values. This is
+ an historic accident and would be done differently today. For
+ x86-64 all integer values are passed as 64-bit values and
+ therefore extending the API to copy 64-bit values instead of
+ 32-bit ints makes sense. It does not break existing
+ functionality and it does not violate the standard which says
+ that passing non-int values means undefined behavior. */
+ for (i = 0; i < argc; ++i)
+ switch (i)
+ {
+ case 0:
+ ucp->uc_mcontext.gregs[REG_RDI] = va_arg (ap, greg_t);
+ break;
+ case 1:
+ ucp->uc_mcontext.gregs[REG_RSI] = va_arg (ap, greg_t);
+ break;
+ case 2:
+ ucp->uc_mcontext.gregs[REG_RDX] = va_arg (ap, greg_t);
+ break;
+ case 3:
+ ucp->uc_mcontext.gregs[REG_RCX] = va_arg (ap, greg_t);
+ break;
+ case 4:
+ ucp->uc_mcontext.gregs[REG_R8] = va_arg (ap, greg_t);
+ break;
+ case 5:
+ ucp->uc_mcontext.gregs[REG_R9] = va_arg (ap, greg_t);
+ break;
+ default:
+ /* Put value on stack. */
+ sp[i - 5] = va_arg (ap, greg_t);
+ break;
+ }
+ va_end (ap);
+}
+
+
+weak_alias (__makecontext, makecontext)
diff --git a/sysdeps/mach/hurd/x86_64/setcontext.S b/sysdeps/mach/hurd/x86_64/setcontext.S
new file mode 100644
index 0000000000..99919ee2a8
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/setcontext.S
@@ -0,0 +1,96 @@
+/* Install given context.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__setcontext)
+ /* Save argument since call will destroy it. */
+ pushq %rdi
+ cfi_adjust_cfa_offset(8)
+
+ /* Set the signal mask with
+ __sigprocmask (SIG_SETMASK, mask, NULL). */
+ xorl %edx, %edx
+ leaq oSIGMASK(%rdi), %rsi
+ movl $SIG_SETMASK, %edi
+ call HIDDEN_JUMPTARGET (__sigprocmask)
+ /* Pop the pointer into RDX. The choice is arbitrary, but
+ leaving RDI and RSI available for use later can avoid
+ shuffling values. */
+ popq %rdx
+
+ test %rax, %rax
+ jne L(pseudo_end)
+
+ /* Restore the floating-point context. Not the registers, only the
+ rest. */
+ movq oFPREGS(%rdx), %rcx
+ fldenv (%rcx)
+ ldmxcsr oMXCSR(%rdx)
+
+ /* Load the new stack pointer, the preserved registers and
+ registers used for passing args. */
+ cfi_def_cfa(%rdx, 0)
+ cfi_offset(%rbx,oRBX)
+ cfi_offset(%rbp,oRBP)
+ cfi_offset(%r12,oR12)
+ cfi_offset(%r13,oR13)
+ cfi_offset(%r14,oR14)
+ cfi_offset(%r15,oR15)
+ cfi_offset(%rsp,oRSP)
+ cfi_offset(%rip,oRIP)
+
+ movq oRSP(%rdx), %rsp
+ movq oRBX(%rdx), %rbx
+ movq oRBP(%rdx), %rbp
+ movq oR12(%rdx), %r12
+ movq oR13(%rdx), %r13
+ movq oR14(%rdx), %r14
+ movq oR15(%rdx), %r15
+
+ /* The following ret should return to the address set with
+ getcontext. Therefore push the address on the stack. */
+ movq oRIP(%rdx), %rcx
+ pushq %rcx
+
+ movq oRSI(%rdx), %rsi
+ movq oRDI(%rdx), %rdi
+ movq oRCX(%rdx), %rcx
+ movq oR8(%rdx), %r8
+ movq oR9(%rdx), %r9
+
+ /* Setup finally %rdx. */
+ movq oRDX(%rdx), %rdx
+
+ /* End FDE here, we fall into another context. */
+ cfi_endproc
+ cfi_startproc
+
+ /* Clear rax to indicate success. */
+ xorl %eax, %eax
+L(pseudo_end):
+ /* The following 'ret' will pop the address of the code and jump
+ to it. */
+ ret
+PSEUDO_END(__setcontext)
+libc_hidden_def (__setcontext)
+
+weak_alias (__setcontext, setcontext)
diff --git a/sysdeps/mach/hurd/x86_64/swapcontext.S b/sysdeps/mach/hurd/x86_64/swapcontext.S
new file mode 100644
index 0000000000..79718a1fdd
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/swapcontext.S
@@ -0,0 +1,120 @@
+/* Save current context and install the given one.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+/* int __swapcontext (ucontext_t *oucp, const ucontext_t *ucp);
+
+ Saves the machine context in oucp such that when it is activated,
+ it appears as if __swapcontextt() returned again, restores the
+ machine context in ucp and thereby resumes execution in that
+ context.
+
+ This implementation is intended to be used for *synchronous* context
+ switches only. Therefore, it does not have to save anything
+ other than the PRESERVED state. */
+
+ENTRY(__swapcontext)
+ /* Save the preserved registers, the registers used for passing args,
+ and the return address. */
+ movq %rbx, oRBX(%rdi)
+ movq %rbp, oRBP(%rdi)
+ movq %r12, oR12(%rdi)
+ movq %r13, oR13(%rdi)
+ movq %r14, oR14(%rdi)
+ movq %r15, oR15(%rdi)
+
+ movq %rdi, oRDI(%rdi)
+ movq %rsi, oRSI(%rdi)
+ movq %rdx, oRDX(%rdi)
+ movq %rcx, oRCX(%rdi)
+ movq %r8, oR8(%rdi)
+ movq %r9, oR9(%rdi)
+
+ movq (%rsp), %rcx
+ movq %rcx, oRIP(%rdi)
+ leaq 8(%rsp), %rcx /* Exclude the return address. */
+ movq %rcx, oRSP(%rdi)
+
+ /* We have separate floating-point register content memory on the
+ stack. We use the __fpregs_mem block in the context. Set the
+ links up correctly. */
+ leaq oFPREGSMEM(%rdi), %rcx
+ movq %rcx, oFPREGS(%rdi)
+ /* Save the floating-point environment. */
+ fnstenv (%rcx)
+ stmxcsr oMXCSR(%rdi)
+
+
+ /* The function call destroys some registers, save ucp. */
+ movq %rsi, %r12
+
+ /* Save the current signal mask and install the new one with
+ __sigprocmask (SIG_BLOCK, newset, oldset). */
+ leaq oSIGMASK(%rdi), %rdx
+ leaq oSIGMASK(%rsi), %rsi
+ movl $SIG_SETMASK, %edi
+ call HIDDEN_JUMPTARGET (__sigprocmask)
+ test %rax, %rax
+ jne L(pseudo_end)
+
+ /* Restore destroyed register into RDX. The choice is arbitrary,
+ but leaving RDI and RSI available for use later can avoid
+ shuffling values. */
+ movq %r12, %rdx
+
+ /* Restore the floating-point context. Not the registers, only the
+ rest. */
+ movq oFPREGS(%rdx), %rcx
+ fldenv (%rcx)
+ ldmxcsr oMXCSR(%rdx)
+
+ /* Load the new stack pointer and the preserved registers. */
+ movq oRSP(%rdx), %rsp
+ movq oRBX(%rdx), %rbx
+ movq oRBP(%rdx), %rbp
+ movq oR12(%rdx), %r12
+ movq oR13(%rdx), %r13
+ movq oR14(%rdx), %r14
+ movq oR15(%rdx), %r15
+
+ /* The following ret should return to the address set with
+ getcontext. Therefore push the address on the stack. */
+ movq oRIP(%rdx), %rcx
+ pushq %rcx
+
+ /* Setup registers used for passing args. */
+ movq oRDI(%rdx), %rdi
+ movq oRSI(%rdx), %rsi
+ movq oRCX(%rdx), %rcx
+ movq oR8(%rdx), %r8
+ movq oR9(%rdx), %r9
+
+ /* Setup finally %rdx. */
+ movq oRDX(%rdx), %rdx
+
+ /* Clear rax to indicate success. */
+ xorl %eax, %eax
+L(pseudo_end):
+ ret
+PSEUDO_END(__swapcontext)
+
+weak_alias (__swapcontext, swapcontext)