This is still a bit rough, but I figured I'd post it for kicks.

Most of the process.c stuff is copy-n-paste with i386 and needs
to get consolidated.  I also need to give this the new name.

I'd appreciate anybody that knows inline assembly well to make
sure that I'm not being a complete doofus with this call below.
This seems to work, but I'm not confident it is the best way.

int clone_with_pids(long flags_low, struct clone_args *clone_args, long 
args_size,
                 int *pids)
{
        long retval;

        __asm__  __volatile__(
                 "movq %3, %%r10\n\t"           /* pids in r10*/
                 "pushq %%rbp\n\t"              /* save value of ebp */
                :
                :"D" (flags_low), /* rdi */
                 "S" (clone_args),/* rsi */
                 "d" (args_size), /* rdx */
                 "a" (pids)       /* use rax, which gets moved to r10 */
                );

        __asm__ __volatile__(
                 "syscall\n\t"  /* Linux/x86_64 system call */
                 "testq %0,%0\n\t"      /* check return value */
                 "jne 1f\n\t"           /* jump if parent */
                 "popq %%rbx\n\t"       /* get subthread function */
                 "call *%%rbx\n\t"      /* start subthread function */
                 "movq %2,%0\n\t"
                 "syscall\n"            /* exit system call: exit subthread */
                 "1:\n\t"
                 "popq %%rbp\t"         /* restore parent's ebp */
                :"=a" (retval)
                :"0" (__NR_clone3), "i" (__NR_exit)
                :"ebx", "ecx", "edx"
                );

        if (retval < 0) {
                errno = -retval;
                retval = -1;
        }
        return retval;
}


---

 linux-2.6.git-dave/arch/x86/include/asm/syscalls.h  |    5 ++
 linux-2.6.git-dave/arch/x86/include/asm/unistd_64.h |    2 
 linux-2.6.git-dave/arch/x86/kernel/entry_64.S       |    8 +++
 linux-2.6.git-dave/arch/x86/kernel/process_64.c     |   49 ++++++++++++++++++++
 linux-2.6.git-dave/kernel/fork.c                    |   18 +++++++
 5 files changed, 82 insertions(+)

diff -puN arch/x86/include/asm/syscalls.h~cwp-x86_64 
arch/x86/include/asm/syscalls.h
--- linux-2.6.git/arch/x86/include/asm/syscalls.h~cwp-x86_64    2009-11-18 
16:37:09.000000000 -0800
+++ linux-2.6.git-dave/arch/x86/include/asm/syscalls.h  2009-11-18 
16:37:09.000000000 -0800
@@ -78,6 +78,11 @@ asmlinkage long sys_iopl(unsigned int, s
 asmlinkage long sys_clone(unsigned long, unsigned long,
                          void __user *, void __user *,
                          struct pt_regs *);
+asmlinkage long sys_clone_with_pids(unsigned int flags_low,
+                               struct clone_args * __user cargs,
+                               int cargs_size,
+                               pid_t * __user pids,
+                               struct pt_regs *pt_regs);
 asmlinkage long sys_execve(char __user *, char __user * __user *,
                           char __user * __user *,
                           struct pt_regs *);
diff -puN arch/x86/include/asm/unistd_64.h~cwp-x86_64 
arch/x86/include/asm/unistd_64.h
--- linux-2.6.git/arch/x86/include/asm/unistd_64.h~cwp-x86_64   2009-11-18 
16:37:09.000000000 -0800
+++ linux-2.6.git-dave/arch/x86/include/asm/unistd_64.h 2009-11-18 
16:37:09.000000000 -0800
@@ -661,6 +661,8 @@ __SYSCALL(__NR_pwritev, sys_pwritev)
 __SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
 #define __NR_perf_counter_open                 298
 __SYSCALL(__NR_perf_counter_open, sys_perf_counter_open)
+#define __NR_clone_with_pids                   299
+__SYSCALL(__NR_clone_with_pids, stub_clone_with_pids)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff -puN arch/x86/kernel/entry_64.S~cwp-x86_64 arch/x86/kernel/entry_64.S
--- linux-2.6.git/arch/x86/kernel/entry_64.S~cwp-x86_64 2009-11-18 
16:37:09.000000000 -0800
+++ linux-2.6.git-dave/arch/x86/kernel/entry_64.S       2009-11-18 
16:37:09.000000000 -0800
@@ -684,6 +684,13 @@ END(system_call)
 
 /*
  * Certain special system calls that need to save a complete full stack frame.
+ *
+ * 'arg' should be the register that pt_regs will show up in when
+ * 'func' is called.  Using normal calling conventions, this is:
+ *
+ *     func(%rdi, %rsi, %rdx, %rcx, %r8, %r9)
+ *
+ * So, if you want pt_regs as the third argument, use %rdx.
  */
        .macro PTREGSCALL label,func,arg
 ENTRY(\label)
@@ -704,6 +711,7 @@ END(\label)
        PTREGSCALL stub_vfork, sys_vfork, %rdi
        PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
        PTREGSCALL stub_iopl, sys_iopl, %rsi
+       PTREGSCALL stub_clone_with_pids, sys_clone_with_pids, %r8
 
 ENTRY(ptregscall_common)
        DEFAULT_FRAME 1 8       /* offset 8: return address */
diff -puN arch/x86/kernel/process_64.c~cwp-x86_64 arch/x86/kernel/process_64.c
--- linux-2.6.git/arch/x86/kernel/process_64.c~cwp-x86_64       2009-11-18 
16:37:09.000000000 -0800
+++ linux-2.6.git-dave/arch/x86/kernel/process_64.c     2009-11-18 
16:37:09.000000000 -0800
@@ -534,6 +534,55 @@ sys_clone(unsigned long clone_flags, uns
        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
+asmlinkage long
+sys_clone_with_pids(unsigned int flags_low, struct clone_args * __user cargs,
+               int args_size, pid_t * __user pids, struct pt_regs *pt_regs)
+{
+       int rc;
+       struct clone_args kca;
+       unsigned long flags;
+       int __user *parent_tid_ptr;
+       int __user *child_tid_ptr;
+       unsigned long __user child_stack;
+       unsigned long stack_size;
+
+       printk("%s() 0\n", __func__);
+       rc = fetch_clone_args_from_user(cargs, args_size, &kca);
+       if (rc) {
+               printk("%s() 1\n", __func__);
+               return rc;
+       }
+
+       /*
+        * TODO: Convert 'clone-flags' to 64-bits on all architectures.
+        * TODO: When ->clone_flags_high is non-zero, copy it in to the
+        *       higher word(s) of 'flags':
+        *
+        *              flags = (kca.clone_flags_high << 32) | flags_low;
+        */
+       printk("%s() 2\n", __func__);
+       flags = flags_low;
+       parent_tid_ptr = (int *)kca.parent_tid_ptr;
+       child_tid_ptr =  (int *)kca.child_tid_ptr;
+
+       printk("%s() 3\n", __func__);
+       stack_size = (unsigned long)kca.child_stack_size;
+       child_stack = (unsigned long)kca.child_stack_base + stack_size;
+
+       printk("%s() 4\n", __func__);
+       if (!child_stack)
+               child_stack = pt_regs->sp;
+       printk("%s() 5\n", __func__);
+
+       /*
+        * TODO: On 32-bit systems, clone_flags is passed in as 32-bit value
+        *       to several functions. Need to convert clone_flags to 64-bit.
+        */
+       return do_fork_with_pids(flags, child_stack, pt_regs, stack_size,
+                               parent_tid_ptr, child_tid_ptr, kca.nr_pids,
+                               pids);
+}
+
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long stack;
diff -puN kernel/fork.c~cwp-x86_64 kernel/fork.c
--- linux-2.6.git/kernel/fork.c~cwp-x86_64      2009-11-18 16:37:09.000000000 
-0800
+++ linux-2.6.git-dave/kernel/fork.c    2009-11-18 16:37:09.000000000 -0800
@@ -1359,8 +1359,10 @@ static pid_t *copy_target_pids(int unum_
 
        if (!unum_pids)
                return NULL;
+       printk("%s(%d, %p) 0\n", __func__, unum_pids, upids);
 
        knum_pids = task_pid(current)->level + 1;
+       printk("%s(%d, %p) knum_pids: %d\n", __func__, unum_pids, upids, 
knum_pids);
        if (unum_pids > knum_pids)
                return ERR_PTR(-EINVAL);
 
@@ -1407,6 +1409,7 @@ static pid_t *copy_target_pids(int unum_
        size = unum_pids * sizeof(pid_t);
 
        rc = copy_from_user(&target_pids[j], upids, size);
+       printk("%s() copy(%p, %p, %d) rc: %d\n", __func__, &target_pids[j], 
upids, size, rc);
        if (rc) {
                rc = -EFAULT;
                goto out_free;
@@ -1467,6 +1470,8 @@ long do_fork_with_pids(unsigned long clo
        long nr;
        pid_t *target_pids;
 
+       if (upids)
+               printk("%s() 0\n", __func__);
        /*
         * Do some preliminary argument and permissions checking before we
         * actually start allocating stuff
@@ -1482,6 +1487,8 @@ long do_fork_with_pids(unsigned long clo
                        return -EPERM;
        }
 
+       if (upids)
+               printk("%s() 1\n", __func__);
        /*
         * We hope to recycle these flags after 2.6.26
         */
@@ -1501,6 +1508,7 @@ long do_fork_with_pids(unsigned long clo
 
        target_pids = copy_target_pids(num_pids, upids);
        if (target_pids) {
+               printk("%s() 1a\n", __func__);
                if (IS_ERR(target_pids))
                        return PTR_ERR(target_pids);
 
@@ -1509,6 +1517,8 @@ long do_fork_with_pids(unsigned long clo
                        goto out_free;
        }
 
+       if (upids)
+               printk("%s() 2\n", __func__);
        /*
         * When called from kernel_thread, don't do user tracing stuff.
         */
@@ -1517,12 +1527,16 @@ long do_fork_with_pids(unsigned long clo
 
        p = copy_process(clone_flags, stack_start, regs, stack_size,
                         child_tidptr, NULL, target_pids, trace);
+       if (upids)
+               printk("%s() 3\n", __func__);
        /*
         * Do this prior waking up the new thread - the thread pointer
         * might get invalid after that point, if the thread exits quickly.
         */
        if (!IS_ERR(p)) {
                struct completion vfork;
+               if (upids)
+                       printk("%s() 4\n", __func__);
 
                trace_sched_process_fork(current, p);
 
@@ -1571,9 +1585,13 @@ long do_fork_with_pids(unsigned long clo
                nr = PTR_ERR(p);
        }
 
+       if (upids)
+               printk("%s() 5\n", __func__);
 out_free:
        kfree(target_pids);
 
+       if (upids)
+               printk("%s() 6\n", __func__);
        return nr;
 }
 
_
_______________________________________________
Containers mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to