From cbadd201cbd20b7e44b9f8edea932a9420f67230 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 16 Jan 2020 16:41:40 +0100 Subject: [PATCH] s390x: use clone3() if possible This adds the parasite clone3() with set_tid wrapper for s390x. In contrast to the x86_64 implementation the thread start address and arguments are not put on the thread stack but passed via r4 and r5. As those registers are caller-saved they still contain the correct value (thread start address and arguments) after returning from the syscall. Tested on 5.5.0-rc6. Signed-off-by: Adrian Reber --- criu/arch/s390/include/asm/restorer.h | 40 +++++++++++++++++++++++---- criu/kerndat.c | 4 +-- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/criu/arch/s390/include/asm/restorer.h b/criu/arch/s390/include/asm/restorer.h index 733f2de33..2fc266535 100644 --- a/criu/arch/s390/include/asm/restorer.h +++ b/criu/arch/s390/include/asm/restorer.h @@ -40,11 +40,41 @@ : "0", "1", "2", "3", "4", "5", "6", "cc", "memory") #define RUN_CLONE3_RESTORE_FN(ret, clone_args, size, args, \ - clone_restore_fn) do { \ - pr_err("This architecture does not support clone3() with set_tid, yet!\n"); \ - pr_err("Not creating a process with PID: %d\n", ((pid_t *)u64_to_ptr(clone_args.set_tid))[0]); \ - ret = -1; \ -} while (0) + clone_restore_fn) \ + asm volatile( \ + /* + * clone3 only needs two arguments (r2, r3), this means + * we can use r4 and r5 for args and thread function. + * r4 and r5 are callee-saved and are not overwritten. + * No need to put these values on the child stack. + */ \ + "lgr %%r4,%4\n" /* Save args in %r4 */ \ + "lgr %%r5,%3\n" /* Save clone_restore_fn in %r5 */ \ + "lgr %%r2,%1\n" /* Parameter 1: clone_args */ \ + "lgr %%r3,%2\n" /* Parameter 2: size */ \ + /* + * On s390x a syscall is done sc . + * That only works for syscalls < 255. clone3 is 435, + * therefore it is necessary to load the syscall number + * into r1 and do 'svc 0'. + */ \ + "lghi %%r1,"__stringify(__NR_clone3)"\n" \ + "svc 0\n" \ + "ltgr %0,%%r2\n" /* Set and check "ret" */ \ + "jnz 0f\n" /* ret != 0: Continue caller */ \ + "lgr %%r2,%%r4\n" /* Thread arguments taken from r4. */ \ + "lgr %%r1,%%r5\n" /* Thread function taken from r5. */ \ + "aghi %%r15,-160\n" /* Prepare stack frame */ \ + "xc 0(8,%%r15),0(%%r15)\n" \ + "basr %%r14,%%r1\n" /* Jump to clone_restore_fn() */ \ + "j .+2\n" /* BUG(): Force PGM check */ \ +"0:\n" /* Continue caller */ \ + : "=d"(ret) \ + : "a"(&clone_args), \ + "d"(size), \ + "d"(clone_restore_fn), \ + "d"(args) \ + : "0", "1", "2", "3", "4", "5", "cc", "memory") #define arch_map_vdso(map, compat) -1 diff --git a/criu/kerndat.c b/criu/kerndat.c index 0772828bc..2261cca60 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -992,10 +992,10 @@ static bool kerndat_has_clone3_set_tid(void) pid_t pid; struct _clone_args args = {}; -#ifndef CONFIG_X86_64 +#if !defined(CONFIG_X86_64) && !defined(CONFIG_S390) /* * Currently the CRIU PIE assembler clone3() wrapper is - * only implemented for X86_64. + * only implemented for X86_64 and S390X. */ kdat.has_clone3_set_tid = false; return 0;