summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/kvx/clone.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/kvx/clone.S')
-rw-r--r--libc/sysdeps/linux/kvx/clone.S100
1 files changed, 100 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/kvx/clone.S b/libc/sysdeps/linux/kvx/clone.S
new file mode 100644
index 000000000..71ea80a01
--- /dev/null
+++ b/libc/sysdeps/linux/kvx/clone.S
@@ -0,0 +1,100 @@
+/*
+ * This file is subject to the terms and conditions of the LGPL V2.1
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2018 Kalray Inc.
+ */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+
+/**
+ * Clone system call implementation for kvx
+ * int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+ * pid_t *ptid, struct user_desc *tls, pid_t *ctid);
+ * $r0 = fn
+ * $r1 = child_stack
+ * $r2 = flags
+ * $r3 = args
+ * $r4 = ptid
+ * $r5 = tls
+ * $r6 = ctid
+ *
+ * The kernel expects to find its arguments in the following order:
+ * sys_clone(unsigned long clone_flags, unsigned long newsp,
+ * int __user * parent_tidptr,
+ * int __user * child_tidptr,
+ * unsigned long tls)
+ *
+ * So we have to make a few modifications before calling
+ *
+ */
+
+ENTRY (__clone)
+ /* Check fn and stack to be non-null */
+ cb.deqz $r1? L(clone_einval_error)
+ /* Align child stack first */
+ andd $r1 = $r1, -32
+ ;;
+ cb.deqz $r0? L(clone_einval_error)
+ /* Prepare space for child arguments on stack and stay aligned */
+ addd $r1 = $r1, -32
+ ;;
+ /* Save fn ($r0) on child stack */
+ sd 0[$r1] = $r0
+ /* Set clone_flags */
+ copyd $r0 = $r2
+ ;;
+ /* Save args ($r3) on child stack */
+ sd 8[$r1] = $r3
+ /* Set parent_tidptr */
+ copyd $r2 = $r4
+ /* Set child_tidptr */
+ copyd $r3 = $r6
+ /* Set tls */
+ copyd $r4 = $r5
+ ;;
+ scall SYS_ify(clone)
+ ;;
+ /* If 0, then we are the child */
+ cb.deqz $r0, L(child_start)
+ ;;
+ /* Else we are the parent, and we need to check for errors */
+ cb.dltz $r0, L(clone_error)
+ ;;
+ /* No error ! Yeepa ! */
+ ret
+ ;;
+L(child_start):
+ /* get fn from stack */
+ ld $r1 = 0[$sp]
+ ;;
+ /* Get args from stack */
+ ld $r0 = 8[$sp]
+ addd $sp = $sp, 32
+ ;;
+ icall $r1
+ ;;
+ scall SYS_ify(exit)
+ ;;
+ /* We should never ever get here ! */
+ errop
+ ;;
+L(clone_einval_error):
+ make $r0 = -EINVAL
+ ;;
+L(clone_error):
+ /* goto __syscall_error but do not use call or $ra will be
+ * destroyed */
+ goto __syscall_error
+ ;;
+ /* We will not return here but to clone caller
+ * (stored in $ra) */
+ errop
+ ;;
+END(__clone)
+
+libc_hidden_def (__clone)
+weak_alias (__clone,clone)