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
      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  }