aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r--sysdeps/unix/sysv/linux/or1k/Versions14
-rw-r--r--sysdeps/unix/sysv/linux/or1k/getcontext-common.S88
-rw-r--r--sysdeps/unix/sysv/linux/or1k/getcontext.S69
-rw-r--r--sysdeps/unix/sysv/linux/or1k/libc.abilist4
-rw-r--r--sysdeps/unix/sysv/linux/or1k/makecontext.c49
-rw-r--r--sysdeps/unix/sysv/linux/or1k/setcontext-common.S120
-rw-r--r--sysdeps/unix/sysv/linux/or1k/setcontext.S102
-rw-r--r--sysdeps/unix/sysv/linux/or1k/swapcontext-common.S139
-rw-r--r--sysdeps/unix/sysv/linux/or1k/swapcontext.S109
-rw-r--r--sysdeps/unix/sysv/linux/or1k/sys/ucontext.h1
-rw-r--r--sysdeps/unix/sysv/linux/or1k/ucontext_i.sym3
11 files changed, 480 insertions, 218 deletions
diff --git a/sysdeps/unix/sysv/linux/or1k/Versions b/sysdeps/unix/sysv/linux/or1k/Versions
new file mode 100644
index 0000000..c1299de
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/or1k/Versions
@@ -0,0 +1,14 @@
+libc {
+ GLIBC_2.35 {
+ getcontext;
+ setcontext;
+ swapcontext;
+ makecontext;
+ }
+ GLIBC_2.40 {
+ getcontext;
+ setcontext;
+ swapcontext;
+ makecontext;
+ }
+}
diff --git a/sysdeps/unix/sysv/linux/or1k/getcontext-common.S b/sysdeps/unix/sysv/linux/or1k/getcontext-common.S
new file mode 100644
index 0000000..9187749
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/or1k/getcontext-common.S
@@ -0,0 +1,88 @@
+/* Save current context. OpenRISC common version.
+ 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/>. */
+
+/* This common getcontext template helps define different
+ implementations using control macros. Before including
+ this file in another file define the following:
+
+ __CONTEXT_FUNC_NAME
+ __CONTEXT_ENABLE_FPCSR
+ __CONTEXT_SIGMASK_OFFSET
+ */
+
+/* int getcontext (ucontext_t *ucp)
+
+ Returns 0 on success -1 and errno on failure.
+ */
+ .text
+ENTRY(__CONTEXT_FUNC_NAME)
+ /* Store r1, the stack pointer. */
+ l.sw (UCONTEXT_MCONTEXT + 1*4)(r3), r1
+ /* Store r2, the frame pointer. */
+ l.sw (UCONTEXT_MCONTEXT + 2*4)(r3), r2
+ /* Store r9, the link register. */
+ l.sw (UCONTEXT_MCONTEXT + 9*4)(r3), r9
+ /* Store r9 to reg[11] too, as we need two links for makecontext. */
+ l.sw (UCONTEXT_MCONTEXT + 11*4)(r3), r9
+ /* Store r10, the TLS register. */
+ l.sw (UCONTEXT_MCONTEXT + 10*4)(r3), r10
+ /* Store r14-r30 even, callee saved registers. */
+ l.sw (UCONTEXT_MCONTEXT + 14*4)(r3), r14
+ l.sw (UCONTEXT_MCONTEXT + 16*4)(r3), r16
+ l.sw (UCONTEXT_MCONTEXT + 18*4)(r3), r18
+ l.sw (UCONTEXT_MCONTEXT + 20*4)(r3), r20
+ l.sw (UCONTEXT_MCONTEXT + 22*4)(r3), r22
+ l.sw (UCONTEXT_MCONTEXT + 24*4)(r3), r24
+ l.sw (UCONTEXT_MCONTEXT + 26*4)(r3), r26
+ l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
+ l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+
+#ifdef __CONTEXT_ENABLE_FPCSR
+# ifdef __or1k_hard_float__
+ /* Store the floating point state. */
+ l.mfspr r4, r0, 20
+ l.sw (MCONTEXT_FPCSR)(r3), r4
+# else
+ /* Store zero to indicate default rounding as per softfloat. */
+ l.sw (MCONTEXT_FPCSR)(r3), r0
+# endif /* __or1k_hard_float__ */
+#endif /* __CONTEXT_ENABLE_FPCSR */
+
+ /* Get signal mask. */
+ /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ l.ori r6, r0, _NSIG8
+ l.addi r5, r3, __CONTEXT_SIGMASK_OFFSET
+ l.ori r4, r0, 0
+ l.ori r3, r0, SIG_BLOCK
+ l.ori r11, r0, SYS_ify (rt_sigprocmask)
+ /* Do the syscall. */
+ l.sys 1
+ l.nop
+
+ /* if -4096 < ret < 0 holds, it's an error */
+ l.sfgeui r11, 0xf001
+ l.bf 1f
+ l.nop
+
+ l.jr r9
+ l.ori r11, r0, 0
+
+1: l.j __syscall_error
+ l.ori r3, r11, 0
+
+END(__CONTEXT_FUNC_NAME)
diff --git a/sysdeps/unix/sysv/linux/or1k/getcontext.S b/sysdeps/unix/sysv/linux/or1k/getcontext.S
index a25b377..da69e69 100644
--- a/sysdeps/unix/sysv/linux/or1k/getcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/getcontext.S
@@ -17,56 +17,35 @@
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
+#include <shlib-compat.h>
#include "ucontext_i.h"
-/* int getcontext (ucontext_t *ucp)
+#define __CONTEXT_FUNC_NAME __getcontext
+#define __CONTEXT_ENABLE_FPCSR 1
+#define __CONTEXT_SIGMASK_OFFSET UCONTEXT_SIGMASK
- Returns 0 on success -1 and errno on failure.
- */
- .text
-ENTRY(__getcontext)
- /* Store r1, the stack pointer. */
- l.sw (UCONTEXT_MCONTEXT + 1*4)(r3), r1
- /* Store r2, the frame pointer. */
- l.sw (UCONTEXT_MCONTEXT + 2*4)(r3), r2
- /* Store r9, the link register. */
- l.sw (UCONTEXT_MCONTEXT + 9*4)(r3), r9
- /* Store r9 to reg[11] too, as we need two links for makecontext. */
- l.sw (UCONTEXT_MCONTEXT + 11*4)(r3), r9
- /* Store r10, the TLS register. */
- l.sw (UCONTEXT_MCONTEXT + 10*4)(r3), r10
- /* Store r14-r30 even, callee saved registers. */
- l.sw (UCONTEXT_MCONTEXT + 14*4)(r3), r14
- l.sw (UCONTEXT_MCONTEXT + 16*4)(r3), r16
- l.sw (UCONTEXT_MCONTEXT + 18*4)(r3), r18
- l.sw (UCONTEXT_MCONTEXT + 20*4)(r3), r20
- l.sw (UCONTEXT_MCONTEXT + 22*4)(r3), r22
- l.sw (UCONTEXT_MCONTEXT + 24*4)(r3), r24
- l.sw (UCONTEXT_MCONTEXT + 26*4)(r3), r26
- l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
- l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+#include "getcontext-common.S"
- /* Get signal mask. */
- /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
- l.ori r6, r0, _NSIG8
- l.addi r5, r3, UCONTEXT_SIGMASK
- l.ori r4, r0, 0
- l.ori r3, r0, SIG_BLOCK
- l.ori r11, r0, SYS_ify (rt_sigprocmask)
- /* Do the syscall. */
- l.sys 1
- l.nop
+versioned_symbol (libc, __getcontext, getcontext, GLIBC_2_40)
- /* if -4096 < ret < 0 holds, it's an error */
- l.sfgeui r11, 0xf001
- l.bf 1f
- l.nop
+#if SHLIB_COMPAT (libc, GLIBC_2_35, GLIBC_2_40)
- l.jr r9
- l.ori r11, r0, 0
+/* Define a compat version of getcontext for glibc's before the fpcsr
+ field was added to mcontext_t. The offset sigmask changed with this
+ introduction, the change was done because glibc's definition of
+ ucontext_t was initially defined incompatible with the Linux
+ definition of ucontext_t. We keep the compatability definition to
+ allow getcontext, setcontext and swapcontext to work in older
+ binaries. */
-1: l.j __syscall_error
- l.ori r3, r11, 0
+# undef __CONTEXT_FUNC_NAME
+# undef __CONTEXT_ENABLE_FPCSR
+# undef __CONTEXT_SIGMASK_OFFSET
+# define __CONTEXT_FUNC_NAME __getcontext_nofpcsr
+# define __CONTEXT_SIGMASK_OFFSET (UCONTEXT_SIGMASK - 4)
-END(__getcontext)
-weak_alias(__getcontext, getcontext)
+# include "getcontext-common.S"
+
+compat_symbol (libc, __getcontext_nofpcsr, getcontext, GLIBC_2_35)
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist
index c40c843..959e59e 100644
--- a/sysdeps/unix/sysv/linux/or1k/libc.abilist
+++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist
@@ -2255,3 +2255,7 @@ GLIBC_2.39 stdc_trailing_zeros_ui F
GLIBC_2.39 stdc_trailing_zeros_ul F
GLIBC_2.39 stdc_trailing_zeros_ull F
GLIBC_2.39 stdc_trailing_zeros_us F
+GLIBC_2.40 getcontext F
+GLIBC_2.40 makecontext F
+GLIBC_2.40 setcontext F
+GLIBC_2.40 swapcontext F
diff --git a/sysdeps/unix/sysv/linux/or1k/makecontext.c b/sysdeps/unix/sysv/linux/or1k/makecontext.c
index fa6626e..7e131ba 100644
--- a/sysdeps/unix/sysv/linux/or1k/makecontext.c
+++ b/sysdeps/unix/sysv/linux/or1k/makecontext.c
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <shlib-compat.h>
#include <sysdep.h>
#include <stdarg.h>
#include <stdint.h>
@@ -36,12 +37,11 @@
r1 : stack pointer
r2 : frame pointer, set to NULL
*/
-void
-__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+static void
+do_makecontext (ucontext_t *ucp, void (*startcontext) (void),
+ void (*func) (void), int argc, va_list ap)
{
- extern void __startcontext (void);
unsigned long int *sp;
- va_list ap;
int i;
sp = (unsigned long int *)
@@ -55,8 +55,8 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
/* Keep uc_link in r14. */
ucp->uc_mcontext.__gprs[14] = (uintptr_t) ucp->uc_link;
- /* Return address points to function __startcontext. */
- ucp->uc_mcontext.__gprs[9] = (uintptr_t) &__startcontext;
+ /* Return address points to function startcontext. */
+ ucp->uc_mcontext.__gprs[9] = (uintptr_t) startcontext;
/* Frame pointer is null. */
ucp->uc_mcontext.__gprs[2] = (uintptr_t) 0;
/* Restart in user-space starting at 'func'. */
@@ -64,14 +64,47 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
/* Set stack pointer. */
ucp->uc_mcontext.__gprs[1] = (uintptr_t) sp;
- va_start (ap, argc);
for (i = 0; i < argc; ++i)
if (i < 6)
ucp->uc_mcontext.__gprs[i + 3] = va_arg (ap, unsigned long int);
else
sp[i - 6] = va_arg (ap, unsigned long int);
+}
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ extern void __startcontext (void);
+ va_list ap;
+
+ va_start (ap, argc);
+ do_makecontext (ucp, &__startcontext, func, argc, ap);
va_end (ap);
}
-weak_alias (__makecontext, makecontext)
+versioned_symbol (libc, __makecontext, makecontext, GLIBC_2_40);
+
+#if SHLIB_COMPAT (libc, GLIBC_2_35, GLIBC_2_40)
+
+/* Define a compat version of makecontext for glibc's before the fpcsr
+ field was added to mcontext_t. The offset sigmask changed with this
+ introduction, the change was done because glibc's definition of
+ ucontext_t was initially defined incompatible with the Linux
+ definition of ucontext_t. We keep the compatability definition to
+ allow getcontext, setcontext and swapcontext to work in older
+ binaries. */
+
+void
+__makecontext_nofpcsr (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+ extern void __startcontext_nofpcsr (void);
+ va_list ap;
+
+ va_start (ap, argc);
+ do_makecontext (ucp, &__startcontext_nofpcsr, func, argc, ap);
+ va_end (ap);
+}
+
+compat_symbol (libc, __makecontext_nofpcsr, makecontext, GLIBC_2_35);
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/or1k/setcontext-common.S b/sysdeps/unix/sysv/linux/or1k/setcontext-common.S
new file mode 100644
index 0000000..8a4f147
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/or1k/setcontext-common.S
@@ -0,0 +1,120 @@
+/* Set current context. OpenRISC common version.
+ 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/>. */
+
+/* This common setcontext and startcontext template helps define
+ different implementations using control macros. Before including
+ this file in another file define the following:
+
+ __CONTEXT_FUNC_NAME
+ __CONTEXT_ENABLE_FPCSR
+ __CONTEXT_SIGMASK_OFFSET
+ __STARTCONTEXT_FUNC_NAME
+ */
+
+/* int setcontext (const ucontext_t *ucp) */
+ .text
+ENTRY(__CONTEXT_FUNC_NAME)
+ l.ori r30, r3, 0
+
+ /* Restore signal mask. */
+ /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
+ l.ori r6, r0, _NSIG8
+ l.ori r5, r0, 0
+ l.addi r4, r3, __CONTEXT_SIGMASK_OFFSET
+ l.ori r3, r0, SIG_SETMASK
+ l.ori r11, r0, SYS_ify (rt_sigprocmask)
+ /* Do the syscall. */
+ l.sys 1
+ l.nop
+
+ /* if -4096 < ret < 0 holds, it's an error */
+ l.sfgeui r11, 0xf001
+ l.bf 1f
+ l.nop
+#ifdef __CONTEXT_ENABLE_FPCSR
+# ifdef __or1k_hard_float__
+ /* Restore the floating point state. */
+ l.lwz r28, (MCONTEXT_FPCSR)(r30)
+ l.mtspr r0, r28, 20
+# endif /* __or1k_hard_float__ */
+#endif /* __CONTEXT_ENABLE_FPCSR */
+ /* Restore argument registers, for the makecontext case. */
+ l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
+ l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
+ l.lwz r5, (UCONTEXT_MCONTEXT + 5*4)(r30)
+ l.lwz r6, (UCONTEXT_MCONTEXT + 6*4)(r30)
+ l.lwz r7, (UCONTEXT_MCONTEXT + 7*4)(r30)
+ l.lwz r8, (UCONTEXT_MCONTEXT + 8*4)(r30)
+
+ /* Restore registers stored in getcontext. */
+ l.lwz r1, (UCONTEXT_MCONTEXT + 1*4)(r30)
+ l.lwz r2, (UCONTEXT_MCONTEXT + 2*4)(r30)
+ l.lwz r9, (UCONTEXT_MCONTEXT + 9*4)(r30)
+ l.lwz r10, (UCONTEXT_MCONTEXT + 10*4)(r30)
+ l.lwz r11, (UCONTEXT_MCONTEXT + 11*4)(r30)
+ /* Restore r14-r30 even, callee saved registers. */
+ l.lwz r14, (UCONTEXT_MCONTEXT + 14*4)(r30)
+ l.lwz r16, (UCONTEXT_MCONTEXT + 16*4)(r30)
+ l.lwz r18, (UCONTEXT_MCONTEXT + 18*4)(r30)
+ l.lwz r20, (UCONTEXT_MCONTEXT + 20*4)(r30)
+ l.lwz r22, (UCONTEXT_MCONTEXT + 22*4)(r30)
+ l.lwz r24, (UCONTEXT_MCONTEXT + 24*4)(r30)
+ l.lwz r26, (UCONTEXT_MCONTEXT + 26*4)(r30)
+ l.lwz r28, (UCONTEXT_MCONTEXT + 28*4)(r30)
+ l.lwz r30, (UCONTEXT_MCONTEXT + 30*4)(r30)
+
+ l.jr r11
+ l.ori r11, r0, 0
+
+1: l.j __syscall_error
+ l.ori r3, r11, 0
+
+END (__CONTEXT_FUNC_NAME)
+
+ /* We add a NOP here because when the unwinder is looking for the
+ enclosing function of the link register (r9) address FDE lookup will
+ use '$r9 - 1' finding setcontext which is wrong. This is because in
+ makecontext we have set r9 to the start of &__startcontext.
+
+ If this NOP did not exist the unwinder would repeatedly find
+ __setcontext's FDE in an infinite loop. Modifying/deleting the below
+ __startcontext's FDE has no help on this. */
+ l.nop
+
+ENTRY(__STARTCONTEXT_FUNC_NAME)
+
+ l.ori r3, r14, 0
+ l.sfeq r3, r0
+ /* If uc_link is not 0 resume there, otherwise exit. */
+ l.bnf __CONTEXT_FUNC_NAME
+ l.nop
+
+#ifdef SHARED
+ /* Obtain a pointer to .got in r16 */
+ l.jal 0x8
+ l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4)
+ l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0)
+ l.add r16, r16, r9
+ l.lwz r16, got(exit)(r16)
+ l.jr r16
+#else
+ l.j exit
+#endif
+ l.nop
+
+END(__STARTCONTEXT_FUNC_NAME)
diff --git a/sysdeps/unix/sysv/linux/or1k/setcontext.S b/sysdeps/unix/sysv/linux/or1k/setcontext.S
index d28a0ac..a49a5c5 100644
--- a/sysdeps/unix/sysv/linux/or1k/setcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/setcontext.S
@@ -16,93 +16,39 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <shlib-compat.h>
#include <sysdep.h>
#include "ucontext_i.h"
-/* int setcontext (const ucontext_t *ucp) */
- .text
-ENTRY(__setcontext)
- l.ori r30, r3, 0
+#define __CONTEXT_FUNC_NAME __setcontext
+#define __CONTEXT_ENABLE_FPCSR 1
+#define __CONTEXT_SIGMASK_OFFSET UCONTEXT_SIGMASK
+#define __STARTCONTEXT_FUNC_NAME __startcontext
- /* Restore signal mask. */
- /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
- l.ori r6, r0, _NSIG8
- l.ori r5, r0, 0
- l.addi r4, r3, UCONTEXT_SIGMASK
- l.ori r3, r0, SIG_SETMASK
- l.ori r11, r0, SYS_ify (rt_sigprocmask)
- /* Do the syscall. */
- l.sys 1
- l.nop
+#include "setcontext-common.S"
- /* if -4096 < ret < 0 holds, it's an error */
- l.sfgeui r11, 0xf001
- l.bf 1f
- l.nop
+versioned_symbol (libc, __setcontext, setcontext, GLIBC_2_40)
- /* Restore argument registers, for the makecontext case. */
- l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
- l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
- l.lwz r5, (UCONTEXT_MCONTEXT + 5*4)(r30)
- l.lwz r6, (UCONTEXT_MCONTEXT + 6*4)(r30)
- l.lwz r7, (UCONTEXT_MCONTEXT + 7*4)(r30)
- l.lwz r8, (UCONTEXT_MCONTEXT + 8*4)(r30)
+#if SHLIB_COMPAT (libc, GLIBC_2_35, GLIBC_2_40)
- /* Restore registers stored in getcontext. */
- l.lwz r1, (UCONTEXT_MCONTEXT + 1*4)(r30)
- l.lwz r2, (UCONTEXT_MCONTEXT + 2*4)(r30)
- l.lwz r9, (UCONTEXT_MCONTEXT + 9*4)(r30)
- l.lwz r10, (UCONTEXT_MCONTEXT + 10*4)(r30)
- l.lwz r11, (UCONTEXT_MCONTEXT + 11*4)(r30)
- /* Restore r14-r30 even, callee saved registers. */
- l.lwz r14, (UCONTEXT_MCONTEXT + 14*4)(r30)
- l.lwz r16, (UCONTEXT_MCONTEXT + 16*4)(r30)
- l.lwz r18, (UCONTEXT_MCONTEXT + 18*4)(r30)
- l.lwz r20, (UCONTEXT_MCONTEXT + 20*4)(r30)
- l.lwz r22, (UCONTEXT_MCONTEXT + 22*4)(r30)
- l.lwz r24, (UCONTEXT_MCONTEXT + 24*4)(r30)
- l.lwz r26, (UCONTEXT_MCONTEXT + 26*4)(r30)
- l.lwz r28, (UCONTEXT_MCONTEXT + 28*4)(r30)
- l.lwz r30, (UCONTEXT_MCONTEXT + 30*4)(r30)
+/* Define a compat version of setcontext for glibc's before the fpcsr
+ field was added to mcontext_t. The offset sigmask changed with this
+ introduction, the change was done because glibc's definition of
+ ucontext_t was initially defined incompatible with the Linux
+ definition of ucontext_t. We keep the compatability definition to
+ allow getcontext, setcontext and swapcontext to work in older
+ binaries. */
- l.jr r11
- l.ori r11, r0, 0
+# undef __CONTEXT_FUNC_NAME
+# undef __CONTEXT_ENABLE_FPCSR
+# undef __CONTEXT_SIGMASK_OFFSET
+# undef __STARTCONTEXT_FUNC_NAME
+# define __CONTEXT_FUNC_NAME __setcontext_nofpcsr
+# define __CONTEXT_SIGMASK_OFFSET (UCONTEXT_SIGMASK - 4)
+# define __STARTCONTEXT_FUNC_NAME __startcontext_nofpcsr
-1: l.j __syscall_error
- l.ori r3, r11, 0
+# include "setcontext-common.S"
-END (__setcontext)
-weak_alias (__setcontext, setcontext)
+compat_symbol (libc, __setcontext_nofpcsr, setcontext, GLIBC_2_35)
- /* We add a NOP here because when the unwinder is looking for the
- enclosing function of the link register (r9) address FDE lookup will
- use '$r9 - 1' finding setcontext which is wrong. This is because in
- makecontext we have set r9 to the start of &__startcontext.
-
- If this NOP did not exist the unwinder would repeatedly find
- __setcontext's FDE in an infinite loop. Modifying/deleting the below
- __startcontext's FDE has no help on this. */
- l.nop
-
-ENTRY(__startcontext)
-
- l.ori r3, r14, 0
- l.sfeq r3, r0
- /* If uc_link is not 0 resume there, otherwise exit. */
- l.bnf __setcontext
- l.nop
-
-#ifdef SHARED
- /* Obtain a pointer to .got in r16 */
- l.jal 0x8
- l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4)
- l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0)
- l.add r16, r16, r9
- l.lwz r16, got(exit)(r16)
- l.jr r16
-#else
- l.j exit
#endif
- l.nop
-
-END(__startcontext)
diff --git a/sysdeps/unix/sysv/linux/or1k/swapcontext-common.S b/sysdeps/unix/sysv/linux/or1k/swapcontext-common.S
new file mode 100644
index 0000000..b7e2d4c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/or1k/swapcontext-common.S
@@ -0,0 +1,139 @@
+/* Swap two contexts. OpenRISC version.
+ Copyright (C) 2022-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/>. */
+
+/* This common swapcontext template helps define different
+ implementations using control macros. Before including this file
+ in another file define the following:
+
+ __CONTEXT_FUNC_NAME
+ __CONTEXT_ENABLE_FPCSR
+ __CONTEXT_SIGMASK_OFFSET
+ */
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+ .text
+ENTRY(__CONTEXT_FUNC_NAME)
+
+ /* Same as getcontext. */
+ /* Store r1, the stack pointer. */
+ l.sw (UCONTEXT_MCONTEXT + 1*4)(r3), r1
+ /* Store r2, the frame pointer. */
+ l.sw (UCONTEXT_MCONTEXT + 2*4)(r3), r2
+ /* Store r9, the link register. */
+ l.sw (UCONTEXT_MCONTEXT + 9*4)(r3), r9
+ /* Store r9 to reg[11] too, as we need two links for makecontext. */
+ l.sw (UCONTEXT_MCONTEXT + 11*4)(r3), r9
+ /* Store r10, the TLS register. */
+ l.sw (UCONTEXT_MCONTEXT + 10*4)(r3), r10
+ /* Store r14-r30 even, callee saved registers. */
+ l.sw (UCONTEXT_MCONTEXT + 14*4)(r3), r14
+ l.sw (UCONTEXT_MCONTEXT + 16*4)(r3), r16
+ l.sw (UCONTEXT_MCONTEXT + 18*4)(r3), r18
+ l.sw (UCONTEXT_MCONTEXT + 20*4)(r3), r20
+ l.sw (UCONTEXT_MCONTEXT + 22*4)(r3), r22
+ l.sw (UCONTEXT_MCONTEXT + 24*4)(r3), r24
+ l.sw (UCONTEXT_MCONTEXT + 26*4)(r3), r26
+ l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
+ l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+
+#ifdef __CONTEXT_ENABLE_FPCSR
+# ifdef __or1k_hard_float__
+ /* Store the floating point state. */
+ l.mfspr r6, r0, 20
+ l.sw (MCONTEXT_FPCSR)(r3), r6
+# else
+ /* Store zero to indicate default rounding as per softfloat. */
+ l.sw (MCONTEXT_FPCSR)(r3), r0
+# endif /* __or1k_hard_float__ */
+#endif /* __CONTEXT_ENABLE_FPCSR */
+ /* Store ucp to non-argument syscall preserved register. */
+ l.ori r30, r4, 0
+
+ /* Get signal mask. */
+ /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
+ l.ori r6, r0, _NSIG8
+ l.addi r5, r3, __CONTEXT_SIGMASK_OFFSET
+ l.ori r4, r0, 0
+ l.ori r3, r0, SIG_BLOCK
+ l.ori r11, r0, SYS_ify (rt_sigprocmask)
+ /* Do the syscall. */
+ l.sys 1
+ l.nop
+
+ /* if -4096 < ret < 0 holds, it's an error */
+ l.sfgeui r11, 0xf001
+ l.bf 1f
+ l.nop
+
+ /* Same as setcontext. */
+
+ /* Restore signal mask. */
+ /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
+ l.ori r6, r0, _NSIG8
+ l.ori r5, r0, 0
+ l.addi r4, r30, __CONTEXT_SIGMASK_OFFSET
+ l.ori r3, r0, SIG_SETMASK
+ l.ori r11, r0, SYS_ify (rt_sigprocmask)
+ /* Do the syscall. */
+ l.sys 1
+ l.nop
+
+ /* if -4096 < ret < 0 holds, it's an error */
+ l.sfgeui r11, 0xf001
+ l.bf 1f
+ l.nop
+
+#ifdef __CONTEXT_ENABLE_FPCSR
+# ifdef __or1k_hard_float__
+ /* Restore the floating point state. */
+ l.lwz r28, (MCONTEXT_FPCSR)(r30)
+ l.mtspr r0, r28, 20
+# endif /* __or1k_hard_float__ */
+#endif /* __CONTEXT_ENABLE_FPCSR */
+
+ /* Restore argument registers, for the makecontext case. */
+ l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
+ l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
+ l.lwz r5, (UCONTEXT_MCONTEXT + 5*4)(r30)
+ l.lwz r6, (UCONTEXT_MCONTEXT + 6*4)(r30)
+ l.lwz r7, (UCONTEXT_MCONTEXT + 7*4)(r30)
+ l.lwz r8, (UCONTEXT_MCONTEXT + 8*4)(r30)
+
+ /* Restore registers stored in getcontext. */
+ l.lwz r1, (UCONTEXT_MCONTEXT + 1*4)(r30)
+ l.lwz r2, (UCONTEXT_MCONTEXT + 2*4)(r30)
+ l.lwz r9, (UCONTEXT_MCONTEXT + 9*4)(r30)
+ l.lwz r10, (UCONTEXT_MCONTEXT + 10*4)(r30)
+ l.lwz r11, (UCONTEXT_MCONTEXT + 11*4)(r30)
+ l.lwz r14, (UCONTEXT_MCONTEXT + 14*4)(r30)
+ l.lwz r16, (UCONTEXT_MCONTEXT + 16*4)(r30)
+ l.lwz r18, (UCONTEXT_MCONTEXT + 18*4)(r30)
+ l.lwz r20, (UCONTEXT_MCONTEXT + 20*4)(r30)
+ l.lwz r22, (UCONTEXT_MCONTEXT + 22*4)(r30)
+ l.lwz r24, (UCONTEXT_MCONTEXT + 24*4)(r30)
+ l.lwz r26, (UCONTEXT_MCONTEXT + 26*4)(r30)
+ l.lwz r28, (UCONTEXT_MCONTEXT + 28*4)(r30)
+ l.lwz r30, (UCONTEXT_MCONTEXT + 30*4)(r30)
+
+ l.jr r11
+ l.ori r11, r0, 0
+
+1: l.j __syscall_error
+ l.ori r3, r11, 0
+
+END (__CONTEXT_FUNC_NAME)
diff --git a/sysdeps/unix/sysv/linux/or1k/swapcontext.S b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
index d09651a..861c1e2 100644
--- a/sysdeps/unix/sysv/linux/or1k/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/or1k/swapcontext.S
@@ -16,101 +16,36 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <shlib-compat.h>
#include <sysdep.h>
#include "ucontext_i.h"
-/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
- .text
-ENTRY(__swapcontext)
+#define __CONTEXT_FUNC_NAME __swapcontext
+#define __CONTEXT_ENABLE_FPCSR 1
+#define __CONTEXT_SIGMASK_OFFSET UCONTEXT_SIGMASK
- /* Same as getcontext. */
- /* Store r1, the stack pointer. */
- l.sw (UCONTEXT_MCONTEXT + 1*4)(r3), r1
- /* Store r2, the frame pointer. */
- l.sw (UCONTEXT_MCONTEXT + 2*4)(r3), r2
- /* Store r9, the link register. */
- l.sw (UCONTEXT_MCONTEXT + 9*4)(r3), r9
- /* Store r9 to reg[11] too, as we need two links for makecontext. */
- l.sw (UCONTEXT_MCONTEXT + 11*4)(r3), r9
- /* Store r10, the TLS register. */
- l.sw (UCONTEXT_MCONTEXT + 10*4)(r3), r10
- /* Store r14-r30 even, callee saved registers. */
- l.sw (UCONTEXT_MCONTEXT + 14*4)(r3), r14
- l.sw (UCONTEXT_MCONTEXT + 16*4)(r3), r16
- l.sw (UCONTEXT_MCONTEXT + 18*4)(r3), r18
- l.sw (UCONTEXT_MCONTEXT + 20*4)(r3), r20
- l.sw (UCONTEXT_MCONTEXT + 22*4)(r3), r22
- l.sw (UCONTEXT_MCONTEXT + 24*4)(r3), r24
- l.sw (UCONTEXT_MCONTEXT + 26*4)(r3), r26
- l.sw (UCONTEXT_MCONTEXT + 28*4)(r3), r28
- l.sw (UCONTEXT_MCONTEXT + 30*4)(r3), r30
+#include "swapcontext-common.S"
- /* Store ucp to non-argument syscall preserved register. */
- l.ori r30, r4, 0
+versioned_symbol (libc, __swapcontext, swapcontext, GLIBC_2_40)
- /* Get signal mask. */
- /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
- l.ori r6, r0, _NSIG8
- l.addi r5, r3, UCONTEXT_SIGMASK
- l.ori r4, r0, 0
- l.ori r3, r0, SIG_BLOCK
- l.ori r11, r0, SYS_ify (rt_sigprocmask)
- /* Do the syscall. */
- l.sys 1
- l.nop
+#if SHLIB_COMPAT (libc, GLIBC_2_35, GLIBC_2_40)
- /* if -4096 < ret < 0 holds, it's an error */
- l.sfgeui r11, 0xf001
- l.bf 1f
- l.nop
+/* Define a compat version of swapcontext for glibc's before the fpcsr
+ field was added to mcontext_t. The offset sigmask changed with this
+ introduction, the change was done because glibc's definition of
+ ucontext_t was initially defined incompatible with the Linux
+ definition of ucontext_t. We keep the compatability definition to
+ allow getcontext, setcontext and swapcontext to work in older
+ binaries. */
- /* Same as setcontext. */
+# undef __CONTEXT_FUNC_NAME
+# undef __CONTEXT_ENABLE_FPCSR
+# undef __CONTEXT_SIGMASK_OFFSET
+# define __CONTEXT_FUNC_NAME __swapcontext_nofpcsr
+# define __CONTEXT_SIGMASK_OFFSET (UCONTEXT_SIGMASK - 4)
- /* Restore signal mask. */
- /* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
- l.ori r6, r0, _NSIG8
- l.ori r5, r0, 0
- l.addi r4, r30, UCONTEXT_SIGMASK
- l.ori r3, r0, SIG_SETMASK
- l.ori r11, r0, SYS_ify (rt_sigprocmask)
- /* Do the syscall. */
- l.sys 1
- l.nop
+# include "swapcontext-common.S"
- /* if -4096 < ret < 0 holds, it's an error */
- l.sfgeui r11, 0xf001
- l.bf 1f
- l.nop
+compat_symbol (libc, __swapcontext_nofpcsr, swapcontext, GLIBC_2_35)
- /* Restore argument registers, for the makecontext case. */
- l.lwz r3, (UCONTEXT_MCONTEXT + 3*4)(r30)
- l.lwz r4, (UCONTEXT_MCONTEXT + 4*4)(r30)
- l.lwz r5, (UCONTEXT_MCONTEXT + 5*4)(r30)
- l.lwz r6, (UCONTEXT_MCONTEXT + 6*4)(r30)
- l.lwz r7, (UCONTEXT_MCONTEXT + 7*4)(r30)
- l.lwz r8, (UCONTEXT_MCONTEXT + 8*4)(r30)
-
- /* Restore registers stored in getcontext. */
- l.lwz r1, (UCONTEXT_MCONTEXT + 1*4)(r30)
- l.lwz r2, (UCONTEXT_MCONTEXT + 2*4)(r30)
- l.lwz r9, (UCONTEXT_MCONTEXT + 9*4)(r30)
- l.lwz r10, (UCONTEXT_MCONTEXT + 10*4)(r30)
- l.lwz r11, (UCONTEXT_MCONTEXT + 11*4)(r30)
- l.lwz r14, (UCONTEXT_MCONTEXT + 14*4)(r30)
- l.lwz r16, (UCONTEXT_MCONTEXT + 16*4)(r30)
- l.lwz r18, (UCONTEXT_MCONTEXT + 18*4)(r30)
- l.lwz r20, (UCONTEXT_MCONTEXT + 20*4)(r30)
- l.lwz r22, (UCONTEXT_MCONTEXT + 22*4)(r30)
- l.lwz r24, (UCONTEXT_MCONTEXT + 24*4)(r30)
- l.lwz r26, (UCONTEXT_MCONTEXT + 26*4)(r30)
- l.lwz r28, (UCONTEXT_MCONTEXT + 28*4)(r30)
- l.lwz r30, (UCONTEXT_MCONTEXT + 30*4)(r30)
-
- l.jr r11
- l.ori r11, r0, 0
-
-1: l.j __syscall_error
- l.ori r3, r11, 0
-
-END (__swapcontext)
-weak_alias (__swapcontext, swapcontext)
+#endif
diff --git a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
index b17e919..1b42859 100644
--- a/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
+++ b/sysdeps/unix/sysv/linux/or1k/sys/ucontext.h
@@ -38,6 +38,7 @@ typedef struct
unsigned long int __gprs[__NGREG];
unsigned long int __pc;
unsigned long int __sr;
+ unsigned long int __fpcsr;
} mcontext_t;
/* Userlevel context. */
diff --git a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
index a8d4db0..45cd725 100644
--- a/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/or1k/ucontext_i.sym
@@ -13,6 +13,7 @@ _NSIG8 (_NSIG / 8)
-- Offsets of the fields in the ucontext_t structure.
#define ucontext(member) offsetof (ucontext_t, member)
#define stack(member) ucontext (uc_stack.member)
+#define mcontext(member) ucontext (uc_mcontext.member)
UCONTEXT_LINK ucontext (uc_link)
UCONTEXT_STACK ucontext (uc_stack)
@@ -23,4 +24,6 @@ STACK_SP stack (ss_sp)
STACK_SIZE stack (ss_size)
STACK_FLAGS stack (ss_flags)
+MCONTEXT_FPCSR mcontext (__fpcsr)
+
UCONTEXT_SIZE sizeof (ucontext_t)