From: Serge E. Hallyn <se...@us.ibm.com>

Implement the s390 hook for sys_eclone().

Changelog:
        Nov 24: Removed user-space code from commit log. See user-cr git tree.
        Nov 17: remove redundant flags_high check
        Nov 13: As suggested by Heiko, convert eclone to take its
                parameters via registers.

Cc: linux-...@vger.kernel.org
Cc: x...@kernel.org
Cc: linux-s...@vger.kernel.org
Cc: linuxppc-...@ozlabs.org
Signed-off-by: Serge E. Hallyn <se...@us.ibm.com>
---
 arch/s390/include/asm/unistd.h    |    3 ++-
 arch/s390/kernel/compat_linux.c   |   17 +++++++++++++++++
 arch/s390/kernel/compat_wrapper.S |    8 ++++++++
 arch/s390/kernel/process.c        |   37 +++++++++++++++++++++++++++++++++++++
 arch/s390/kernel/syscalls.S       |    1 +
 5 files changed, 65 insertions(+), 1 deletions(-)

diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index 5f00751..ff13be1 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -269,7 +269,8 @@
 #define        __NR_pwritev            329
 #define __NR_rt_tgsigqueueinfo 330
 #define __NR_perf_event_open   331
-#define NR_syscalls 332
+#define __NR_eclone            332
+#define NR_syscalls 333
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 73b624e..1f70d6f 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -663,6 +663,23 @@ asmlinkage long sys32_write(unsigned int fd, char __user * 
buf, size_t count)
        return sys_write(fd, buf, count);
 }
 
+asmlinkage long sys32_clone(void)
+{
+       struct pt_regs *regs = task_pt_regs(current);
+       unsigned long clone_flags;
+       unsigned long newsp;
+       int __user *parent_tidptr, *child_tidptr;
+
+       clone_flags = regs->gprs[3] & 0xffffffffUL;
+       newsp = regs->orig_gpr2 & 0x7fffffffUL;
+       parent_tidptr = compat_ptr(regs->gprs[4]);
+       child_tidptr = compat_ptr(regs->gprs[5]);
+       if (!newsp)
+               newsp = regs->gprs[15];
+       return do_fork(clone_flags, newsp, regs, 0,
+                      parent_tidptr, child_tidptr);
+}
+
 /*
  * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64.
  * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
diff --git a/arch/s390/kernel/compat_wrapper.S 
b/arch/s390/kernel/compat_wrapper.S
index 672ce52..b7bedfa 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1847,6 +1847,14 @@ sys_clone_wrapper:
        llgtr   %r5,%r5                 # int *
        jg      sys_clone               # branch to system call
 
+       .globl  sys_eclone_wrapper
+sys_eclone_wrapper:
+       llgfr   %r2,%r2                 # unsigned int
+       llgtr   %r3,%r3                 # struct clone_args *
+       lgfr    %r4,%r4                 # int
+       llgtr   %r5,%r5                 # pid_t *
+       jg      sys_eclone              # branch to system call
+
        .globl  sys32_execve_wrapper
 sys32_execve_wrapper:
        llgtr   %r2,%r2                 # char *
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 1039fde..799cbb0 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -240,6 +240,43 @@ SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned 
long, clone_flags,
                       parent_tidptr, child_tidptr);
 }
 
+SYSCALL_DEFINE4(eclone, unsigned int, flags_low, struct clone_args __user *,
+               uca, int, args_size, pid_t __user *, pids)
+{
+       int rc;
+       struct pt_regs *regs = task_pt_regs(current);
+       struct clone_args kca;
+       int __user *parent_tid_ptr;
+       int __user *child_tid_ptr;
+       unsigned long flags;
+       unsigned long __user child_stack;
+       unsigned long stack_size;
+
+       rc = fetch_clone_args_from_user(uca, args_size, &kca);
+       if (rc)
+               return rc;
+
+       flags = flags_low;
+       parent_tid_ptr = (int __user *) kca.parent_tid_ptr;
+       child_tid_ptr =  (int __user *) kca.child_tid_ptr;
+
+       stack_size = (unsigned long) kca.child_stack_size;
+       if (stack_size)
+               return -EINVAL;
+
+       child_stack = (unsigned long) kca.child_stack;
+       if (!child_stack)
+               child_stack = regs->gprs[15];
+
+       /*
+        * 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, regs, stack_size,
+                               parent_tid_ptr, child_tid_ptr, kca.nr_pids,
+                               pids);
+}
+
 /*
  * This is trivial, and on the face of it looks like it
  * could equally well be done in user mode.
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 201ce6b..08eab1d 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -340,3 +340,4 @@ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper)
 SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper)
 
SYSCALL(sys_rt_tgsigqueueinfo,sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo_wrapper)
 /* 330 */
 SYSCALL(sys_perf_event_open,sys_perf_event_open,sys_perf_event_open_wrapper)
+SYSCALL(sys_eclone,sys_eclone,sys_eclone_wrapper)
-- 
1.6.3.3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to