Mark Wielaard f88b36
commit e31d72da6cb415d0856ad53dac78e307548cd831
Mark Wielaard f88b36
Author: philippe <philippe@a5019735-40e9-0310-863c-91ae7b9d1cf9>
Mark Wielaard f88b36
Date:   Sun Dec 11 21:39:23 2016 +0000
Mark Wielaard f88b36
Mark Wielaard f88b36
    Fix 342040 Valgrind mishandles clone with CLONE_VFORK | CLONE_VM that clones to a different stack
Mark Wielaard f88b36
    Fix 373192 Calling posix_spawn in glibc 2.24 completely broken
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    Functionally, this patch just does the following 2 changes to the
Mark Wielaard f88b36
    fork clone handling:
Mark Wielaard f88b36
    * It does not mask anymore CLONE_VFORK :
Mark Wielaard f88b36
      The only effect of this flag is to suspend the parent, waiting for
Mark Wielaard f88b36
      the child to either exit or execve.
Mark Wielaard f88b36
      If some applications depends on this synchronisation, better keep it,
Mark Wielaard f88b36
      as it will not harm to suspend the parent valgrind waiting for the
Mark Wielaard f88b36
      child valgrind to exit or execve.
Mark Wielaard f88b36
    * In case the guest calls the clone syscall providing a non zero client stack,
Mark Wielaard f88b36
      set the child guest SP after the syscall, before executing guest instructions.
Mark Wielaard f88b36
      Not setting the guest stack ptr was the source of the problem reported
Mark Wielaard f88b36
      in the bugs.
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    This also adds a test case  none/tests/linux/clonev.
Mark Wielaard f88b36
    Before this patch, test gives a SEGV, which is fixed by the patch.
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    The patch is however a lot bigger : this fix was touching some (mostly
Mark Wielaard f88b36
    identical/duplicated) code in all the linux platforms.
Mark Wielaard f88b36
    So, the clone/fork code has been factorised as much as possible.
Mark Wielaard f88b36
    This removes about 1700 lines of code.
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    This has been tested on:
Mark Wielaard f88b36
    * amd64
Mark Wielaard f88b36
    * x86
Mark Wielaard f88b36
    * ppc64 be and le
Mark Wielaard f88b36
    * ppc32
Mark Wielaard f88b36
    * arm64
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    This has been compiled on but *not really tested* on:
Mark Wielaard f88b36
    * mips64 (not too clear how to properly build and run valgrind on gcc22)
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    It has *not* been compiled and *not* tested on:
Mark Wielaard f88b36
    * arm
Mark Wielaard f88b36
    * mips32
Mark Wielaard f88b36
    * tilegx
Mark Wielaard f88b36
    * darwin   (normally, no impact)
Mark Wielaard f88b36
    * solaris  (normally, no impact)
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    The changes are relatively mechanical, so it is not impossible that
Mark Wielaard f88b36
    it will compile and work out of the box on these platforms.
Mark Wielaard f88b36
    Otherwise, questions welcome.
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    A few points of interest:
Mark Wielaard f88b36
    * Some platforms did have a typedef void vki_modify_ldt_t,
Mark Wielaard f88b36
      and some platforms had no definition for this type at all.
Mark Wielaard f88b36
      To make it easier to factorise, for such platforms, the following has
Mark Wielaard f88b36
      been used:
Mark Wielaard f88b36
         typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
        When the sizeof vki_modify_ldt_t is > 1, then the arg syscall is checked.
Mark Wielaard f88b36
      This is somewhat a hack, but was simplifying the factorisation.
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    * for mips32/mips64 and tilegx, there is a strange unconditional assignment
Mark Wielaard f88b36
      of 0 to a register (guest_r2 on mips, guest_r0 on tilegx).
Mark Wielaard f88b36
      Unclear what this is, in particular because this is assigned whatever
Mark Wielaard f88b36
      the result of the syscall (success or not).
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    
Mark Wielaard f88b36
    git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16186 a5019735-40e9-0310-863c-91ae7b9d1cf9
Mark Wielaard f88b36
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard f88b36
index 38fcd7b..06ea7cd 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
Mark Wielaard f88b36
@@ -39,12 +39,10 @@ extern Word ML_(start_thread_NORETURN) ( void* arg );
Mark Wielaard f88b36
 extern Addr ML_(allocstack)            ( ThreadId tid );
Mark Wielaard f88b36
 extern void ML_(call_on_new_stack_0_1) ( Addr stack, Addr retaddr,
Mark Wielaard f88b36
 			                 void (*f)(Word), Word arg1 );
Mark Wielaard f88b36
-extern SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
-                                   Int* parent_tidptr, Int* child_tidptr );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 // Linux-specific (but non-arch-specific) syscalls
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+DECL_TEMPLATE(linux, sys_clone)
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_mount);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_oldumount);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_umount);
Mark Wielaard f88b36
@@ -61,6 +59,10 @@ DECL_TEMPLATE(linux, sys_vmsplice);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_readahead);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_move_pages);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+// clone is similar enough between linux variants to have a generic
Mark Wielaard f88b36
+// version, but which will call an extern defined in syswrap-<platform>-linux.c
Mark Wielaard f88b36
+DECL_TEMPLATE(linux, sys_clone);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
 // POSIX, but various sub-cases differ between Linux and Darwin.
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_fcntl);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_fcntl64);
Mark Wielaard f88b36
@@ -368,7 +370,83 @@ DECL_TEMPLATE(linux, sys_getpeername);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_socketpair);
Mark Wielaard f88b36
 DECL_TEMPLATE(linux, sys_kcmp);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-#endif   // __PRIV_SYSWRAP_LINUX_H
Mark Wielaard f88b36
+// Some arch specific functions called from syswrap-linux.c
Mark Wielaard f88b36
+extern Int do_syscall_clone_x86_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                        void* stack, 
Mark Wielaard f88b36
+                                        Int   flags, 
Mark Wielaard f88b36
+                                        void* arg,
Mark Wielaard f88b36
+                                        Int*  child_tid, 
Mark Wielaard f88b36
+                                        Int*  parent_tid, 
Mark Wielaard f88b36
+                                        void* tls_ptr);
Mark Wielaard f88b36
+extern SysRes ML_(x86_sys_set_thread_area) ( ThreadId tid,
Mark Wielaard f88b36
+                                             vki_modify_ldt_t* info );
Mark Wielaard f88b36
+extern void ML_(x86_setup_LDT_GDT) ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
+                                     /*IN*/  ThreadArchState *parent );
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+extern Long do_syscall_clone_amd64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                           void* stack, 
Mark Wielaard f88b36
+                                           Long  flags, 
Mark Wielaard f88b36
+                                           void* arg,
Mark Wielaard f88b36
+                                           Int* child_tid, 
Mark Wielaard f88b36
+                                           Int* parent_tid, 
Mark Wielaard f88b36
+                                           void* tls_ptr);
Mark Wielaard f88b36
+extern ULong do_syscall_clone_ppc32_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                            void* stack, 
Mark Wielaard f88b36
+                                            Int   flags, 
Mark Wielaard f88b36
+                                            void* arg,
Mark Wielaard f88b36
+                                            Int*  child_tid, 
Mark Wielaard f88b36
+                                            Int*  parent_tid, 
Mark Wielaard f88b36
+                                            void* tls_ptr);
Mark Wielaard f88b36
+extern ULong do_syscall_clone_ppc64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                            void* stack, 
Mark Wielaard f88b36
+                                            Int   flags, 
Mark Wielaard f88b36
+                                            void* arg,
Mark Wielaard f88b36
+                                            Int*  child_tid, 
Mark Wielaard f88b36
+                                            Int*  parent_tid, 
Mark Wielaard f88b36
+                                            void* tls_ptr );
Mark Wielaard f88b36
+extern ULong do_syscall_clone_s390x_linux ( void  *stack,
Mark Wielaard f88b36
+                                            ULong flags,
Mark Wielaard f88b36
+                                            Int   *parent_tid,
Mark Wielaard f88b36
+                                            Int   *child_tid,
Mark Wielaard f88b36
+                                            void*  tls_ptr,
Mark Wielaard f88b36
+                                            Word (*fn)(void *),
Mark Wielaard f88b36
+                                            void  *arg);
Mark Wielaard f88b36
+extern Long do_syscall_clone_arm64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                           void* stack, 
Mark Wielaard f88b36
+                                           Long  flags, 
Mark Wielaard f88b36
+                                           void* arg,
Mark Wielaard f88b36
+                                           Int*  child_tid,
Mark Wielaard f88b36
+                                           Int*  parent_tid,
Mark Wielaard f88b36
+                                           void* tls_ptr );
Mark Wielaard f88b36
+extern ULong do_syscall_clone_arm_linux   ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                            void* stack, 
Mark Wielaard f88b36
+                                            Int   flags, 
Mark Wielaard f88b36
+                                            void* arg,
Mark Wielaard f88b36
+                                            Int*  child_tid,
Mark Wielaard f88b36
+                                            Int*  parent_tid,
Mark Wielaard f88b36
+                                            void* tls_ptr );
Mark Wielaard f88b36
+extern ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *),  /* a0 - 4 */
Mark Wielaard f88b36
+                                             void* stack,          /* a1 - 5 */
Mark Wielaard f88b36
+                                             Int   flags,          /* a2 - 6 */
Mark Wielaard f88b36
+                                             void* arg,            /* a3 - 7 */
Mark Wielaard f88b36
+                                             Int*  parent_tid,     /* a4 - 8 */
Mark Wielaard f88b36
+                                             void* tls_ptr,        /* a5 - 9 */
Mark Wielaard f88b36
+                                             Int*  child_tid );    /* a6 - 10 */
Mark Wielaard f88b36
+extern UInt do_syscall_clone_mips_linux ( Word (*fn) (void *), //a0     0    32
Mark Wielaard f88b36
+                                          void* stack,         //a1     4    36
Mark Wielaard f88b36
+                                          Int   flags,         //a2     8    40
Mark Wielaard f88b36
+                                          void* arg,           //a3     12   44
Mark Wielaard f88b36
+                                          Int*  child_tid,     //stack  16   48
Mark Wielaard f88b36
+                                          Int*  parent_tid,    //stack  20   52
Mark Wielaard f88b36
+                                          void* tls_ptr);      //stack  24   56
Mark Wielaard f88b36
+extern Long do_syscall_clone_tilegx_linux ( Word (*fn) (void *),  //r0
Mark Wielaard f88b36
+                                            void* stack,          //r1
Mark Wielaard f88b36
+                                            Long  flags,          //r2
Mark Wielaard f88b36
+                                            void* arg,            //r3
Mark Wielaard f88b36
+                                            Long* child_tid,      //r4
Mark Wielaard f88b36
+                                            Long* parent_tid,     //r5
Mark Wielaard f88b36
+                                            void* tls_ptr );      //r6
Mark Wielaard f88b36
+ #endif   // __PRIV_SYSWRAP_LINUX_H
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 /*--------------------------------------------------------------------*/
Mark Wielaard f88b36
 /*--- end                                                          ---*/
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard f88b36
index 08e9a93..3fe9938 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
Mark Wielaard f88b36
@@ -130,14 +130,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-Long do_syscall_clone_amd64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                    void* stack, 
Mark Wielaard f88b36
-                                    Long  flags, 
Mark Wielaard f88b36
-                                    void* arg,
Mark Wielaard f88b36
-                                    Long* child_tid, 
Mark Wielaard f88b36
-                                    Long* parent_tid, 
Mark Wielaard f88b36
-                                    vki_modify_ldt_t * );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n"
Mark Wielaard f88b36
 ".globl do_syscall_clone_amd64_linux\n"
Mark Wielaard f88b36
@@ -183,126 +176,6 @@ asm(
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-// forward declaration
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState*, ThreadArchState* );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for EIP, and a separate stack
Mark Wielaard f88b36
-   for ESP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         ULong flags, Addr rsp, 
Mark Wielaard f88b36
-                         Long* parent_tidptr, 
Mark Wielaard f88b36
-                         Long* child_tidptr, 
Mark Wielaard f88b36
-                         Addr tlsaddr )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   static const Bool debug = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   Long         rax;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL rsp for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's rsp.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   ctst->arch.vex.guest_RAX = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (rsp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_RSP = rsp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (rsp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  If the clone
Mark Wielaard f88b36
-      fails, we'll send out a ll_exit notification for it at the out:
Mark Wielaard f88b36
-      label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (debug)
Mark Wielaard f88b36
-	 VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
Mark Wielaard f88b36
-      ctst->arch.vex.guest_FS_CONST = tlsaddr;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   rax = do_syscall_clone_amd64_linux(
Mark Wielaard f88b36
-            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-            child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-         );
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_amd64_linux)( rax );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    More thread stuff
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -311,16 +184,6 @@ void VG_(cleanup_thread) ( ThreadArchState *arch )
Mark Wielaard f88b36
 {  
Mark Wielaard f88b36
 }  
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void setup_child ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
-                   /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
-{  
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}  
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for AMD64/Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -333,7 +196,6 @@ void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
    the right thing to do is to make these wrappers 'static' since they
Mark Wielaard f88b36
    aren't visible outside this file, but that requires even more macro
Mark Wielaard f88b36
    magic. */
Mark Wielaard f88b36
-DECL_TEMPLATE(amd64_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE(amd64_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(amd64_linux, sys_arch_prctl);
Mark Wielaard f88b36
 DECL_TEMPLATE(amd64_linux, sys_ptrace);
Mark Wielaard f88b36
@@ -342,108 +204,6 @@ DECL_TEMPLATE(amd64_linux, sys_mmap);
Mark Wielaard f88b36
 DECL_TEMPLATE(amd64_linux, sys_syscall184);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   ULong cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ2(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *, child_stack);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA3("clone", int *, parent_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA4("clone", vki_modify_ldt_t *, tlsinfo);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_READ("clone(tlsinfo)", ARG4, sizeof(vki_modify_ldt_t));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t), 
Mark Wielaard f88b36
-                                             VKI_PROT_READ)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA5("clone", int *, child_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int), VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,          /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,    /* child ESP */
Mark Wielaard f88b36
-                  (Long *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Long *)ARG4,  /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG5));  /* set_tls */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG4));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                   "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                   "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                   "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                   " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                   " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG4, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_rt_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    /* This isn't really a syscall at all - it's a misuse of the
Mark Wielaard f88b36
@@ -761,7 +521,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
    LINX_(__NR_setsockopt,        sys_setsockopt),     // 54
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    LINXY(__NR_getsockopt,        sys_getsockopt),     // 55 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),          // 56 
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),          // 56 
Mark Wielaard f88b36
    GENX_(__NR_fork,              sys_fork),           // 57 
Mark Wielaard f88b36
    GENX_(__NR_vfork,             sys_fork),           // 58 treat as fork
Mark Wielaard f88b36
    GENX_(__NR_execve,            sys_execve),         // 59 
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c
Mark Wielaard f88b36
index 3bbd109..b417428 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-arm-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
Mark Wielaard f88b36
@@ -102,14 +102,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-ULong do_syscall_clone_arm_linux   ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                     void* stack, 
Mark Wielaard f88b36
-                                     Int   flags, 
Mark Wielaard f88b36
-                                     void* arg,
Mark Wielaard f88b36
-                                     Int*  child_tid,
Mark Wielaard f88b36
-                                     Int*  parent_tid,
Mark Wielaard f88b36
-                                     void* tls );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n"
Mark Wielaard f88b36
 ".globl do_syscall_clone_arm_linux\n"
Mark Wielaard f88b36
@@ -148,104 +141,8 @@ asm(
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 // forward declarations
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState*, ThreadArchState* );
Mark Wielaard f88b36
-static void assign_guest_tls(ThreadId ctid, Addr tlsptr);
Mark Wielaard f88b36
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
Mark Wielaard f88b36
             
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         UInt flags, Addr sp, 
Mark Wielaard f88b36
-                         Int *parent_tidptr, 
Mark Wielaard f88b36
-                         Int *child_tidptr, 
Mark Wielaard f88b36
-                         Addr child_tls)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   ThreadId ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   UInt r0;
Mark Wielaard f88b36
-   UWord *stack;
Mark Wielaard f88b36
-   SysRes res;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if(stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->arch.vex.guest_R0 = 0;
Mark Wielaard f88b36
-   if(sp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_R13 = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      /* Just assign the tls pointer in the guest TPIDRURO. */
Mark Wielaard f88b36
-      assign_guest_tls(ctid, child_tls);
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-    
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   r0 = do_syscall_clone_arm_linux(
Mark Wielaard f88b36
-      ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-      child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-   );
Mark Wielaard f88b36
-   //VG_(printf)("AFTER SYSCALL, %x and %x  CHILD: %d PARENT: %d\n",child_tidptr, parent_tidptr,*child_tidptr,*parent_tidptr);
Mark Wielaard f88b36
-    
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_arm_linux)( r0 );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    More thread stuff
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -256,26 +153,13 @@ void VG_(cleanup_thread) ( ThreadArchState* arch )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
 }  
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
-                   /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-static void assign_guest_tls(ThreadId tid, Addr tlsptr)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   VG_(threads)[tid].arch.vex.guest_TPIDRURO = tlsptr;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* Assigns tlsptr to the guest TPIDRURO.
Mark Wielaard f88b36
    If needed for the specific hardware, really executes
Mark Wielaard f88b36
    the set_tls syscall.
Mark Wielaard f88b36
 */
Mark Wielaard f88b36
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
-   assign_guest_tls(tid, tlsptr);
Mark Wielaard f88b36
+   VG_(threads)[tid].arch.vex.guest_TPIDRURO = tlsptr;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    if (KernelVariantiS(KernelVariant_android_no_hw_tls,
Mark Wielaard f88b36
                        VG_(clo_kernel_variant))) {
Mark Wielaard f88b36
@@ -333,7 +217,6 @@ DECL_TEMPLATE(arm_linux, sys_stat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_lstat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_fstatat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_fstat64);
Mark Wielaard f88b36
-DECL_TEMPLATE(arm_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm_linux, sys_sigsuspend);
Mark Wielaard f88b36
@@ -424,100 +307,6 @@ POST(sys_fstat64)
Mark Wielaard f88b36
    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-    UInt cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ5(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *, child_stack,
Mark Wielaard f88b36
-                 int *, parent_tidptr,
Mark Wielaard f88b36
-                 void *, child_tls,
Mark Wielaard f88b36
-                 int *, child_tidptr);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t), 
Mark Wielaard f88b36
-                                             VKI_PROT_READ)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,         /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,   /* child ESP */
Mark Wielaard f88b36
-                  (Int *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int *)ARG5,  /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG4)); /* set_tls */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG5));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
Mark Wielaard f88b36
@@ -901,7 +690,7 @@ static SyscallTableEntry syscall_main_table[] = {
Mark Wielaard f88b36
    GENX_(__NR_fsync,             sys_fsync),          // 118
Mark Wielaard f88b36
    PLAX_(__NR_sigreturn,         sys_sigreturn),      // 119 ?/Linux
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),          // 120
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),          // 120
Mark Wielaard f88b36
 //zz    //   (__NR_setdomainname,     sys_setdomainname),  // 121 */*(?)
Mark Wielaard f88b36
    GENXY(__NR_uname,             sys_newuname),       // 122
Mark Wielaard f88b36
 //   PLAX_(__NR_modify_ldt,        sys_modify_ldt),     // 123
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard f88b36
index 6b579e8..1be6629 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
Mark Wielaard f88b36
@@ -138,14 +138,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-Long do_syscall_clone_arm64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                    void* child_stack, 
Mark Wielaard f88b36
-                                    Long  flags, 
Mark Wielaard f88b36
-                                    void* arg,
Mark Wielaard f88b36
-                                    Int*  child_tid,
Mark Wielaard f88b36
-                                    Int*  parent_tid,
Mark Wielaard f88b36
-                                    void* tls );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n"
Mark Wielaard f88b36
 ".globl do_syscall_clone_arm64_linux\n"
Mark Wielaard f88b36
@@ -196,121 +189,6 @@ static void setup_child ( ThreadArchState*, ThreadArchState* );
Mark Wielaard f88b36
 static void assign_guest_tls(ThreadId ctid, Addr tlsptr);
Mark Wielaard f88b36
 //ZZ static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
Mark Wielaard f88b36
             
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         ULong flags,
Mark Wielaard f88b36
-                         Addr  child_xsp, 
Mark Wielaard f88b36
-                         Int*  parent_tidptr, 
Mark Wielaard f88b36
-                         Int*  child_tidptr, 
Mark Wielaard f88b36
-                         Addr  child_tls )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   ULong        x0;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL xsp for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's xsp.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   ctst->arch.vex.guest_X0 = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (child_xsp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_XSP = child_xsp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack)(child_xsp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  If the clone
Mark Wielaard f88b36
-      fails, we'll send out a ll_exit notification for it at the out:
Mark Wielaard f88b36
-      label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      /* Just assign the tls pointer in the guest TPIDR_EL0. */
Mark Wielaard f88b36
-      assign_guest_tls(ctid, child_tls);
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-    
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   x0 = do_syscall_clone_arm64_linux(
Mark Wielaard f88b36
-      ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-      child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-   );
Mark Wielaard f88b36
-    
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_arm64_linux)( x0 );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    More thread stuff
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -397,7 +275,6 @@ DECL_TEMPLATE(arm64_linux, sys_mmap);
Mark Wielaard f88b36
 //ZZ DECL_TEMPLATE(arm_linux, sys_lstat64);
Mark Wielaard f88b36
 //ZZ DECL_TEMPLATE(arm_linux, sys_fstatat64);
Mark Wielaard f88b36
 //ZZ DECL_TEMPLATE(arm_linux, sys_fstat64);
Mark Wielaard f88b36
-DECL_TEMPLATE(arm64_linux, sys_clone);
Mark Wielaard f88b36
 //ZZ DECL_TEMPLATE(arm_linux, sys_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(arm64_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 //ZZ DECL_TEMPLATE(arm_linux, sys_sigsuspend);
Mark Wielaard f88b36
@@ -512,110 +389,6 @@ PRE(sys_mmap)
Mark Wielaard f88b36
 //ZZ    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
Mark Wielaard f88b36
 //ZZ }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-/* Aarch64 seems to use CONFIG_CLONE_BACKWARDS in the kernel.  See:
Mark Wielaard f88b36
-      http://dev.gentoo.org/~vapier/aarch64/linux-3.12.6.config
Mark Wielaard f88b36
-      http://people.redhat.com/wcohen/aarch64/aarch64_config
Mark Wielaard f88b36
-   from linux-3.10.5/kernel/fork.c 
Mark Wielaard f88b36
-    #ifdef CONFIG_CLONE_BACKWARDS
Mark Wielaard f88b36
-    SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
Mark Wielaard f88b36
-                     int __user *, parent_tidptr,
Mark Wielaard f88b36
-                     int, tls_val,
Mark Wielaard f88b36
-                     int __user *, child_tidptr)
Mark Wielaard f88b36
-*/
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ5(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *, child_stack,
Mark Wielaard f88b36
-                 int *, parent_tidptr,
Mark Wielaard f88b36
-                 void *, child_tls,
Mark Wielaard f88b36
-                 int *, child_tidptr);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-//ZZ    if (ARG1 & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-//ZZ       PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
Mark Wielaard f88b36
-//ZZ       if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t), 
Mark Wielaard f88b36
-//ZZ                                              VKI_PROT_READ)) {
Mark Wielaard f88b36
-//ZZ          SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-//ZZ          return;
Mark Wielaard f88b36
-//ZZ       }
Mark Wielaard f88b36
-//ZZ    }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,         /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,   /* child SP */
Mark Wielaard f88b36
-                  (Int*)ARG3,   /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int*)ARG5,   /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG4)); /* tls_val */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,     /* flags */
Mark Wielaard f88b36
-                       (Int*)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int*)ARG5));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 //ZZ PRE(sys_sigreturn)
Mark Wielaard f88b36
 //ZZ {
Mark Wielaard f88b36
 //ZZ    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
Mark Wielaard f88b36
@@ -1072,7 +845,7 @@ static SyscallTableEntry syscall_main_table[] = {
Mark Wielaard f88b36
    LINX_(__NR_add_key,           sys_add_key),           // 217
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    LINXY(__NR_keyctl,            sys_keyctl),            // 219
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),             // 220
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),             // 220
Mark Wielaard f88b36
    GENX_(__NR_execve,            sys_execve),            // 221
Mark Wielaard f88b36
    PLAX_(__NR_mmap,              sys_mmap),              // 222
Mark Wielaard f88b36
    PLAX_(__NR_fadvise64,         sys_fadvise64),         // 223
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard f88b36
index b3ffdb1..aa00a5f 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-linux.c
Mark Wielaard f88b36
@@ -93,9 +93,8 @@ static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
Mark Wielaard f88b36
    VG_TRACK(pre_thread_first_insn, tid);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    tst->os_state.lwpid = VG_(gettid)();
Mark Wielaard f88b36
-   /* Set the threadgroup for real.  This overwrites the provisional
Mark Wielaard f88b36
-      value set in do_clone() syswrap-*-linux.c.  See comments in
Mark Wielaard f88b36
-      do_clone for background, also #226116. */
Mark Wielaard f88b36
+   /* Set the threadgroup for real.  This overwrites the provisional value set
Mark Wielaard f88b36
+      in do_clone().  See comments in do_clone for background, also #226116. */
Mark Wielaard f88b36
    tst->os_state.threadgroup = VG_(getpid)();
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    /* Thread created with all signals blocked; scheduler will set the
Mark Wielaard f88b36
@@ -430,17 +429,327 @@ void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
Mark Wielaard f88b36
    vg_assert(0);
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+/* Clone a new thread. Note that in the clone syscalls, we hard-code
Mark Wielaard f88b36
+   tlsaddr argument as NULL : the guest TLS is emulated via guest
Mark Wielaard f88b36
+   registers, and Valgrind itself has no thread local storage. */
Mark Wielaard f88b36
+static SysRes clone_new_thread ( Word (*fn)(void *), 
Mark Wielaard f88b36
+                                 void* stack, 
Mark Wielaard f88b36
+                                 Word  flags, 
Mark Wielaard f88b36
+                                 ThreadState* ctst,
Mark Wielaard f88b36
+                                 Int* child_tidptr, 
Mark Wielaard f88b36
+                                 Int* parent_tidptr)
Mark Wielaard f88b36
+{
Mark Wielaard f88b36
+   SysRes res;
Mark Wielaard f88b36
+   /* Note that in all the below, we make sys_clone appear to have returned
Mark Wielaard f88b36
+      Success(0) in the child, by assigning the relevant child guest
Mark Wielaard f88b36
+      register(s) just before the clone syscall. */
Mark Wielaard f88b36
+#if defined(VGP_x86_linux)
Mark Wielaard f88b36
+   Int          eax;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_EAX = 0;
Mark Wielaard f88b36
+   eax = do_syscall_clone_x86_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_x86_linux)( eax );
Mark Wielaard f88b36
+#elif defined(VGP_amd64_linux)
Mark Wielaard f88b36
+   Long         rax;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_RAX = 0;
Mark Wielaard f88b36
+   rax = do_syscall_clone_amd64_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_amd64_linux)( rax );
Mark Wielaard f88b36
+#elif defined(VGP_ppc32_linux)
Mark Wielaard f88b36
+   ULong        word64;
Mark Wielaard f88b36
+   UInt old_cr = LibVEX_GuestPPC32_get_CR( &ctst->arch.vex );
Mark Wielaard f88b36
+   /* %r3 = 0 */
Mark Wielaard f88b36
+   ctst->arch.vex.guest_GPR3 = 0;
Mark Wielaard f88b36
+   /* %cr0.so = 0 */
Mark Wielaard f88b36
+   LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
Mark Wielaard f88b36
+   word64 = do_syscall_clone_ppc32_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   /* High half word64 is syscall return value.  Low half is
Mark Wielaard f88b36
+      the entire CR, from which we need to extract CR0.SO. */
Mark Wielaard f88b36
+   /* VG_(printf)("word64 = 0x%llx\n", word64); */
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_ppc32_linux)(/*val*/(UInt)(word64 >> 32), 
Mark Wielaard f88b36
+                                    /*errflag*/ (((UInt)word64) >> 28) & 1);
Mark Wielaard f88b36
+#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
Mark Wielaard f88b36
+   ULong        word64;
Mark Wielaard f88b36
+   UInt old_cr = LibVEX_GuestPPC64_get_CR( &ctst->arch.vex );
Mark Wielaard f88b36
+   /* %r3 = 0 */
Mark Wielaard f88b36
+   ctst->arch.vex.guest_GPR3 = 0;
Mark Wielaard f88b36
+   /* %cr0.so = 0 */
Mark Wielaard f88b36
+   LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
Mark Wielaard f88b36
+   word64 = do_syscall_clone_ppc64_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   /* Low half word64 is syscall return value.  Hi half is
Mark Wielaard f88b36
+      the entire CR, from which we need to extract CR0.SO. */
Mark Wielaard f88b36
+   /* VG_(printf)("word64 = 0x%llx\n", word64); */
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_ppc64_linux)
Mark Wielaard f88b36
+      (/*val*/(UInt)(word64 & 0xFFFFFFFFULL), 
Mark Wielaard f88b36
+       /*errflag*/ (UInt)((word64 >> (32+28)) & 1));
Mark Wielaard f88b36
+#elif defined(VGP_s390x_linux)
Mark Wielaard f88b36
+   ULong        r2;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
+   r2 = do_syscall_clone_s390x_linux
Mark Wielaard f88b36
+      (stack, flags, parent_tidptr, child_tidptr, NULL,
Mark Wielaard f88b36
+       ML_(start_thread_NORETURN), ctst);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_s390x_linux)( r2 );
Mark Wielaard f88b36
+#elif defined(VGP_arm64_linux)
Mark Wielaard f88b36
+   ULong        x0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_X0 = 0;
Mark Wielaard f88b36
+   x0 = do_syscall_clone_arm64_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_arm64_linux)( x0 );
Mark Wielaard f88b36
+#elif defined(VGP_arm_linux)
Mark Wielaard f88b36
+   UInt r0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_R0 = 0;
Mark Wielaard f88b36
+   r0 = do_syscall_clone_arm_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_arm_linux)( r0 );
Mark Wielaard f88b36
+#elif defined(VGP_mips64_linux)
Mark Wielaard f88b36
+   UInt ret = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r7 = 0;
Mark Wielaard f88b36
+   ret = do_syscall_clone_mips64_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       parent_tidptr, NULL, child_tidptr);
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0);
Mark Wielaard f88b36
+#elif defined(VGP_mips32_linux)
Mark Wielaard f88b36
+   UInt ret = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r7 = 0;
Mark Wielaard f88b36
+   ret = do_syscall_clone_mips_linux
Mark Wielaard f88b36
+      (ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   /* High half word64 is syscall return value.  Low half is
Mark Wielaard f88b36
+      the entire CR, from which we need to extract CR0.SO. */ 
Mark Wielaard f88b36
+   res = VG_ (mk_SysRes_mips32_linux) (/*val */ ret, 0, /*errflag */ 0);
Mark Wielaard f88b36
+#elif defined(VGP_tilegx_linux)
Mark Wielaard f88b36
+   Long ret = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r0 = 0;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r3 = 0;
Mark Wielaard f88b36
+   ret = do_syscall_clone_tilegx_linux
Mark Wielaard f88b36
+      (ML_ (start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+       child_tidptr, parent_tidptr, NULL);
Mark Wielaard f88b36
+   /* High half word64 is syscall return value. */
Mark Wielaard f88b36
+   res = VG_(mk_SysRes_tilegx_linux) (/*val */ ret);
Mark Wielaard f88b36
+#else
Mark Wielaard f88b36
+# error Unknown platform
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+   return res;
Mark Wielaard f88b36
+}
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+static void setup_child ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
+                          /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
+{  
Mark Wielaard f88b36
+   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
+   child->vex = parent->vex;
Mark Wielaard f88b36
+   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
+   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-/* Do a clone which is really a fork() */
Mark Wielaard f88b36
-SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
-                            Int* parent_tidptr, Int* child_tidptr )
Mark Wielaard f88b36
+#if defined(VGP_x86_linux)
Mark Wielaard f88b36
+   extern void ML_(x86_setup_LDT_GDT) ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
+                                        /*IN*/  ThreadArchState *parent );
Mark Wielaard f88b36
+   ML_(x86_setup_LDT_GDT)(child, parent);
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+}
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+static SysRes setup_child_tls (ThreadId ctid, Addr tlsaddr)
Mark Wielaard f88b36
+{
Mark Wielaard f88b36
+   static const Bool debug = False;
Mark Wielaard f88b36
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
+   // res is succesful by default, overriden if a real syscall is needed/done.
Mark Wielaard f88b36
+   SysRes res = VG_(mk_SysRes_Success)(0);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (debug)
Mark Wielaard f88b36
+      VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+#if defined(VGP_x86_linux)
Mark Wielaard f88b36
+   vki_modify_ldt_t* tlsinfo = (vki_modify_ldt_t*)tlsaddr;
Mark Wielaard f88b36
+   if (debug)
Mark Wielaard f88b36
+      VG_(printf)("clone child has SETTLS: tls info at %p: idx=%u "
Mark Wielaard f88b36
+                  "base=%#lx limit=%x; esp=%#x fs=%x gs=%x\n",
Mark Wielaard f88b36
+                  tlsinfo, tlsinfo->entry_number, 
Mark Wielaard f88b36
+                  tlsinfo->base_addr, tlsinfo->limit,
Mark Wielaard f88b36
+                  ctst->arch.vex.guest_ESP,
Mark Wielaard f88b36
+                  ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
Mark Wielaard f88b36
+   res = ML_(x86_sys_set_thread_area)(ctid, tlsinfo);
Mark Wielaard f88b36
+#elif defined(VGP_amd64_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_FS_CONST = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_ppc32_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_GPR2 = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_GPR13 = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_s390x_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_a0 = (UInt) (tlsaddr >> 32);
Mark Wielaard f88b36
+   ctst->arch.vex.guest_a1 = (UInt) tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_arm64_linux)
Mark Wielaard f88b36
+   /* Just assign the tls pointer in the guest TPIDR_EL0. */
Mark Wielaard f88b36
+   ctst->arch.vex.guest_TPIDR_EL0 = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_arm_linux)
Mark Wielaard f88b36
+   /* Just assign the tls pointer in the guest TPIDRURO. */
Mark Wielaard f88b36
+   ctst->arch.vex.guest_TPIDRURO = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_mips64_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_ULR = tlsaddr;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r27 = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_mips32_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_ULR = tlsaddr;
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r27 = tlsaddr;
Mark Wielaard f88b36
+#elif defined(VGP_tilegx_linux)
Mark Wielaard f88b36
+   ctst->arch.vex.guest_r53 = tlsaddr;
Mark Wielaard f88b36
+#else
Mark Wielaard f88b36
+# error Unknown platform
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+   return res;
Mark Wielaard f88b36
+} 
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+/* 
Mark Wielaard f88b36
+   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
+   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
+   but using the scheduler entrypoint for EIP, and a separate stack
Mark Wielaard f88b36
+   for ESP.
Mark Wielaard f88b36
+ */
Mark Wielaard f88b36
+static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
+                         UWord flags, Addr sp, 
Mark Wielaard f88b36
+                         Int* parent_tidptr, 
Mark Wielaard f88b36
+                         Int* child_tidptr, 
Mark Wielaard f88b36
+                         Addr tlsaddr)
Mark Wielaard f88b36
+{
Mark Wielaard f88b36
+   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
+   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
+   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
+   UWord*       stack;
Mark Wielaard f88b36
+   SysRes       res;
Mark Wielaard f88b36
+   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
+   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
+   if (stack == NULL) {
Mark Wielaard f88b36
+      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
+      goto out;
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* Copy register state
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
+      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
+      don't need to worry about it.
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
+      child gets 0.
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+      If the clone call specifies a NULL sp for the new thread, then
Mark Wielaard f88b36
+      it actually gets a copy of the parent's sp.
Mark Wielaard f88b36
+   */
Mark Wielaard f88b36
+   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (sp != 0)
Mark Wielaard f88b36
+      VG_(set_SP)(ctid, sp);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* inherit signal mask */
Mark Wielaard f88b36
+   ctst->sig_mask     = ptst->sig_mask;
Mark Wielaard f88b36
+   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
+      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
+      after the child is created but before it sets its
Mark Wielaard f88b36
+      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
+      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
+      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
+      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
+      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
+      See #226116. */
Mark Wielaard f88b36
+   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
+   
Mark Wielaard f88b36
+   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
+      know that this thread has come into existence.  We cannot defer
Mark Wielaard f88b36
+      it beyond this point because setup_tls, just below,
Mark Wielaard f88b36
+      causes checks to assert by making references to the new ThreadId
Mark Wielaard f88b36
+      if we don't state the new thread exists prior to that point.
Mark Wielaard f88b36
+      If the clone fails, we'll send out a ll_exit notification for it
Mark Wielaard f88b36
+      at the out: label below, to clean up. */
Mark Wielaard f88b36
+   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
+   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
+      res = setup_child_tls(ctid, tlsaddr);
Mark Wielaard f88b36
+      if (sr_isError(res))
Mark Wielaard f88b36
+	 goto out;
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* start the thread with everything blocked */
Mark Wielaard f88b36
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* Create the new thread */
Mark Wielaard f88b36
+   res = clone_new_thread ( ML_(start_thread_NORETURN), stack, flags, ctst,
Mark Wielaard f88b36
+                            child_tidptr, parent_tidptr);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+  out:
Mark Wielaard f88b36
+   if (sr_isError(res)) {
Mark Wielaard f88b36
+      /* clone failed */
Mark Wielaard f88b36
+      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
+      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
+      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
+      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+#if defined(VGP_mips64_linux) || defined(VGP_mips32_linux)
Mark Wielaard f88b36
+   // ??? why do we set unconditionally r2 to 0, even when error out ???
Mark Wielaard f88b36
+   ptst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
+#elif defined(VGP_tilegx_linux)
Mark Wielaard f88b36
+   // ??? why do we set unconditionally r0 to 0, even when error out ???
Mark Wielaard f88b36
+   ptst->arch.vex.guest_r0 = 0;
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   return res;
Mark Wielaard f88b36
+}
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+/* Do a clone which is really a fork().
Mark Wielaard f88b36
+   ML_(do_fork_clone) uses the clone syscall to fork a child process.
Mark Wielaard f88b36
+   Note that this should not be called for a thread creation.
Mark Wielaard f88b36
+   Also, some flags combinations are not supported, and such combinations
Mark Wielaard f88b36
+   are handled either by masking the non supported flags or by asserting.
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   The CLONE_VFORK flag is accepted, as this just tells that the parent is
Mark Wielaard f88b36
+   suspended till the child exits or calls execve. We better keep this flag,
Mark Wielaard f88b36
+   just in case the guests parent/client code depends on this synchronisation.
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   We cannot keep the flag CLONE_VM, as Valgrind will do whatever host
Mark Wielaard f88b36
+   instructions in the child process, that will mess up the parent host
Mark Wielaard f88b36
+   memory. So, we hope for the best and assumes that the guest application does
Mark Wielaard f88b36
+   not (really) depends on sharing the memory between parent and child in the
Mark Wielaard f88b36
+   interval between clone and exits/execve.
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   If child_sp != 0, the child (guest) sp will be set to child_sp just after the
Mark Wielaard f88b36
+   clone syscall, before child guest instructions are executed. */
Mark Wielaard f88b36
+static SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
+                                   Int* parent_tidptr, Int* child_tidptr,
Mark Wielaard f88b36
+                                   Addr child_sp)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    vki_sigset_t fork_saved_mask;
Mark Wielaard f88b36
    vki_sigset_t mask;
Mark Wielaard f88b36
    SysRes       res;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM 
Mark Wielaard f88b36
-                | VKI_CLONE_FILES | VKI_CLONE_VFORK))
Mark Wielaard f88b36
+                | VKI_CLONE_FILES))
Mark Wielaard f88b36
       return VG_(mk_SysRes_Error)( VKI_EINVAL );
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    /* Block all signals during fork, so that we can fix things up in
Mark Wielaard f88b36
@@ -476,6 +785,8 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    if (!sr_isError(res) && sr_Res(res) == 0) {
Mark Wielaard f88b36
       /* child */
Mark Wielaard f88b36
+      if (child_sp != 0)
Mark Wielaard f88b36
+          VG_(set_SP)(tid, child_sp);
Mark Wielaard f88b36
       VG_(do_atfork_child)(tid);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
       /* restore signal mask */
Mark Wielaard f88b36
@@ -508,7 +819,6 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
    return res;
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for arch-generic, Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -519,6 +829,157 @@ SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
Mark Wielaard f88b36
 #error Unknown endianness
Mark Wielaard f88b36
 #endif
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+PRE(sys_clone)
Mark Wielaard f88b36
+{
Mark Wielaard f88b36
+   UInt cloneflags;
Mark Wielaard f88b36
+   Bool badarg = False;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+// Order of arguments differs between platforms.
Mark Wielaard f88b36
+#if defined(VGP_x86_linux) \
Mark Wielaard f88b36
+    || defined(VGP_ppc32_linux) \
Mark Wielaard f88b36
+    || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)	\
Mark Wielaard f88b36
+    || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
Mark Wielaard f88b36
+    || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
Mark Wielaard f88b36
+#define ARG_CHILD_TIDPTR ARG5
Mark Wielaard f88b36
+#define PRA_CHILD_TIDPTR PRA5
Mark Wielaard f88b36
+#define ARG_TLS          ARG4
Mark Wielaard f88b36
+#define PRA_TLS          PRA4
Mark Wielaard f88b36
+#elif defined(VGP_amd64_linux) || defined(VGP_tilegx_linux) \
Mark Wielaard f88b36
+    || defined(VGP_s390x_linux)
Mark Wielaard f88b36
+#define ARG_CHILD_TIDPTR ARG4
Mark Wielaard f88b36
+#define PRA_CHILD_TIDPTR PRA4
Mark Wielaard f88b36
+#define ARG_TLS          ARG5
Mark Wielaard f88b36
+#define PRA_TLS          PRA5
Mark Wielaard f88b36
+#else
Mark Wielaard f88b36
+# error Unknown platform
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+// And s390x is even more special, and inverts flags and child stack args
Mark Wielaard f88b36
+#if defined(VGP_s390x_linux)
Mark Wielaard f88b36
+#define ARG_FLAGS       ARG2
Mark Wielaard f88b36
+#define PRA_FLAGS       PRA2
Mark Wielaard f88b36
+#define ARG_CHILD_STACK ARG1
Mark Wielaard f88b36
+#define PRA_CHILD_STACK PRA1
Mark Wielaard f88b36
+#else
Mark Wielaard f88b36
+#define ARG_FLAGS       ARG1
Mark Wielaard f88b36
+#define PRA_FLAGS       PRA1
Mark Wielaard f88b36
+#define ARG_CHILD_STACK ARG2
Mark Wielaard f88b36
+#define PRA_CHILD_STACK PRA2
Mark Wielaard f88b36
+#endif
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
+      PRA_FLAGS("clone", unsigned long, flags);
Mark Wielaard f88b36
+      PRA_CHILD_STACK("clone",  void *, child_stack);
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (ARG_FLAGS & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
+      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
+         PRA3("clone", int *, parent_tidptr);
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
+      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
+                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
+         badarg = True;
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+   if (ARG_FLAGS & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
+      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
+         PRA_TLS("clone", vki_modify_ldt_t *, tlsinfo);
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+      /* Not very clear what is vki_modify_ldt_t: for many platforms, it is a
Mark Wielaard f88b36
+         dummy type (that we define as a char). We only dereference/check the
Mark Wielaard f88b36
+         ARG_TLS pointer if the type looks like a real type, i.e. sizeof > 1. */
Mark Wielaard f88b36
+      if (sizeof(vki_modify_ldt_t) > 1) {
Mark Wielaard f88b36
+         PRE_MEM_READ("clone(tlsinfo)", ARG_TLS, sizeof(vki_modify_ldt_t));
Mark Wielaard f88b36
+         if (!VG_(am_is_valid_for_client)(ARG_TLS, sizeof(vki_modify_ldt_t), 
Mark Wielaard f88b36
+                                          VKI_PROT_READ)) {
Mark Wielaard f88b36
+            badarg = True;
Mark Wielaard f88b36
+         }
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+   if (ARG_FLAGS & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
+      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
+         PRA_CHILD_TIDPTR("clone", int *, child_tidptr);
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+      PRE_MEM_WRITE("clone(child_tidptr)", ARG_CHILD_TIDPTR, sizeof(Int));
Mark Wielaard f88b36
+      if (!VG_(am_is_valid_for_client)(ARG_CHILD_TIDPTR, sizeof(Int), 
Mark Wielaard f88b36
+                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
+         badarg = True;
Mark Wielaard f88b36
+      }
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (badarg) {
Mark Wielaard f88b36
+      SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
+      return;
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   cloneflags = ARG_FLAGS;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (!ML_(client_signal_OK)(ARG_FLAGS & VKI_CSIGNAL)) {
Mark Wielaard f88b36
+      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
+      return;
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   /* Only look at the flags we really care about */
Mark Wielaard f88b36
+   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
+                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
+   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
+      /* thread creation */
Mark Wielaard f88b36
+      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
+         do_clone(tid,
Mark Wielaard f88b36
+                  ARG_FLAGS,               /* flags */
Mark Wielaard f88b36
+                  (Addr)ARG_CHILD_STACK,   /* child ESP */
Mark Wielaard f88b36
+                  (Int*)ARG3,              /* parent_tidptr */
Mark Wielaard f88b36
+                  (Int*)ARG_CHILD_TIDPTR,  /* child_tidptr */
Mark Wielaard f88b36
+                  (Addr)ARG_TLS));         /* set_tls */
Mark Wielaard f88b36
+      break;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
+      // FALLTHROUGH - assume vfork (somewhat) == fork, see ML_(do_fork_clone).
Mark Wielaard f88b36
+      cloneflags &= ~VKI_CLONE_VM;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   case 0: /* plain fork */
Mark Wielaard f88b36
+      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
+         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
+                       cloneflags,      /* flags */
Mark Wielaard f88b36
+                       (Int*)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
+                       (Int*)ARG_CHILD_TIDPTR,     /* child_tidptr */
Mark Wielaard f88b36
+                       (Addr)ARG_CHILD_STACK));
Mark Wielaard f88b36
+      break;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   default:
Mark Wielaard f88b36
+      /* should we just ENOSYS? */
Mark Wielaard f88b36
+      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG_FLAGS);
Mark Wielaard f88b36
+      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
+      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
+      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
+      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
+      VG_(unimplemented)
Mark Wielaard f88b36
+         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+   if (SUCCESS) {
Mark Wielaard f88b36
+      if (ARG_FLAGS & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
+         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
+      if (ARG_FLAGS & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
+         POST_MEM_WRITE(ARG_CHILD_TIDPTR, sizeof(Int));
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
+         to run */
Mark Wielaard f88b36
+      *flags |= SfYieldAfter;
Mark Wielaard f88b36
+   }
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+#undef ARG_CHILD_TIDPTR
Mark Wielaard f88b36
+#undef PRA_CHILD_TIDPTR
Mark Wielaard f88b36
+#undef ARG_TLS
Mark Wielaard f88b36
+#undef PRA_TLS
Mark Wielaard f88b36
+#undef ARG_FLAGS
Mark Wielaard f88b36
+#undef PRA_FLAGS
Mark Wielaard f88b36
+#undef ARG_CHILD_STACK
Mark Wielaard f88b36
+#undef PRA_CHILD_STACK
Mark Wielaard f88b36
+}
Mark Wielaard f88b36
+
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    *mount wrappers
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-mips64-linux.c b/coregrind/m_syswrap/syswrap-mips64-linux.c
Mark Wielaard f88b36
index 6e3db74..d3d70c5 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-mips64-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-mips64-linux.c
Mark Wielaard f88b36
@@ -136,14 +136,7 @@ asm (
Mark Wielaard f88b36
 #define __NR_CLONE        __NR_clone
Mark Wielaard f88b36
 #define __NR_EXIT         __NR_exit
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-ULong do_syscall_clone_mips64_linux ( Word (*fn) (void *),  /* a0 - 4 */
Mark Wielaard f88b36
-                                      void* stack,          /* a1 - 5 */
Mark Wielaard f88b36
-                                      Int   flags,          /* a2 - 6 */
Mark Wielaard f88b36
-                                      void* arg,            /* a3 - 7 */
Mark Wielaard f88b36
-                                      Int*  parent_tid,     /* a4 - 8 */
Mark Wielaard f88b36
-                                      void* /* Int tls */,  /* a5 - 9 */
Mark Wielaard f88b36
-                                      Int*  child_tid );    /* a6 - 10 */
Mark Wielaard f88b36
-
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n" 
Mark Wielaard f88b36
 ".set noreorder\n"
Mark Wielaard f88b36
@@ -199,104 +192,13 @@ asm(
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 /* forward declarations */
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState *, ThreadArchState *);
Mark Wielaard f88b36
 static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-/* When a client clones, we need to keep track of the new thread. This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested, but using
Mark Wielaard f88b36
-      the scheduler entrypoint for IP, and a separate stack for SP. */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid,
Mark Wielaard f88b36
-                         UInt flags, Addr sp,
Mark Wielaard f88b36
-                         Int* parent_tidptr,
Mark Wielaard f88b36
-                         Int* child_tidptr,
Mark Wielaard f88b36
-                         Addr child_tls )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   const Bool debug = False;
Mark Wielaard f88b36
-   ThreadId ctid = VG_ (alloc_ThreadState) ();
Mark Wielaard f88b36
-   ThreadState * ptst = VG_ (get_ThreadState) (ptid);
Mark Wielaard f88b36
-   ThreadState * ctst = VG_ (get_ThreadState) (ctid);
Mark Wielaard f88b36
-   UInt ret = 0;
Mark Wielaard f88b36
-   UWord * stack;
Mark Wielaard f88b36
-   SysRes res;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-   stack = (UWord *)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)(VKI_ENOMEM);
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   setup_child(&ctst->arch, &ptst->arch);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* on MIPS we need to set V0 and A3 to zero */
Mark Wielaard f88b36
-   ctst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
-   ctst->arch.vex.guest_r7 = 0;
Mark Wielaard f88b36
-   if (sp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_r29 = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_TRACK(pre_thread_ll_create, ptid, ctid);
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-       if (debug)
Mark Wielaard f88b36
-         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
Mark Wielaard f88b36
-       res = sys_set_tls(ctid, child_tls);
Mark Wielaard f88b36
-       if (sr_isError(res))
Mark Wielaard f88b36
-          goto out;
Mark Wielaard f88b36
-       ctst->arch.vex.guest_r27 = child_tls;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-   VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   ret = do_syscall_clone_mips64_linux(ML_(start_thread_NORETURN),
Mark Wielaard f88b36
-                                       stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-                                       parent_tidptr, NULL /*child_tls*/,
Mark Wielaard f88b36
-                                       child_tidptr);
Mark Wielaard f88b36
-   if (debug)
Mark Wielaard f88b36
-     VG_(printf)("ret: 0x%x\n", ret);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_mips64_linux)( /* val */ ret, 0, /* errflag */ 0);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   out:
Mark Wielaard f88b36
-   if (sr_isError (res)) {
Mark Wielaard f88b36
-      VG_ (cleanup_thread) (&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      VG_TRACK (pre_thread_ll_exit, ctid);
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   ptst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
                           More thread stuff
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
 void VG_(cleanup_thread) ( ThreadArchState * arch ) { };
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void setup_child ( /* OUT */ ThreadArchState * child,
Mark Wielaard f88b36
-                   /* IN  */ ThreadArchState * parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    VG_(threads)[tid].arch.vex.guest_ULR = tlsptr;
Mark Wielaard f88b36
@@ -316,7 +218,6 @@ SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
Mark Wielaard f88b36
    file, but that requires even more macro magic. */
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 DECL_TEMPLATE (mips_linux, sys_set_thread_area);
Mark Wielaard f88b36
-DECL_TEMPLATE (mips_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE (mips_linux, sys_tee);
Mark Wielaard f88b36
 DECL_TEMPLATE (mips_linux, sys_splice);
Mark Wielaard f88b36
 DECL_TEMPLATE (mips_linux, sys_vmsplice);
Mark Wielaard f88b36
@@ -494,84 +395,6 @@ PRE(sys_mmap)
Mark Wielaard f88b36
                                  (Off64T) ARG6);
Mark Wielaard f88b36
    SET_STATUS_from_SysRes(r);
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   Bool badarg = False;
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )", ARG1, ARG2, ARG3,
Mark Wielaard f88b36
-                                                      ARG4, ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ2(int, "clone", unsigned long, flags, void *, child_stack);
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA3("clone", int *, parent_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         badarg = True;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA5("clone", int *, child_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof (Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof (Int), VKI_PROT_WRITE))
Mark Wielaard f88b36
-         badarg = True;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (badarg) {
Mark Wielaard f88b36
-      SET_STATUS_Failure(VKI_EFAULT);
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure(VKI_EINVAL);
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
Mark Wielaard f88b36
-           |VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-      case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-         /* thread creation */
Mark Wielaard f88b36
-         SET_STATUS_from_SysRes(do_clone(tid,
Mark Wielaard f88b36
-                                         ARG1,          /* flags */
Mark Wielaard f88b36
-                                         (Addr)ARG2,    /* child SP */
Mark Wielaard f88b36
-                                         (Int *)ARG3,   /* parent_tidptr */
Mark Wielaard f88b36
-                                         (Int *)ARG5,   /* child_tidptr */
Mark Wielaard f88b36
-                                         (Addr)ARG4));  /* child_tls */
Mark Wielaard f88b36
-         break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      case VKI_CLONE_VFORK | VKI_CLONE_VM:  /* vfork */
Mark Wielaard f88b36
-         /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-         cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-      case 0:  /* plain fork */
Mark Wielaard f88b36
-         SET_STATUS_from_SysRes(ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                                cloneflags,     /* flags */
Mark Wielaard f88b36
-                                (Int *)ARG3,    /* parent_tidptr */
Mark Wielaard f88b36
-                                (Int *)ARG5));  /* child_tidptr */
Mark Wielaard f88b36
-         break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      default:
Mark Wielaard f88b36
-         /* should we just ENOSYS? */
Mark Wielaard f88b36
-         VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-         VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-         VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-         VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                       " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-         VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                       " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-         VG_(unimplemented)("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_rt_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-s390x-linux.c for
Mark Wielaard f88b36
@@ -766,7 +589,7 @@ static SyscallTableEntry syscall_main_table[] = {
Mark Wielaard f88b36
    LINXY (__NR_socketpair, sys_socketpair),
Mark Wielaard f88b36
    LINX_ (__NR_setsockopt, sys_setsockopt),
Mark Wielaard f88b36
    LINXY (__NR_getsockopt, sys_getsockopt),
Mark Wielaard f88b36
-   PLAX_ (__NR_clone, sys_clone),
Mark Wielaard f88b36
+   LINX_ (__NR_clone, sys_clone),
Mark Wielaard f88b36
    GENX_ (__NR_fork, sys_fork),
Mark Wielaard f88b36
    GENX_ (__NR_execve, sys_execve),
Mark Wielaard f88b36
    GENX_ (__NR_exit, sys_exit),
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c
Mark Wielaard f88b36
index 379fcb3..a654a90 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-ppc32-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c
Mark Wielaard f88b36
@@ -146,14 +146,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-ULong do_syscall_clone_ppc32_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                     void* stack, 
Mark Wielaard f88b36
-                                     Int   flags, 
Mark Wielaard f88b36
-                                     void* arg,
Mark Wielaard f88b36
-                                     Int*  child_tid, 
Mark Wielaard f88b36
-                                     Int*  parent_tid, 
Mark Wielaard f88b36
-                                     vki_modify_ldt_t * );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n"
Mark Wielaard f88b36
 ".globl do_syscall_clone_ppc32_linux\n"
Mark Wielaard f88b36
@@ -216,145 +209,6 @@ asm(
Mark Wielaard f88b36
 #undef __NR_CLONE
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-// forward declarations
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState*, ThreadArchState* );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         UInt flags, Addr sp, 
Mark Wielaard f88b36
-                         Int *parent_tidptr, 
Mark Wielaard f88b36
-                         Int *child_tidptr, 
Mark Wielaard f88b36
-                         Addr child_tls)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   const Bool debug = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   ULong        word64;
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-//?   /* make a stack frame */
Mark Wielaard f88b36
-//?   stack -= 16;
Mark Wielaard f88b36
-//?   *(UWord *)stack = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL SP for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's SP.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The child's TLS register (r2) gets set to the tlsaddr argument
Mark Wielaard f88b36
-      if the CLONE_SETTLS flag is set.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   { UInt old_cr = LibVEX_GuestPPC32_get_CR( &ctst->arch.vex );
Mark Wielaard f88b36
-     /* %r3 = 0 */
Mark Wielaard f88b36
-     ctst->arch.vex.guest_GPR3 = 0;
Mark Wielaard f88b36
-     /* %cr0.so = 0 */
Mark Wielaard f88b36
-     LibVEX_GuestPPC32_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (sp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_GPR1 = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  If the clone
Mark Wielaard f88b36
-      fails, we'll send out a ll_exit notification for it at the out:
Mark Wielaard f88b36
-      label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (debug)
Mark Wielaard f88b36
-         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
Mark Wielaard f88b36
-      ctst->arch.vex.guest_GPR2 = child_tls;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   word64 = do_syscall_clone_ppc32_linux(
Mark Wielaard f88b36
-               ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-               child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-            );
Mark Wielaard f88b36
-   /* High half word64 is syscall return value.  Low half is
Mark Wielaard f88b36
-      the entire CR, from which we need to extract CR0.SO. */
Mark Wielaard f88b36
-   /* VG_(printf)("word64 = 0x%llx\n", word64); */
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_ppc32_linux)( 
Mark Wielaard f88b36
-            /*val*/(UInt)(word64 >> 32), 
Mark Wielaard f88b36
-            /*errflag*/ (((UInt)word64) >> 28) & 1 
Mark Wielaard f88b36
-         );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    More thread stuff
Mark Wielaard f88b36
@@ -364,16 +218,6 @@ void VG_(cleanup_thread) ( ThreadArchState* arch )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
 }  
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
-                   /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for ppc32/Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -393,7 +237,6 @@ DECL_TEMPLATE(ppc32_linux, sys_stat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_lstat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_fstatat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_fstat64);
Mark Wielaard f88b36
-DECL_TEMPLATE(ppc32_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc32_linux, sys_sigsuspend);
Mark Wielaard f88b36
@@ -530,91 +373,6 @@ POST(sys_fstat64)
Mark Wielaard f88b36
 //..    }
Mark Wielaard f88b36
 //.. }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ5(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *,        child_stack,
Mark Wielaard f88b36
-                 int *,         parent_tidptr,
Mark Wielaard f88b36
-                 void *,        child_tls,
Mark Wielaard f88b36
-                 int *,         child_tidptr);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,         /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,   /* child SP */
Mark Wielaard f88b36
-                  (Int *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int *)ARG5,  /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG4)); /* child_tls */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG5));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
Mark Wielaard f88b36
@@ -999,7 +757,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
    GENX_(__NR_fsync,             sys_fsync),             // 118
Mark Wielaard f88b36
    PLAX_(__NR_sigreturn,         sys_sigreturn),         // 119 ?/Linux
Mark Wielaard f88b36
 //.. 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),             // 120
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),             // 120
Mark Wielaard f88b36
 //..    //   (__NR_setdomainname,     sys_setdomainname),     // 121 */*(?)
Mark Wielaard f88b36
    GENXY(__NR_uname,             sys_newuname),          // 122
Mark Wielaard f88b36
 //..    PLAX_(__NR_modify_ldt,        sys_modify_ldt),        // 123
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard f88b36
index 1ae4454..f90140d 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
Mark Wielaard f88b36
@@ -209,14 +209,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-ULong do_syscall_clone_ppc64_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                     void* stack, 
Mark Wielaard f88b36
-                                     Int   flags, 
Mark Wielaard f88b36
-                                     void* arg,
Mark Wielaard f88b36
-                                     Int*  child_tid, 
Mark Wielaard f88b36
-                                     Int*  parent_tid, 
Mark Wielaard f88b36
-                                     void/*vki_modify_ldt_t*/ * );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 #if defined(VGP_ppc64be_linux)
Mark Wielaard f88b36
 "   .align   2\n"
Mark Wielaard f88b36
@@ -366,148 +359,6 @@ asm(
Mark Wielaard f88b36
 #undef __NR_CLONE
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-// forward declarations
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState*, ThreadArchState* );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         UInt flags, Addr sp, 
Mark Wielaard f88b36
-                         Int *parent_tidptr, 
Mark Wielaard f88b36
-                         Int *child_tidptr, 
Mark Wielaard f88b36
-                         Addr child_tls)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   const Bool debug = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   ULong        word64;
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-//?   /* make a stack frame */
Mark Wielaard f88b36
-//?   stack -= 16;
Mark Wielaard f88b36
-//?   *(UWord *)stack = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL SP for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's SP.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The child's TLS register (r2) gets set to the tlsaddr argument
Mark Wielaard f88b36
-      if the CLONE_SETTLS flag is set.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   { UInt old_cr = LibVEX_GuestPPC64_get_CR( &ctst->arch.vex );
Mark Wielaard f88b36
-     /* %r3 = 0 */
Mark Wielaard f88b36
-     ctst->arch.vex.guest_GPR3 = 0;
Mark Wielaard f88b36
-     /* %cr0.so = 0 */
Mark Wielaard f88b36
-     LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), &ctst->arch.vex );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (sp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_GPR1 = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  If the clone
Mark Wielaard f88b36
-      fails, we'll send out a ll_exit notification for it at the out:
Mark Wielaard f88b36
-      label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (debug)
Mark Wielaard f88b36
-         VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
Mark Wielaard f88b36
-      ctst->arch.vex.guest_GPR13 = child_tls;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   word64 = do_syscall_clone_ppc64_linux(
Mark Wielaard f88b36
-               ML_(start_thread_NORETURN),
Mark Wielaard f88b36
-               stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-               child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-            );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Low half word64 is syscall return value.  Hi half is
Mark Wielaard f88b36
-      the entire CR, from which we need to extract CR0.SO. */
Mark Wielaard f88b36
-   /* VG_(printf)("word64 = 0x%llx\n", word64); */
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_ppc64_linux)( 
Mark Wielaard f88b36
-            /*val*/(UInt)(word64 & 0xFFFFFFFFULL), 
Mark Wielaard f88b36
-            /*errflag*/ (UInt)((word64 >> (32+28)) & 1)
Mark Wielaard f88b36
-         );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    More thread stuff
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -516,16 +367,6 @@ void VG_(cleanup_thread) ( ThreadArchState* arch )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
 }  
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
-                   /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for ppc64/Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -544,7 +385,6 @@ DECL_TEMPLATE(ppc64_linux, sys_mmap);
Mark Wielaard f88b36
 //zz DECL_TEMPLATE(ppc64_linux, sys_stat64);
Mark Wielaard f88b36
 //zz DECL_TEMPLATE(ppc64_linux, sys_lstat64);
Mark Wielaard f88b36
 //zz DECL_TEMPLATE(ppc64_linux, sys_fstat64);
Mark Wielaard f88b36
-DECL_TEMPLATE(ppc64_linux, sys_clone);
Mark Wielaard f88b36
 //zz DECL_TEMPLATE(ppc64_linux, sys_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc64_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(ppc64_linux, sys_fadvise64);
Mark Wielaard f88b36
@@ -629,92 +469,6 @@ PRE(sys_mmap)
Mark Wielaard f88b36
 //zz   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
Mark Wielaard f88b36
 //zz }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ5(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *,        child_stack,
Mark Wielaard f88b36
-                 int *,         parent_tidptr,
Mark Wielaard f88b36
-                 void *,        child_tls,
Mark Wielaard f88b36
-                 int *,         child_tidptr);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,         /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,   /* child SP */
Mark Wielaard f88b36
-                  (Int *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int *)ARG5,  /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG4)); /* child_tls */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG5));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_fadvise64)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    PRINT("sys_fadvise64 ( %ld, %ld, %lu, %ld )",  SARG1, SARG2, SARG3, SARG4);
Mark Wielaard f88b36
@@ -922,7 +676,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
    GENX_(__NR_fsync,             sys_fsync),              // 118
Mark Wielaard f88b36
 // _____(__NR_sigreturn,         sys_sigreturn),          // 119
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),              // 120
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),              // 120
Mark Wielaard f88b36
 // _____(__NR_setdomainname,     sys_setdomainname),      // 121
Mark Wielaard f88b36
    GENXY(__NR_uname,             sys_newuname),           // 122
Mark Wielaard f88b36
 // _____(__NR_modify_ldt,        sys_modify_ldt),         // 123
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-s390x-linux.c b/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard f88b36
index ebb8295..f596341 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-s390x-linux.c
Mark Wielaard f88b36
@@ -138,14 +138,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-ULong do_syscall_clone_s390x_linux ( void  *stack,
Mark Wielaard f88b36
-                                     ULong flags,
Mark Wielaard f88b36
-                                     Int   *parent_tid,
Mark Wielaard f88b36
-                                     Int   *child_tid,
Mark Wielaard f88b36
-                                     Addr  tlsaddr,
Mark Wielaard f88b36
-                                     Word (*fn)(void *),
Mark Wielaard f88b36
-                                     void  *arg);
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
    "   .text\n"
Mark Wielaard f88b36
    "   .align  4\n"
Mark Wielaard f88b36
@@ -182,126 +175,6 @@ void VG_(cleanup_thread) ( ThreadArchState* arch )
Mark Wielaard f88b36
   /* only used on x86 for descriptor tables */
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-static void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
-                   /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-/*
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid,
Mark Wielaard f88b36
-                         Addr sp, ULong flags,
Mark Wielaard f88b36
-                         Int *parent_tidptr,
Mark Wielaard f88b36
-                         Int *child_tidptr,
Mark Wielaard f88b36
-                         Addr tlsaddr)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   static const Bool debug = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   ULong        r2;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL sp for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's sp.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   ctst->arch.vex.guest_r2 = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (sp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_SP = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* have the parents thread group */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  If the clone
Mark Wielaard f88b36
-      fails, we'll send out a ll_exit notification for it at the out:
Mark Wielaard f88b36
-      label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (debug)
Mark Wielaard f88b36
-	 VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
Mark Wielaard f88b36
-      ctst->arch.vex.guest_a0 = (UInt) (tlsaddr >> 32);
Mark Wielaard f88b36
-      ctst->arch.vex.guest_a1 = (UInt) tlsaddr;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   r2 = do_syscall_clone_s390x_linux(
Mark Wielaard f88b36
-            stack, flags, parent_tidptr, child_tidptr, tlsaddr,
Mark Wielaard f88b36
-            ML_(start_thread_NORETURN), &VG_(threads)[ctid]);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_s390x_linux)( r2 );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for s390x/Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -317,7 +190,6 @@ static SysRes do_clone ( ThreadId ptid,
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 DECL_TEMPLATE(s390x_linux, sys_ptrace);
Mark Wielaard f88b36
 DECL_TEMPLATE(s390x_linux, sys_mmap);
Mark Wielaard f88b36
-DECL_TEMPLATE(s390x_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE(s390x_linux, sys_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(s390x_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE(s390x_linux, sys_fadvise64);
Mark Wielaard f88b36
@@ -452,99 +324,6 @@ PRE(sys_mmap)
Mark Wielaard f88b36
    SET_STATUS_from_SysRes(r);
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4, ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ2(int, "clone",
Mark Wielaard f88b36
-                 void *,        child_stack,
Mark Wielaard f88b36
-                 unsigned long, flags);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG2 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read)
Mark Wielaard f88b36
-         PRA3("clone(parent_tidptr)", int *, parent_tidptr);
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG2 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read)
Mark Wielaard f88b36
-         PRA4("clone(child_tidptr)", int *, child_tidptr);
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int),
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-         return;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* The kernel simply copies reg6 (ARG5) into AR0 and AR1, no checks */
Mark Wielaard f88b36
-   if (ARG2 & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA5("clone", Addr, tlsinfo);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG2;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG2 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  (Addr)ARG1,   /* child SP */
Mark Wielaard f88b36
-                  ARG2,         /* flags */
Mark Wielaard f88b36
-                  (Int *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int *)ARG4, /* child_tidptr */
Mark Wielaard f88b36
-                  (Addr)ARG5)); /*  tlsaddr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG4));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG2);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG2 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG2 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG4, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    ThreadState* tst;
Mark Wielaard f88b36
@@ -775,7 +554,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
    GENX_(__NR_fsync,  sys_fsync),                                     // 118
Mark Wielaard f88b36
    PLAX_(__NR_sigreturn, sys_sigreturn),                              // 119
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,  sys_clone),                                     // 120
Mark Wielaard f88b36
+   LINX_(__NR_clone,  sys_clone),                                     // 120
Mark Wielaard f88b36
 // ?????(__NR_setdomainname, ),                                       // 121
Mark Wielaard f88b36
    GENXY(__NR_uname, sys_newuname),                                   // 122
Mark Wielaard f88b36
    GENX_(123, sys_ni_syscall), /* unimplemented (by the kernel) */    // 123
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-tilegx-linux.c b/coregrind/m_syswrap/syswrap-tilegx-linux.c
Mark Wielaard f88b36
index 7501b20..05d81e8 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-tilegx-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-tilegx-linux.c
Mark Wielaard f88b36
@@ -224,14 +224,7 @@ void ML_(call_on_new_stack_0_1) (Addr stack, Addr retaddr,
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-Long do_syscall_clone_tilegx_linux ( Word (*fn) (void *),  //r0
Mark Wielaard f88b36
-                                     void *stack,          //r1
Mark Wielaard f88b36
-                                     Long flags,           //r2
Mark Wielaard f88b36
-                                     void *arg,            //r3
Mark Wielaard f88b36
-                                     Long * child_tid,     //r4
Mark Wielaard f88b36
-                                     Long * parent_tid,    //r5
Mark Wielaard f88b36
-                                     Long   tls );         //r6
Mark Wielaard f88b36
-    /*
Mark Wielaard f88b36
+   /*
Mark Wielaard f88b36
       stack
Mark Wielaard f88b36
       high -> 4  r29
Mark Wielaard f88b36
       3
Mark Wielaard f88b36
@@ -239,6 +232,7 @@ Long do_syscall_clone_tilegx_linux ( Word (*fn) (void *),  //r0
Mark Wielaard f88b36
       1  r10
Mark Wielaard f88b36
       low  -> 0  lr    <- sp
Mark Wielaard f88b36
     */
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
      asm (
Mark Wielaard f88b36
        ".text\n"
Mark Wielaard f88b36
        "   .globl   do_syscall_clone_tilegx_linux\n"
Mark Wielaard f88b36
@@ -315,101 +309,6 @@ Long do_syscall_clone_tilegx_linux ( Word (*fn) (void *),  //r0
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 // forward declarations
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState *, ThreadArchState * );
Mark Wielaard f88b36
-static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr );
Mark Wielaard f88b36
- /*
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for IP, and a separate stack
Mark Wielaard f88b36
-   for SP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid,
Mark Wielaard f88b36
-                         Long flags, Addr sp,
Mark Wielaard f88b36
-                         Long * parent_tidptr,
Mark Wielaard f88b36
-                         Long * child_tidptr,
Mark Wielaard f88b36
-                         Addr child_tls )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-  const Bool debug = False;
Mark Wielaard f88b36
-  ThreadId ctid = VG_ (alloc_ThreadState) ();
Mark Wielaard f88b36
-  ThreadState * ptst = VG_ (get_ThreadState) (ptid);
Mark Wielaard f88b36
-  ThreadState * ctst = VG_ (get_ThreadState) (ctid);
Mark Wielaard f88b36
-  Long ret = 0;
Mark Wielaard f88b36
-  Long * stack;
Mark Wielaard f88b36
-  SysRes res;
Mark Wielaard f88b36
-  vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  VG_ (sigfillset) (&blockall);
Mark Wielaard f88b36
-  vg_assert (VG_ (is_running_thread) (ptid));
Mark Wielaard f88b36
-  vg_assert (VG_ (is_valid_tid) (ctid));
Mark Wielaard f88b36
-  stack = (Long *) ML_ (allocstack) (ctid);
Mark Wielaard f88b36
-  if (stack == NULL) {
Mark Wielaard f88b36
-    res = VG_ (mk_SysRes_Error) (VKI_ENOMEM);
Mark Wielaard f88b36
-    goto out;
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-  setup_child (&ctst->arch, &ptst->arch);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  /* On TILEGX we need to set r0 and r3 to zero */
Mark Wielaard f88b36
-  ctst->arch.vex.guest_r0 = 0;
Mark Wielaard f88b36
-  ctst->arch.vex.guest_r3 = 0;
Mark Wielaard f88b36
-  if (sp != 0)
Mark Wielaard f88b36
-    ctst->arch.vex.guest_r54 = sp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-  ctst->sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-  ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-     parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-     after the child is created but before it sets its
Mark Wielaard f88b36
-     os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-     syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-     a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-     exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-     is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-     See #226116. */
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-  ML_(guess_and_register_stack) (sp, ctst);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  VG_TRACK (pre_thread_ll_create, ptid, ctid);
Mark Wielaard f88b36
-  if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-    if (debug)
Mark Wielaard f88b36
-      VG_(printf)("clone child has SETTLS: tls at %#lx\n", child_tls);
Mark Wielaard f88b36
-    ctst->arch.vex.guest_r53 = child_tls;
Mark Wielaard f88b36
-    res = sys_set_tls(ctid, child_tls);
Mark Wielaard f88b36
-    if (sr_isError(res))
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-  VG_ (sigprocmask) (VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-  /* Create the new thread */
Mark Wielaard f88b36
-  ret = do_syscall_clone_tilegx_linux (ML_ (start_thread_NORETURN),
Mark Wielaard f88b36
-                                       stack, flags, &VG_ (threads)[ctid],
Mark Wielaard f88b36
-                                       child_tidptr, parent_tidptr,
Mark Wielaard f88b36
-                                       (Long)NULL /*child_tls*/);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  /* High half word64 is syscall return value. */
Mark Wielaard f88b36
-  if (debug)
Mark Wielaard f88b36
-    VG_(printf)("ret: 0x%llx\n", (ULong)ret);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  res = VG_(mk_SysRes_tilegx_linux) (/*val */ ret);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  VG_ (sigprocmask) (VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
- out:
Mark Wielaard f88b36
-  if (sr_isError (res)) {
Mark Wielaard f88b36
-    VG_(cleanup_thread) (&ctst->arch);
Mark Wielaard f88b36
-    ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-    VG_TRACK (pre_thread_ll_exit, ctid);
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-  ptst->arch.vex.guest_r0 = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 extern Addr do_brk ( Addr newbrk );
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 extern
Mark Wielaard f88b36
@@ -428,23 +327,6 @@ extern Bool linux_kernel_2_6_22(void);
Mark Wielaard f88b36
 void
Mark Wielaard f88b36
 VG_ (cleanup_thread) ( ThreadArchState * arch ) { }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-void
Mark Wielaard f88b36
-setup_child ( /*OUT*/ ThreadArchState * child,
Mark Wielaard f88b36
-              /*IN*/ ThreadArchState * parent )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-  /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-  child->vex = parent->vex;
Mark Wielaard f88b36
-  child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-  child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-  VG_(threads)[tid].arch.vex.guest_r53 = tlsptr;
Mark Wielaard f88b36
-  return VG_(mk_SysRes_Success)( 0 );
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    PRE/POST wrappers for tilegx/Linux-specific syscalls
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -457,7 +339,6 @@ SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
Mark Wielaard f88b36
    aren't visible outside this file, but that requires even more macro
Mark Wielaard f88b36
    magic. */
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-DECL_TEMPLATE (tilegx_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE (tilegx_linux, sys_rt_sigreturn);
Mark Wielaard f88b36
 DECL_TEMPLATE (tilegx_linux, sys_socket);
Mark Wielaard f88b36
 DECL_TEMPLATE (tilegx_linux, sys_setsockopt);
Mark Wielaard f88b36
@@ -496,94 +377,6 @@ DECL_TEMPLATE (tilegx_linux, sys_syscall184);
Mark Wielaard f88b36
 DECL_TEMPLATE (tilegx_linux, sys_cacheflush);
Mark Wielaard f88b36
 DECL_TEMPLATE (tilegx_linux, sys_set_dataplane);
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-  ULong cloneflags;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-  PRE_REG_READ5(int, "clone",
Mark Wielaard f88b36
-                unsigned long, flags,
Mark Wielaard f88b36
-                void *, child_stack,
Mark Wielaard f88b36
-                int *, parent_tidptr,
Mark Wielaard f88b36
-                int *, child_tidptr,
Mark Wielaard f88b36
-                void *, tlsaddr);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-    PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-    if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-    }
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-  if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-    PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
Mark Wielaard f88b36
-    if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int), VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-    }
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-    SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-    return;
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  /* Only look at the flags we really care about */
Mark Wielaard f88b36
-  switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
Mark Wielaard f88b36
-                        | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-  case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-    /* thread creation */
Mark Wielaard f88b36
-    SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-      do_clone(tid,
Mark Wielaard f88b36
-               ARG1,          /* flags */
Mark Wielaard f88b36
-               (Addr)ARG2,    /* child ESP */
Mark Wielaard f88b36
-               (Long *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-               (Long *)ARG4,  /* child_tidptr */
Mark Wielaard f88b36
-               (Addr)ARG5));  /* set_tls */
Mark Wielaard f88b36
-    break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-    /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-    cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  case 0: /* plain fork */
Mark Wielaard f88b36
-    SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-      ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                         cloneflags,      /* flags */
Mark Wielaard f88b36
-                         (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                         (Int *)ARG4));   /* child_tidptr */
Mark Wielaard f88b36
-    break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  default:
Mark Wielaard f88b36
-    /* should we just ENOSYS? */
Mark Wielaard f88b36
-    VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                 "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-    VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                 "\n");
Mark Wielaard f88b36
-    VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                 "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-    VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                 " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-    VG_(message)(Vg_UserMsg,
Mark Wielaard f88b36
-                 " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-    VG_(unimplemented)
Mark Wielaard f88b36
-      ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  if (SUCCESS) {
Mark Wielaard f88b36
-    if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-      POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-    if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-      POST_MEM_WRITE(ARG4, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-    /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-       to run */
Mark Wielaard f88b36
-    *flags |= SfYieldAfter;
Mark Wielaard f88b36
-  }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_rt_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
   /* This isn't really a syscall at all - it's a misuse of the
Mark Wielaard f88b36
@@ -1344,7 +1137,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
   LINX_(__NR_add_key,           sys_add_key),              // 217
Mark Wielaard f88b36
   LINX_(__NR_request_key,       sys_request_key),          // 218
Mark Wielaard f88b36
   LINXY(__NR_keyctl,            sys_keyctl),               // 219
Mark Wielaard f88b36
-  PLAX_(__NR_clone,             sys_clone),                // 220
Mark Wielaard f88b36
+  LINX_(__NR_clone,             sys_clone),                // 220
Mark Wielaard f88b36
   GENX_(__NR_execve,            sys_execve),               // 221
Mark Wielaard f88b36
   PLAX_(__NR_mmap,              sys_mmap),                 // 222
Mark Wielaard f88b36
   GENXY(__NR_mprotect,          sys_mprotect),             // 226
Mark Wielaard f88b36
diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard f88b36
index 0e5af98..f8c4eb4 100644
Mark Wielaard f88b36
--- a/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard f88b36
+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
Mark Wielaard f88b36
@@ -131,14 +131,7 @@ asm(
Mark Wielaard f88b36
 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
Mark Wielaard f88b36
 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-extern
Mark Wielaard f88b36
-Int do_syscall_clone_x86_linux ( Word (*fn)(void *), 
Mark Wielaard f88b36
-                                 void* stack, 
Mark Wielaard f88b36
-                                 Int   flags, 
Mark Wielaard f88b36
-                                 void* arg,
Mark Wielaard f88b36
-                                 Int*  child_tid, 
Mark Wielaard f88b36
-                                 Int*  parent_tid, 
Mark Wielaard f88b36
-                                 vki_modify_ldt_t * );
Mark Wielaard f88b36
+// See priv_syswrap-linux.h for arg profile.
Mark Wielaard f88b36
 asm(
Mark Wielaard f88b36
 ".text\n"
Mark Wielaard f88b36
 ".globl do_syscall_clone_x86_linux\n"
Mark Wielaard f88b36
@@ -191,141 +184,6 @@ asm(
Mark Wielaard f88b36
 #undef __NR_EXIT
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-// forward declarations
Mark Wielaard f88b36
-static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
Mark Wielaard f88b36
-static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-/* 
Mark Wielaard f88b36
-   When a client clones, we need to keep track of the new thread.  This means:
Mark Wielaard f88b36
-   1. allocate a ThreadId+ThreadState+stack for the thread
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   2. initialize the thread's new VCPU state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   3. create the thread using the same args as the client requested,
Mark Wielaard f88b36
-   but using the scheduler entrypoint for EIP, and a separate stack
Mark Wielaard f88b36
-   for ESP.
Mark Wielaard f88b36
- */
Mark Wielaard f88b36
-static SysRes do_clone ( ThreadId ptid, 
Mark Wielaard f88b36
-                         UInt flags, Addr esp, 
Mark Wielaard f88b36
-                         Int* parent_tidptr, 
Mark Wielaard f88b36
-                         Int* child_tidptr, 
Mark Wielaard f88b36
-                         vki_modify_ldt_t *tlsinfo)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   static const Bool debug = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ThreadId     ctid = VG_(alloc_ThreadState)();
Mark Wielaard f88b36
-   ThreadState* ptst = VG_(get_ThreadState)(ptid);
Mark Wielaard f88b36
-   ThreadState* ctst = VG_(get_ThreadState)(ctid);
Mark Wielaard f88b36
-   UWord*       stack;
Mark Wielaard f88b36
-   SysRes       res;
Mark Wielaard f88b36
-   Int          eax;
Mark Wielaard f88b36
-   vki_sigset_t blockall, savedmask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigfillset)(&blockall);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   vg_assert(VG_(is_running_thread)(ptid));
Mark Wielaard f88b36
-   vg_assert(VG_(is_valid_tid)(ctid));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   stack = (UWord*)ML_(allocstack)(ctid);
Mark Wielaard f88b36
-   if (stack == NULL) {
Mark Wielaard f88b36
-      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
Mark Wielaard f88b36
-      goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Copy register state
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      Both parent and child return to the same place, and the code
Mark Wielaard f88b36
-      following the clone syscall works out which is which, so we
Mark Wielaard f88b36
-      don't need to worry about it.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      The parent gets the child's new tid returned from clone, but the
Mark Wielaard f88b36
-      child gets 0.
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      If the clone call specifies a NULL esp for the new thread, then
Mark Wielaard f88b36
-      it actually gets a copy of the parent's esp.
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   /* Note: the clone call done by the Quadrics Elan3 driver specifies
Mark Wielaard f88b36
-      clone flags of 0xF00, and it seems to rely on the assumption
Mark Wielaard f88b36
-      that the child inherits a copy of the parent's GDT.  
Mark Wielaard f88b36
-      setup_child takes care of setting that up. */
Mark Wielaard f88b36
-   setup_child( &ctst->arch, &ptst->arch, True );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Make sys_clone appear to have returned Success(0) in the
Mark Wielaard f88b36
-      child. */
Mark Wielaard f88b36
-   ctst->arch.vex.guest_EAX = 0;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (esp != 0)
Mark Wielaard f88b36
-      ctst->arch.vex.guest_ESP = esp;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ctst->os_state.parent = ptid;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* inherit signal mask */
Mark Wielaard f88b36
-   ctst->sig_mask     = ptst->sig_mask;
Mark Wielaard f88b36
-   ctst->tmp_sig_mask = ptst->sig_mask;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Start the child with its threadgroup being the same as the
Mark Wielaard f88b36
-      parent's.  This is so that any exit_group calls that happen
Mark Wielaard f88b36
-      after the child is created but before it sets its
Mark Wielaard f88b36
-      os_state.threadgroup field for real (in thread_wrapper in
Mark Wielaard f88b36
-      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
Mark Wielaard f88b36
-      a race condition in which the thread is unkillable (via
Mark Wielaard f88b36
-      exit_group) because its threadgroup is not set.  The race window
Mark Wielaard f88b36
-      is probably only a few hundred or a few thousand cycles long.
Mark Wielaard f88b36
-      See #226116. */
Mark Wielaard f88b36
-   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   ML_(guess_and_register_stack) (esp, ctst);
Mark Wielaard f88b36
-   
Mark Wielaard f88b36
-   /* Assume the clone will succeed, and tell any tool that wants to
Mark Wielaard f88b36
-      know that this thread has come into existence.  We cannot defer
Mark Wielaard f88b36
-      it beyond this point because sys_set_thread_area, just below,
Mark Wielaard f88b36
-      causes tCheck to assert by making references to the new ThreadId
Mark Wielaard f88b36
-      if we don't state the new thread exists prior to that point.
Mark Wielaard f88b36
-      If the clone fails, we'll send out a ll_exit notification for it
Mark Wielaard f88b36
-      at the out: label below, to clean up. */
Mark Wielaard f88b36
-   vg_assert(VG_(owns_BigLock_LL)(ptid));
Mark Wielaard f88b36
-   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (flags & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (debug)
Mark Wielaard f88b36
-	 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%u "
Mark Wielaard f88b36
-                     "base=%#lx limit=%x; esp=%#x fs=%x gs=%x\n",
Mark Wielaard f88b36
-		     tlsinfo, tlsinfo->entry_number, 
Mark Wielaard f88b36
-                     tlsinfo->base_addr, tlsinfo->limit,
Mark Wielaard f88b36
-		     ptst->arch.vex.guest_ESP,
Mark Wielaard f88b36
-		     ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
Mark Wielaard f88b36
-      res = sys_set_thread_area(ctid, tlsinfo);
Mark Wielaard f88b36
-      if (sr_isError(res))
Mark Wielaard f88b36
-	 goto out;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   flags &= ~VKI_CLONE_SETTLS;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* start the thread with everything blocked */
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Create the new thread */
Mark Wielaard f88b36
-   eax = do_syscall_clone_x86_linux(
Mark Wielaard f88b36
-            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
Mark Wielaard f88b36
-            child_tidptr, parent_tidptr, NULL
Mark Wielaard f88b36
-         );
Mark Wielaard f88b36
-   res = VG_(mk_SysRes_x86_linux)( eax );
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-  out:
Mark Wielaard f88b36
-   if (sr_isError(res)) {
Mark Wielaard f88b36
-      /* clone failed */
Mark Wielaard f88b36
-      VG_(cleanup_thread)(&ctst->arch);
Mark Wielaard f88b36
-      ctst->status = VgTs_Empty;
Mark Wielaard f88b36
-      /* oops.  Better tell the tool the thread exited in a hurry :-) */
Mark Wielaard f88b36
-      VG_TRACK( pre_thread_ll_exit, ctid );
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   return res;
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 /* ---------------------------------------------------------------------
Mark Wielaard f88b36
    LDT/GDT simulation
Mark Wielaard f88b36
    ------------------------------------------------------------------ */
Mark Wielaard f88b36
@@ -630,7 +488,7 @@ static SysRes sys_modify_ldt ( ThreadId tid,
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-static SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
Mark Wielaard f88b36
+SysRes ML_(x86_sys_set_thread_area) ( ThreadId tid, vki_modify_ldt_t* info )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    Int                  idx;
Mark Wielaard f88b36
    VexGuestX86SegDescr* gdt;
Mark Wielaard f88b36
@@ -738,15 +596,9 @@ void VG_(cleanup_thread) ( ThreadArchState* arch )
Mark Wielaard f88b36
 }  
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-static void setup_child ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
-                          /*IN*/  ThreadArchState *parent,
Mark Wielaard f88b36
-                          Bool inherit_parents_GDT )
Mark Wielaard f88b36
+void ML_(x86_setup_LDT_GDT) ( /*OUT*/ ThreadArchState *child, 
Mark Wielaard f88b36
+                              /*IN*/  ThreadArchState *parent )
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
-   /* We inherit our parent's guest state. */
Mark Wielaard f88b36
-   child->vex = parent->vex;
Mark Wielaard f88b36
-   child->vex_shadow1 = parent->vex_shadow1;
Mark Wielaard f88b36
-   child->vex_shadow2 = parent->vex_shadow2;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
    /* We inherit our parent's LDT. */
Mark Wielaard f88b36
    if (parent->vex.guest_LDT == (HWord)NULL) {
Mark Wielaard f88b36
       /* We hope this is the common case. */
Mark Wielaard f88b36
@@ -763,7 +615,7 @@ static void setup_child ( /*OUT*/ ThreadArchState *child,
Mark Wielaard f88b36
       only). */
Mark Wielaard f88b36
    child->vex.guest_GDT = (HWord)NULL;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-   if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) {
Mark Wielaard f88b36
+   if (parent->vex.guest_GDT != (HWord)NULL) {
Mark Wielaard f88b36
       child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT();
Mark Wielaard f88b36
       copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT,
Mark Wielaard f88b36
                         (VexGuestX86SegDescr*)child->vex.guest_GDT );
Mark Wielaard f88b36
@@ -787,7 +639,6 @@ DECL_TEMPLATE(x86_linux, sys_stat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, sys_fstatat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, sys_fstat64);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, sys_lstat64);
Mark Wielaard f88b36
-DECL_TEMPLATE(x86_linux, sys_clone);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, old_mmap);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, sys_mmap2);
Mark Wielaard f88b36
 DECL_TEMPLATE(x86_linux, sys_sigreturn);
Mark Wielaard f88b36
@@ -835,137 +686,6 @@ PRE(old_select)
Mark Wielaard f88b36
    }
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-PRE(sys_clone)
Mark Wielaard f88b36
-{
Mark Wielaard f88b36
-   UInt cloneflags;
Mark Wielaard f88b36
-   Bool badarg = False;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
Mark Wielaard f88b36
-   PRE_REG_READ2(int, "clone",
Mark Wielaard f88b36
-                 unsigned long, flags,
Mark Wielaard f88b36
-                 void *, child_stack);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA3("clone", int *, parent_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         badarg = True;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & VKI_CLONE_SETTLS) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA4("clone", vki_modify_ldt_t *, tlsinfo);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_READ("clone(tlsinfo)", ARG4, sizeof(vki_modify_ldt_t));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t), 
Mark Wielaard f88b36
-                                             VKI_PROT_READ)) {
Mark Wielaard f88b36
-         badarg = True;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
Mark Wielaard f88b36
-      if (VG_(tdict).track_pre_reg_read) {
Mark Wielaard f88b36
-         PRA5("clone", int *, child_tidptr);
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
Mark Wielaard f88b36
-      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int), 
Mark Wielaard f88b36
-                                             VKI_PROT_WRITE)) {
Mark Wielaard f88b36
-         badarg = True;
Mark Wielaard f88b36
-      }
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (badarg) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EFAULT );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   cloneflags = ARG1;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
Mark Wielaard f88b36
-      SET_STATUS_Failure( VKI_EINVAL );
Mark Wielaard f88b36
-      return;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Be ultra-paranoid and filter out any clone-variants we don't understand:
Mark Wielaard f88b36
-      - ??? specifies clone flags of 0x100011
Mark Wielaard f88b36
-      - ??? specifies clone flags of 0x1200011.
Mark Wielaard f88b36
-      - NPTL specifies clone flags of 0x7D0F00.
Mark Wielaard f88b36
-      - The Quadrics Elan3 driver specifies clone flags of 0xF00.
Mark Wielaard f88b36
-      - Newer Quadrics Elan3 drivers with NTPL support specify 0x410F00.
Mark Wielaard f88b36
-      Everything else is rejected. 
Mark Wielaard f88b36
-   */
Mark Wielaard f88b36
-   if (
Mark Wielaard f88b36
-        1 ||
Mark Wielaard f88b36
-        /* 11 Nov 05: for the time being, disable this ultra-paranoia.
Mark Wielaard f88b36
-           The switch below probably does a good enough job. */
Mark Wielaard f88b36
-          (cloneflags == 0x100011 || cloneflags == 0x1200011
Mark Wielaard f88b36
-                                  || cloneflags == 0x7D0F00
Mark Wielaard f88b36
-                                  || cloneflags == 0x790F00
Mark Wielaard f88b36
-                                  || cloneflags == 0x3D0F00
Mark Wielaard f88b36
-                                  || cloneflags == 0x410F00
Mark Wielaard f88b36
-                                  || cloneflags == 0xF00
Mark Wielaard f88b36
-                                  || cloneflags == 0xF21)) {
Mark Wielaard f88b36
-     /* OK */
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-   else {
Mark Wielaard f88b36
-      /* Nah.  We don't like it.  Go away. */
Mark Wielaard f88b36
-      goto reject;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   /* Only look at the flags we really care about */
Mark Wielaard f88b36
-   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS 
Mark Wielaard f88b36
-                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
Mark Wielaard f88b36
-   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
Mark Wielaard f88b36
-      /* thread creation */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         do_clone(tid,
Mark Wielaard f88b36
-                  ARG1,         /* flags */
Mark Wielaard f88b36
-                  (Addr)ARG2,   /* child ESP */
Mark Wielaard f88b36
-                  (Int *)ARG3,  /* parent_tidptr */
Mark Wielaard f88b36
-                  (Int *)ARG5,  /* child_tidptr */
Mark Wielaard f88b36
-                  (vki_modify_ldt_t *)ARG4)); /* set_tls */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
Mark Wielaard f88b36
-      /* FALLTHROUGH - assume vfork == fork */
Mark Wielaard f88b36
-      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   case 0: /* plain fork */
Mark Wielaard f88b36
-      SET_STATUS_from_SysRes(
Mark Wielaard f88b36
-         ML_(do_fork_clone)(tid,
Mark Wielaard f88b36
-                       cloneflags,      /* flags */
Mark Wielaard f88b36
-                       (Int *)ARG3,     /* parent_tidptr */
Mark Wielaard f88b36
-                       (Int *)ARG5));   /* child_tidptr */
Mark Wielaard f88b36
-      break;
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   default:
Mark Wielaard f88b36
-   reject:
Mark Wielaard f88b36
-      /* should we just ENOSYS? */
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
Mark Wielaard f88b36
-      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
Mark Wielaard f88b36
-      VG_(unimplemented)
Mark Wielaard f88b36
-         ("Valgrind does not support general clone().");
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-   if (SUCCESS) {
Mark Wielaard f88b36
-      if (ARG1 & VKI_CLONE_PARENT_SETTID)
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG3, sizeof(Int));
Mark Wielaard f88b36
-      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
Mark Wielaard f88b36
-         POST_MEM_WRITE(ARG5, sizeof(Int));
Mark Wielaard f88b36
-
Mark Wielaard f88b36
-      /* Thread creation was successful; let the child have the chance
Mark Wielaard f88b36
-         to run */
Mark Wielaard f88b36
-      *flags |= SfYieldAfter;
Mark Wielaard f88b36
-   }
Mark Wielaard f88b36
-}
Mark Wielaard f88b36
-
Mark Wielaard f88b36
 PRE(sys_sigreturn)
Mark Wielaard f88b36
 {
Mark Wielaard f88b36
    /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
Mark Wielaard f88b36
@@ -1063,7 +783,7 @@ PRE(sys_set_thread_area)
Mark Wielaard f88b36
    PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
Mark Wielaard f88b36
 
Mark Wielaard f88b36
    /* "do" the syscall ourselves; the kernel never sees it */
Mark Wielaard f88b36
-   SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
Mark Wielaard f88b36
+   SET_STATUS_from_SysRes( ML_(x86_sys_set_thread_area)( tid, (void *)ARG1 ) );
Mark Wielaard f88b36
 }
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 PRE(sys_get_thread_area)
Mark Wielaard f88b36
@@ -1553,7 +1273,7 @@ static SyscallTableEntry syscall_table[] = {
Mark Wielaard f88b36
    GENX_(__NR_fsync,             sys_fsync),          // 118
Mark Wielaard f88b36
    PLAX_(__NR_sigreturn,         sys_sigreturn),      // 119 ?/Linux
Mark Wielaard f88b36
 
Mark Wielaard f88b36
-   PLAX_(__NR_clone,             sys_clone),          // 120
Mark Wielaard f88b36
+   LINX_(__NR_clone,             sys_clone),          // 120
Mark Wielaard f88b36
 //zz    //   (__NR_setdomainname,     sys_setdomainname),  // 121 */*(?)
Mark Wielaard f88b36
    GENXY(__NR_uname,             sys_newuname),       // 122
Mark Wielaard f88b36
    PLAX_(__NR_modify_ldt,        sys_modify_ldt),     // 123
Mark Wielaard f88b36
diff --git a/include/vki/vki-arm64-linux.h b/include/vki/vki-arm64-linux.h
Mark Wielaard f88b36
index df34dd6..5a3b08f 100644
Mark Wielaard f88b36
--- a/include/vki/vki-arm64-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-arm64-linux.h
Mark Wielaard f88b36
@@ -586,7 +586,8 @@ struct vki_ucontext {
Mark Wielaard f88b36
 //ZZ };
Mark Wielaard f88b36
 //ZZ 
Mark Wielaard f88b36
 //ZZ // [[Nb: for our convenience within Valgrind, use a more specific name]]
Mark Wielaard f88b36
-//ZZ typedef struct vki_user_desc vki_modify_ldt_t;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
 // From linux-3.10.5/include/asm-generic/ipcbuf.h
Mark Wielaard f88b36
diff --git a/include/vki/vki-mips32-linux.h b/include/vki/vki-mips32-linux.h
Mark Wielaard f88b36
index 5be8e15..b6c9914 100644
Mark Wielaard f88b36
--- a/include/vki/vki-mips32-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-mips32-linux.h
Mark Wielaard f88b36
@@ -679,7 +679,7 @@ struct vki_ucontext {
Mark Wielaard f88b36
 };
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 // CAB: TODO
Mark Wielaard f88b36
-typedef void vki_modify_ldt_t;
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
 // From linux-2.6.35.5/include/asm-mips/ipcbuf.h
Mark Wielaard f88b36
diff --git a/include/vki/vki-mips64-linux.h b/include/vki/vki-mips64-linux.h
Mark Wielaard f88b36
index 26b8e9f..ca49b10 100644
Mark Wielaard f88b36
--- a/include/vki/vki-mips64-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-mips64-linux.h
Mark Wielaard f88b36
@@ -710,6 +710,7 @@ struct vki_ucontext {
Mark Wielaard f88b36
        vki_sigset_t           uc_sigmask;  /* mask last for extensibility */
Mark Wielaard f88b36
 };
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
 // From linux-2.6.35.9/include/asm-mips/ipcbuf.h
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
diff --git a/include/vki/vki-ppc32-linux.h b/include/vki/vki-ppc32-linux.h
Mark Wielaard f88b36
index 70c2835..0fd3c79 100644
Mark Wielaard f88b36
--- a/include/vki/vki-ppc32-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-ppc32-linux.h
Mark Wielaard f88b36
@@ -811,10 +811,9 @@ struct vki_ucontext {
Mark Wielaard f88b36
 //.. };
Mark Wielaard f88b36
 //.. 
Mark Wielaard f88b36
 //.. // [[Nb: for our convenience within Valgrind, use a more specific name]]
Mark Wielaard f88b36
-//.. typedef struct vki_user_desc vki_modify_ldt_t;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 // CAB: TODO
Mark Wielaard f88b36
-typedef void vki_modify_ldt_t;
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
diff --git a/include/vki/vki-ppc64-linux.h b/include/vki/vki-ppc64-linux.h
Mark Wielaard f88b36
index b410663..fd5cea6 100644
Mark Wielaard f88b36
--- a/include/vki/vki-ppc64-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-ppc64-linux.h
Mark Wielaard f88b36
@@ -685,6 +685,9 @@ struct vki_ucontext {
Mark Wielaard f88b36
   struct vki_sigcontext uc_mcontext;  /* last for extensibility */
Mark Wielaard f88b36
 };
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+// CAB: TODO
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
 // From linux-2.6.13/include/asm-ppc64/ipcbuf.h
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
diff --git a/include/vki/vki-s390x-linux.h b/include/vki/vki-s390x-linux.h
Mark Wielaard f88b36
index c3f6d00..1ef5cf7 100644
Mark Wielaard f88b36
--- a/include/vki/vki-s390x-linux.h
Mark Wielaard f88b36
+++ b/include/vki/vki-s390x-linux.h
Mark Wielaard f88b36
@@ -822,6 +822,8 @@ struct vki_ucontext {
Mark Wielaard f88b36
 	vki_sigset_t	      uc_sigmask; /* mask last for extensibility */
Mark Wielaard f88b36
 };
Mark Wielaard f88b36
 
Mark Wielaard f88b36
+typedef char vki_modify_ldt_t;
Mark Wielaard f88b36
+
Mark Wielaard f88b36
 //----------------------------------------------------------------------
Mark Wielaard f88b36
 // From linux-2.6.16.60/include/asm-s390/ipcbuf.h
Mark Wielaard f88b36
 //----------------------------------------------------------------------