diff options
Diffstat (limited to 'gnu/packages/patches/glibc-hurd64-sgms-context.patch')
-rw-r--r-- | gnu/packages/patches/glibc-hurd64-sgms-context.patch | 505 |
1 files changed, 505 insertions, 0 deletions
diff --git a/gnu/packages/patches/glibc-hurd64-sgms-context.patch b/gnu/packages/patches/glibc-hurd64-sgms-context.patch new file mode 100644 index 0000000000..7ae45542c1 --- /dev/null +++ b/gnu/packages/patches/glibc-hurd64-sgms-context.patch @@ -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 <[email protected]> +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: <[email protected]> + +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) |