1 /* clone_linux.c -- consistent wrapper around Linux clone syscall
2 
3    Copyright 2016 The Go Authors. All rights reserved.
4    Use of this source code is governed by a BSD-style
5    license that can be found in the LICENSE file.  */
6 
7 #include <errno.h>
8 #include <sys/syscall.h>
9 
10 #include "runtime.h"
11 
12 long rawClone (unsigned long flags, void *child_stack, void *ptid,
13 	       void *ctid, void *regs)
14   __asm__ (GOSYM_PREFIX "syscall.rawClone")
15   __attribute__ ((no_split_stack));
16 
17 long
rawClone(unsigned long flags,void * child_stack,void * ptid,void * ctid,void * regs)18 rawClone (unsigned long flags, void *child_stack, void *ptid, void *ctid, void *regs)
19 {
20 #if defined(__arc__) || defined(__aarch64__) || defined(__arm__) || defined(__mips__) || defined(__hppa__) || defined(__powerpc__) || defined(__score__) || defined(__i386__) || defined(__xtensa__)
21   // CLONE_BACKWARDS
22   return syscall(__NR_clone, flags, child_stack, ptid, regs, ctid);
23 #elif defined(__s390__) || defined(__cris__)
24   // CLONE_BACKWARDS2
25   return syscall(__NR_clone, child_stack, flags, ptid, ctid, regs);
26 #elif defined(__microblaze__)
27   // CLONE_BACKWARDS3
28   return syscall(__NR_clone, flags, child_stack, 0, ptid, ctid, regs);
29 #elif defined(__sparc__)
30 
31   /* SPARC has a unique return value convention:
32 
33      Parent -->  %o0 == child's  pid, %o1 == 0
34      Child  -->  %o0 == parent's pid, %o1 == 1
35 
36      Translate this to look like a normal clone.  */
37 
38 # if defined(__arch64__)
39 
40 #  define SYSCALL_STRING						\
41 	"ta	0x6d;"							\
42 	"bcc,pt	%%xcc, 1f;"						\
43 	" mov	0, %%g1;"						\
44 	"sub	%%g0, %%o0, %%o0;"					\
45 	"mov	1, %%g1;"						\
46 	"1:"
47 
48 #  define SYSCALL_CLOBBERS						\
49 	"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",			\
50 	"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",		\
51 	"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",		\
52 	"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",		\
53 	"f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",		\
54 	"f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",		\
55 	"cc", "memory"
56 
57 # else /* __arch64__ */
58 
59 #  define SYSCALL_STRING						\
60 	"ta	0x10;"							\
61 	"bcc	1f;"							\
62 	" mov	0, %%g1;"						\
63 	"sub	%%g0, %%o0, %%o0;"					\
64 	"mov	1, %%g1;"						\
65 	"1:"
66 
67 #  define SYSCALL_CLOBBERS						\
68 	"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",			\
69 	"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",		\
70 	"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",		\
71 	"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",		\
72 	"cc", "memory"
73 
74 # endif /* __arch64__ */
75 
76   register long o0 __asm__ ("o0") = (long)flags;
77   register long o1 __asm__ ("o1") = (long)child_stack;
78   register long o2 __asm__ ("o2") = (long)ptid;
79   register long o3 __asm__ ("o3") = (long)ctid;
80   register long o4 __asm__ ("o4") = (long)regs;
81   register long g1 __asm__ ("g1") = __NR_clone;
82 
83   __asm __volatile (SYSCALL_STRING :
84 		    "=r" (g1), "=r" (o0), "=r" (o1) :
85 		    "0" (g1), "1" (o0), "2" (o1),
86 		    "r" (o2), "r" (o3), "r" (o4) :
87 		    SYSCALL_CLOBBERS);
88 
89   if (__builtin_expect(g1 != 0, 0))
90     {
91       errno = -o0;
92       o0 = -1L;
93     }
94   else
95     o0 &= (o1 - 1);
96 
97   return o0;
98 
99 #else
100   return syscall(__NR_clone, flags, child_stack, ptid, ctid, regs);
101 #endif
102 }
103