clone-with-pids for s390
Ok, attached is a simpler version of the clone-with-pid userspace, which works for me on s390 with the following patch on top of ckpt-v16-x86.
-serge
From 80f9ab794dbb546aa8e33447403cc3717b448b0a Mon Sep 17 00:00:00 2001
From: Serge E. Hallyn <serue-r/[email protected]>
Date: Wed, 10 Jun 2009 15:06:25 -0400
Subject: [PATCH 1/1] s390: implement clone_with_pids()
--- arch/s390/include/asm/unistd.h | 3 ++- arch/s390/kernel/compat_linux.c | 19 +++++++++++++++++++ arch/s390/kernel/compat_wrapper.S | 8 ++++++++ arch/s390/kernel/process.c | 19 +++++++++++++++++++ arch/s390/kernel/syscalls.S | 1 + 5 files changed, 49 insertions(+), 1 deletions(-)
arch/s390/include/asm/unistd.h +2 -1
@@ -269,7 +269,8 @@#define __NR_pwritev 329#define __NR_checkpoint 330#define __NR_restart 331 -#define NR_syscalls 332 +#define __NR_clone_with_pids 332 +#define NR_syscalls 333/* * There are some system calls that are not present on 64 bit, some
arch/s390/kernel/compat_linux.c +19 -0
@@ -821,6 +821,25 @@ asmlinkage long sys32_clone(void) parent_tidptr, child_tidptr); } +asmlinkage long sys32_clone_with_pids (void ) +{ +struct pt_regs *regs =task_pt_regs (current); +unsigned long clone_flags; +unsigned long newsp; +int __user *parent_tidptr, *child_tidptr; +void __user *upid_setp; + + 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 ]); + upid_setp = (void __user *)regs->gprs[6 ]; +if (!newsp) + newsp = regs->gprs[15 ]; +return do_fork_with_pids (clone_flags, newsp, regs,0 , parent_tidptr, + child_tidptr, upid_setp); +} +/* * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE}
arch/s390/kernel/compat_wrapper.S +8 -0
@@ -1835,3 +1835,11 @@ sys_restore_wrapper: lgfr %r2,%r2 # int lgfr %r3,%r3 # int llgfr %r4,%r4 # unsigned long + + .globl sys_clone_with_pids_wrapper +sys_clone_with_pids_wrapper: + llgfr %r2,%r2 # unsigned long + llgfr %r3,%r3 # unsigned long + llgtr %r4,%r4 # int * + llgtr %r5,%r5 # int * + llgtr %r6,%r6 # upid_setp *
arch/s390/kernel/process.c +19 -0
@@ -246,6 +246,25 @@ SYSCALL_DEFINE0(clone) parent_tidptr, child_tidptr); } +SYSCALL_DEFINE0 (clone_with_pids) +{ +struct pt_regs *regs =task_pt_regs (current); +unsigned long clone_flags; +unsigned long newsp; +int __user *parent_tidptr, *child_tidptr; +void __user *upid_setp; + + clone_flags = regs->gprs[3 ]; + newsp = regs->orig_gpr2; + parent_tidptr = (int __user *) regs->gprs[4 ]; + child_tidptr = (int __user *) regs->gprs[5 ]; + upid_setp = (void __user *)regs->gprs[6 ]; +if (!newsp) + newsp = regs->gprs[15 ]; +return do_fork_with_pids (clone_flags, newsp, regs,0 , parent_tidptr, + child_tidptr, upid_setp); +} +/* * This is trivial, and on the face of it looks like it * could equally well be done in user mode.
arch/s390/kernel/syscalls.S +1 -0
@@ -340,3 +340,4 @@ SYSCALL(sys_preadv,sys_preadv,compat_sys_preadv_wrapper) SYSCALL(sys_pwritev,sys_pwritev,compat_sys_pwritev_wrapper) SYSCALL(sys_checkpoint,sys_checkpoint,sys_checkpoint_wrapper) /* 330 */ SYSCALL(sys_restart,sys_restart,sys_restore_wrapper) +SYSCALL(sys_clone_with_pids,sys_clone_with_pids,sys_clone_with_pids_wrapper)
Signature · 1 line
1.6.1
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <malloc.h>
#define CLONE_NEWPID 0x20000000
#ifndef __NR_gettid
#ifdef __x86__
#define __NR_gettid 224
#elif __s390__
#define __NR_gettid 236
#else
#error __NR_gettid undefined
#endif
#endif
#ifndef __NR_clone_with_pids
#ifdef __x86__
#define __NR_clone_with_pids 335
#elif __s390__
#define __NR_clone_with_pids 332
#else
#error __NR_clone_with_pids undefined
#endif
#endif
/*
* TODO: getpid() in child returns pid of parent for some reason gettid()
* returns correct pid (i.e 1 if CLONE_NEWPID or 19799 otherwise)
*/
int gettid()
{
int rc;
rc = syscall(__NR_gettid, 0, 0, 0);
if (rc < 0) {
printf("rc %d, errno %d\n", rc, errno);
fflush(stdout);
}
return rc;
}struct target_pid_set {
int num_pids;
pid_t *target_pids;
unsigned long flags;
};main()
{
int rc;
int clone_flags;
struct target_pid_set pid_set;
int stacksize = 4 * getpagesize();
void *childsp, *topstack;
int pids[1] = { 19799 };
childsp = malloc(stacksize);
if (!childsp)
return -1;
topstack = childsp + stacksize;
pid_set.num_pids = 1;
pid_set.target_pids = &pids[0];
pid_set.flags = 0;
//clone_flags = (CLONE_NEWPID| CLONE_FS | CLONE_FILES | SIGCHLD);
clone_flags = ( CLONE_FS | CLONE_FILES | SIGCHLD);
printf("Parent: Call clone_with_pids() for &pid_set %p\n", &pid_set);
rc = syscall(__NR_clone_with_pids, topstack, clone_flags, NULL,
NULL, &pid_set);
//NULL, NULL);
if (rc == 0) {
printf("Child: tid %d\n", gettid());
_exit(0);
} else if (rc > 0) {
printf("Parent: child pid %d\n", rc);
_exit(0);
} else {
printf("myclone() failed, rc %d, errno %d\n", rc, errno);
}
}_______________________________________________
Containers mailing list Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linux-foundation.org/mailman/listinfo/containers
A message that is not in the archive (sent off-list or not yet received): 20090611180149.GA31458-r/[email protected]
Review
Quoted 1 line · Serge E. Hallyn
(quoted diff) +1
-0+ upid_setp = (void __user *)regs->gprs[6];
Gah, gprs[6] is used to store a new tls if CLONE_NEWTLS so I can't do that.
-serge