Add the obsolescent SUSv3 family of user context manipulating functions
for kvx.

Signed-off-by: Julian Vetter <[email protected]>
---
 extra/Configs/Config.kvx              |   1 +
 libc/sysdeps/linux/kvx/Makefile.arch  |   2 +
 libc/sysdeps/linux/kvx/getcontext.S   |  81 ++++++++++++++++++++
 libc/sysdeps/linux/kvx/makecontext.c  |  53 +++++++++++++
 libc/sysdeps/linux/kvx/setcontext.S   | 106 ++++++++++++++++++++++++++
 libc/sysdeps/linux/kvx/swapcontext.S  |  63 +++++++++++++++
 libc/sysdeps/linux/kvx/sys/ucontext.h |   4 +-
 libc/sysdeps/linux/kvx/ucontext_i.sym |  28 +++++++
 8 files changed, 337 insertions(+), 1 deletion(-)
 create mode 100644 libc/sysdeps/linux/kvx/getcontext.S
 create mode 100644 libc/sysdeps/linux/kvx/makecontext.c
 create mode 100644 libc/sysdeps/linux/kvx/setcontext.S
 create mode 100644 libc/sysdeps/linux/kvx/swapcontext.S
 create mode 100644 libc/sysdeps/linux/kvx/ucontext_i.sym

diff --git a/extra/Configs/Config.kvx b/extra/Configs/Config.kvx
index 04df53c38..4d8152ab9 100644
--- a/extra/Configs/Config.kvx
+++ b/extra/Configs/Config.kvx
@@ -30,6 +30,7 @@ config FORCE_OPTIONS_FOR_ARCH
        default y
        select ARCH_LITTLE_ENDIAN
         select ARCH_HAS_MMU
+       select ARCH_HAS_UCONTEXT
        select UCLIBC_HAS_FPU
        select UCLIBC_HAS_FENV
        select UCLIBC_HAS_WCHAR
diff --git a/libc/sysdeps/linux/kvx/Makefile.arch 
b/libc/sysdeps/linux/kvx/Makefile.arch
index 3ad290915..18f2118f6 100644
--- a/libc/sysdeps/linux/kvx/Makefile.arch
+++ b/libc/sysdeps/linux/kvx/Makefile.arch
@@ -8,3 +8,5 @@
 CSRC-y := __syscall_error.c
 CSRC-$(UCLIBC_LINUX_SPECIFIC) += cachectl.c
 SSRC-y := setjmp.S bsd-setjmp.S bsd-_setjmp.S __longjmp.S clone.S vfork.S
+CSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += makecontext.c
+SSRC-$(UCLIBC_HAS_CONTEXT_FUNCS) += getcontext.S setcontext.S swapcontext.S
diff --git a/libc/sysdeps/linux/kvx/getcontext.S 
b/libc/sysdeps/linux/kvx/getcontext.S
new file mode 100644
index 000000000..9440f67ce
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/getcontext.S
@@ -0,0 +1,81 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2025 Kalray Inc.
+ * Author(s): Julian Vetter <[email protected]>
+ */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+       .text
+
+/*
+ * int getcontext (ucontext_t *ucp)
+ */
+ENTRY(__getcontext)
+       /* Save callee saved registers ($r14, $r18 - $r31)
+        * and some special registers */
+
+       /* Save the entire occtuple, although we only need $sp and $r14 */
+       so MCONTEXT_Q12[$r0] = $r12r13r14r15
+       get $r4 = $lc
+       ;;
+       /* Don't need to save veneer registers $r16 and $r17 */
+       sq (MCONTEXT_Q16 + 16)[$r0] = $r18r19
+       get $r5 = $le
+       ;;
+       so MCONTEXT_Q20[$r0] = $r20r21r22r23
+       get $r6 = $ls
+       ;;
+       so MCONTEXT_Q24[$r0] = $r24r25r26r27
+       get $r7 = $ra
+       ;;
+       so MCONTEXT_Q28[$r0] = $r28r29r30r31
+       get $r8 = $cs
+       ;;
+       so MCONTEXT_LC_LE_LS_RA[$r0] = $r4r5r6r7
+       /* Save ucp and $ra in callee saved registers because below we need to
+        * do a call to sigprocmask and afterwards we need to restore $ra. */
+       copyd $r20 = $r0
+       copyd $r21 = $r7
+       ;;
+       sd MCONTEXT_CS_SPC[$r0] = $r8
+
+       /* Prepare call to sigprocmask */
+       make $r0 = SIG_BLOCK
+       make $r1 = 0
+       ;;
+       /* $r20 points to the ucontext */
+       addd $r2 = $r20, UCONTEXT_SIGMASK
+       /* Already set the return value for when this is called in the context
+        * of swapcontext. Because when this context returns it should look
+        * like as if swapcontext returned with 0. */
+       sd MCONTEXT_Q0[$r20] = $r1
+       ;;
+       /* sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
+       call sigprocmask
+       ;;
+       /* Restore $ra to point to the caller of this function. So,
+        * __getcontext will return with -1 (set by __syscall_error) and an
+        * appropriate errno */
+       set $ra = $r21
+       ;;
+       /* Check return value of sigprocmask */
+       cb.deqz $r0 ? 1f
+       ;;
+       goto __syscall_error
+       ;;
+1:
+       /* Restore used callee saved registers */
+       lq $r20r21 = MCONTEXT_Q20[$r20]
+       ;;
+       /* Set return value */
+       make $r0 = 0
+       ret
+       ;;
+END(__getcontext)
+weak_alias(__getcontext, getcontext)
diff --git a/libc/sysdeps/linux/kvx/makecontext.c 
b/libc/sysdeps/linux/kvx/makecontext.c
new file mode 100644
index 000000000..a52eded9f
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/makecontext.c
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2025 Kalray Inc.
+ * Author(s): Julian Vetter <[email protected]>
+ */
+
+#include <stdarg.h>
+#include <ucontext.h>
+
+
+/* Number of arguments that go in registers.   */
+#define NREG_ARGS 12
+
+/* Take a context previously prepared via getcontext() and set to
+        call func() with the given int only args.      */
+void
+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...)
+{
+       extern void __startcontext (void);
+       unsigned long *funcstack;
+       va_list vl;
+       unsigned long *regptr;
+       unsigned int reg;
+
+       /* Start at the top of stack.   */
+       funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + 
ucp->uc_stack.ss_size);
+       funcstack -= argc < NREG_ARGS ? 0 : argc - NREG_ARGS;
+       funcstack = (unsigned long *) (((uintptr_t) funcstack & -32L));
+
+       ucp->uc_mcontext.sc_regs.r12 = (unsigned long) funcstack;
+       /* Use $r20 and $r21 to pass some infos to __startcontext */
+       ucp->uc_mcontext.sc_regs.r20 = (unsigned long) ucp->uc_link;
+       ucp->uc_mcontext.sc_regs.r21 = (unsigned long) func;
+       ucp->uc_mcontext.sc_regs.ra = (unsigned long) __startcontext;
+
+       va_start (vl, argc);
+
+       /* The first twelve arguments go into registers.        */
+       regptr = &(ucp->uc_mcontext.sc_regs.r0);
+
+       for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++)
+               *regptr++ = va_arg (vl, unsigned long);
+
+       /* And the remainder on the stack.      */
+       for (; reg < argc; reg++)
+               *funcstack++ = va_arg (vl, unsigned long);
+
+       va_end (vl);
+}
+weak_alias (__makecontext, makecontext)
diff --git a/libc/sysdeps/linux/kvx/setcontext.S 
b/libc/sysdeps/linux/kvx/setcontext.S
new file mode 100644
index 000000000..7b91d21d9
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/setcontext.S
@@ -0,0 +1,106 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2025 Kalray Inc.
+ * Author(s): Julian Vetter <[email protected]>
+ */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+       .text
+
+/*
+ * int setcontext (const ucontext_t *ucp)
+ */
+ENTRY(__setcontext)
+       get $r16 = $ra
+       addd $r12 = $r12, -32
+       ;;
+       /* Save ucp pointer  and $ra on the stack because we can't trash
+        * any callee saved registers in case __setcontext returns */
+       sd 16[$r12] = $r16
+       ;;
+       sd 24[$r12] = $r0
+       ;;
+       /* Bring back the signal status. */
+       make $r0 = SIG_SETMASK
+       addd $r1 = $r0, UCONTEXT_SIGMASK
+       make $r2 = 0
+       ;;
+       /* sigprocmask(SIG_SETMASK, &(ucontext->uc_sigmask), NULL) */
+       call sigprocmask
+       ;;
+       /* Check return value of sigprocmask */
+       cb.deqz $r0 ? 1f
+       /* Normally __setcontext does not return. But in case of an error it
+        * returns with -1 and an appropriate errno */
+       ld $r16 = 16[$r12]
+       ;;
+       set $ra = $r16
+       addd $r12 = $r12, 32
+       ;;
+       goto __syscall_error
+       ;;
+1:
+       /* Get back the ucp pointer */
+       ld $r16 = 24[$r12]
+       /* Reset the stack pointer (we can trash $ra here, because we will
+        * never return to after __setcontext from this point onwards) */
+       addd $r12 = $r12, 32
+       ;;
+       /* Restore callee saved registers */
+       lq $r18r19 = (MCONTEXT_Q16 + 16)[$r16]
+       ;;
+       /* Setup $r20, $r21 for the __startcontext to work */
+       lo $r20r21r22r23 = MCONTEXT_Q20[$r16]
+       ;;
+       lo $r24r25r26r27 = MCONTEXT_Q24[$r16]
+       ;;
+       lo $r28r29r30r31 = MCONTEXT_Q28[$r16]
+       ;;
+       /* Restore special registers */
+       lo $r40r41r42r43 = MCONTEXT_LC_LE_LS_RA[$r16]
+       ;;
+       /* Now load argument registers */
+       lo $r0r1r2r3 = MCONTEXT_Q0[$r16]
+       set $lc = $r40
+       ;;
+       lo $r4r5r6r7 = MCONTEXT_Q4[$r16]
+       set $le = $r41
+       ;;
+       lo $r8r9r10r11 = MCONTEXT_Q8[$r16]
+       set $ls = $r42
+       ;;
+       /* Restore $sp */
+       ld $r12 = MCONTEXT_Q12[$r16]
+       /* Restore $ra which points to the $ra set by __getcontext or
+        * to__startcontext if __makecontext was called in between */
+       set $ra = $r43
+       ;;
+       ld $r40 = MCONTEXT_CS_SPC[$r16]
+       ;;
+       ld $r14 = (MCONTEXT_Q12 + 16)[$r16]
+       set $cs = $r40
+       ;;
+       ret
+       ;;
+END(setcontext)
+weak_alias(__setcontext, setcontext)
+
+ENTRY(__startcontext)
+       icall $r21
+       ;;
+       copyd $r0 = $r20
+       /* Check if the new context is 0 if so just call _exit */
+       cb.deqz $r20 ? 1f
+       ;;
+       goto __setcontext
+       ;;
+       /* This should never be reached otherwise kill the thread */
+1:     goto _exit
+       ;;
+END(__startcontext)
diff --git a/libc/sysdeps/linux/kvx/swapcontext.S 
b/libc/sysdeps/linux/kvx/swapcontext.S
new file mode 100644
index 000000000..1abb6a8a8
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/swapcontext.S
@@ -0,0 +1,63 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive for
+ * more details.
+ *
+ * Copyright (C) 2025 Kalray Inc.
+ * Author(s): Julian Vetter <[email protected]>
+ */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+       .text
+
+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
+
+ENTRY(swapcontext)
+       /* Make space on the stack to save all caller saved registers */
+       get $r16 = $ra
+       addd $r12 = $r12, -32
+       ;;
+
+       /* Save $ra on the stack */
+       sd (24)[$r12] = $r16
+       ;;
+       /* Save the arguments of swapcontext on the stack */
+       sq (8)[$r12] = $r0r1
+       ;;
+       call __getcontext
+       ;;
+
+       /* Save the return value of __getcontext in $r17 */
+       copyd $r17 = $r0
+
+       /* Restore $ra */
+       ld $r16 = (24)[$r12]
+       ;;
+       /* Restore arguments */
+       lq $r0r1 = (8)[$r12]
+       /* Readjust the stack pointer */
+       addd $r12 = $r12, 32
+       /* Also restore $ra */
+       set $ra = $r16
+       ;;
+
+       /* Exit if getcontext() failed */
+       cb.deqz $r17 ? 1f
+       ;;
+
+       /* Set the return value set by __syscall_error in __getcontext */
+       copyd $r0 = $r17
+       ret
+       ;;
+1:
+       /* Store the $sp and $ra in the context to be saved */
+       sd (MCONTEXT_Q12)[$r0] = $r12
+       ;;
+       sd (MCONTEXT_LC_LE_LS_RA + 24)[$r0] = $r16
+       copyd $r0 = $r1
+       goto __setcontext
+       ;;
+END(swapcontext)
diff --git a/libc/sysdeps/linux/kvx/sys/ucontext.h 
b/libc/sysdeps/linux/kvx/sys/ucontext.h
index a97b83cad..6a30a09e2 100644
--- a/libc/sysdeps/linux/kvx/sys/ucontext.h
+++ b/libc/sysdeps/linux/kvx/sys/ucontext.h
@@ -17,11 +17,13 @@
 /* Type for general register.  */
 typedef unsigned long greg_t;
 
+typedef struct sigcontext mcontext_t;
+
 typedef struct ucontext {
        unsigned long     uc_flags;
        struct ucontext  *uc_link;
        stack_t           uc_stack;
-       struct sigcontext uc_mcontext;
+       mcontext_t        uc_mcontext;
        sigset_t          uc_sigmask;   /* mask last for extensibility */
 } ucontext_t;
 
diff --git a/libc/sysdeps/linux/kvx/ucontext_i.sym 
b/libc/sysdeps/linux/kvx/ucontext_i.sym
new file mode 100644
index 000000000..d2b565332
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/ucontext_i.sym
@@ -0,0 +1,28 @@
+#include <inttypes.h>
+#include <signal.h>
+#include <stddef.h>
+#include <sys/ucontext.h>
+
+SIG_BLOCK
+SIG_SETMASK
+
+-- Offsets of the fields in the ucontext_t structure.
+#define ucontext(member)       offsetof (ucontext_t, member)
+#define mcontext(member)       ucontext (uc_mcontext.member)
+
+UCONTEXT_FLAGS                 ucontext (uc_flags)
+UCONTEXT_LINK                  ucontext (uc_link)
+UCONTEXT_STACK                 ucontext (uc_stack)
+UCONTEXT_MCONTEXT              ucontext (uc_mcontext)
+UCONTEXT_SIGMASK               ucontext (uc_sigmask)
+
+MCONTEXT_Q0                    mcontext (sc_regs.r0)
+MCONTEXT_Q4                    mcontext (sc_regs.r4)
+MCONTEXT_Q8                    mcontext (sc_regs.r8)
+MCONTEXT_Q12                   mcontext (sc_regs.r12)
+MCONTEXT_Q16                   mcontext (sc_regs.r16)
+MCONTEXT_Q20                   mcontext (sc_regs.r20)
+MCONTEXT_Q24                   mcontext (sc_regs.r24)
+MCONTEXT_Q28                   mcontext (sc_regs.r28)
+MCONTEXT_LC_LE_LS_RA           mcontext (sc_regs.lc)
+MCONTEXT_CS_SPC                        mcontext (sc_regs.cs)
-- 
2.34.1

_______________________________________________
devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to