Received: by 2002:a25:868d:0:0:0:0:0 with SMTP id z13csp2881317ybk; Tue, 12 May 2020 10:20:09 -0700 (PDT) X-Google-Smtp-Source: APiQypKXDS3hXI5K4i2WkRxqiZ63VgJ5cFrEz0Hg/bIilvU5/XiRcVQgr52EYAGuliVySGNmNH2G X-Received: by 2002:a50:c889:: with SMTP id d9mr11837523edh.81.1589304009199; Tue, 12 May 2020 10:20:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589304009; cv=none; d=google.com; s=arc-20160816; b=a0kC6SPRepWAlUGvDjVaHC5fjfKXNreHTNvPcnZ1jeDbM+t/TcL+TCrQq8tSKzgHZc cenhN2J6MMDuDVgwhDGmYbezEwRzD16lmDGBfLdOI2ifWtmogJ9EYGnf+szS59GESNjp 1tZvar3jGH0btbh/q2OHIPOW8J9OMnI4/0utKZKv8py/PiAVexlTkG7ePzxYPShidGhg MrpLIIt4btJ2r2FBTmjIYTVSKlmnhheYUEDflyg4As21AhfIuD/6zYSuMsnL982Bxal9 Ax21ixibfTK0eThIvssqsBAarNZlqZ9VzSb1uACEcWHzV/K3KgjNGUmjKspsWMQZq1kg orDg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=cSkTO+yInJGKReBWiAa/UZKdU0vJg9Nv+SSrcdisVEE=; b=0oFDgHRiRY9KgM8PfHKbBM9g+HZeS6YVl5XP+pKCkPWP9XOjwHMnzed2teMkmpq+Ub TVc0ta70XsTOt5/euhVo8vf3H5xOK2x++XmGC6Pt4IwcAgeRccwgNTQt1MaiwtwOCSJK NJwOzm74o7xU91SWYRATryJ6MoeKSBEB+kuEv8VSN5xK/Sxfcewow+bO9cClDttoHWAd jw6JJjAne8fExJRde43+WlSX6Ru8+O/O6M5Bsv2qeNNXt4mQqDTZgn3N9fw4+NTIsplf YyiHyXB0i7yPahpmjceKJ4cKJ5Rjbmp00HQVz4D9ans5jbHGpKre7nWFmwsfifERuU1b Xi8A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ck25si7960525ejb.114.2020.05.12.10.19.46; Tue, 12 May 2020 10:20:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729610AbgELRPk (ORCPT + 99 others); Tue, 12 May 2020 13:15:40 -0400 Received: from youngberry.canonical.com ([91.189.89.112]:43898 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725938AbgELRPk (ORCPT ); Tue, 12 May 2020 13:15:40 -0400 Received: from ip5f5af183.dynamic.kabel-deutschland.de ([95.90.241.131] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1jYYVC-0002Ci-H9; Tue, 12 May 2020 17:15:34 +0000 From: Christian Brauner To: "David S. Miller" Cc: Arnd Bergmann , Guo Ren , linux-csky@vger.kernel.org, linux-kernel@vger.kernel.org, sparclinux@vger.kernel.org, Christian Brauner Subject: [PATCH 2/3] sparc: share process creation helpers between sparc and sparc64 Date: Tue, 12 May 2020 19:15:26 +0200 Message-Id: <20200512171527.570109-3-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200512171527.570109-1-christian.brauner@ubuntu.com> References: <20200512171527.570109-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org As promised in the previous patch, this moves the process creation helpers into a common process.c file that is shared between sparc and sparc64. It allows us to get rid of quite a bit custom assembler and the to remove the separe 32bit specific sparc_do_fork() call. One thing to note, is that when clone() was called with a separate stack for the child the assembler would align it. But copy_thread() has always been doing that too so that line wasn't needed and can thus simply be removed. Cc: Arnd Bergmann Cc: "David S. Miller" Cc: Guo Ren Cc: linux-csky@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: sparclinux@vger.kernel.org Signed-off-by: Christian Brauner --- arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/entry.S | 29 +++------ arch/sparc/kernel/kernel.h | 7 +-- arch/sparc/kernel/process.c | 111 +++++++++++++++++++++++++++++++++ arch/sparc/kernel/process_32.c | 27 -------- arch/sparc/kernel/process_64.c | 97 ---------------------------- 6 files changed, 122 insertions(+), 150 deletions(-) create mode 100644 arch/sparc/kernel/process.c diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 97c0e19263d1..d3a0e072ebe8 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -33,6 +33,7 @@ obj-y += irq_$(BITS).o obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o obj-y += process_$(BITS).o +obj-y += process.o obj-y += signal_$(BITS).o obj-y += sigutil_$(BITS).o obj-$(CONFIG_SPARC32) += ioport.o diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 4d3696973325..7925e8e5092b 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -869,14 +869,11 @@ flush_patch_two: ld [%curptr + TI_TASK], %o4 rd %psr, %g4 WRITE_PAUSE - mov SIGCHLD, %o0 ! arg0: clone flags rd %wim, %g5 WRITE_PAUSE - mov %fp, %o1 ! arg1: usp std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] - add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr - mov 0, %o3 - call sparc_do_fork + add %sp, STACKFRAME_SZ, %o0 + call sparc_fork mov %l5, %o7 /* Whee, kernel threads! */ @@ -888,19 +885,11 @@ flush_patch_three: ld [%curptr + TI_TASK], %o4 rd %psr, %g4 WRITE_PAUSE - - /* arg0,1: flags,usp -- loaded already */ - cmp %o1, 0x0 ! Is new_usp NULL? rd %wim, %g5 WRITE_PAUSE - be,a 1f - mov %fp, %o1 ! yes, use callers usp - andn %o1, 7, %o1 ! no, align to 8 bytes -1: std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] - add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr - mov 0, %o3 - call sparc_do_fork + add %sp, STACKFRAME_SZ, %o0 + call sparc_clone mov %l5, %o7 /* Whee, real vfork! */ @@ -914,13 +903,9 @@ flush_patch_four: rd %wim, %g5 WRITE_PAUSE std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] - sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 - mov %fp, %o1 - or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 - sethi %hi(sparc_do_fork), %l1 - mov 0, %o3 - jmpl %l1 + %lo(sparc_do_fork), %g0 - add %sp, STACKFRAME_SZ, %o2 + sethi %hi(sparc_vfork), %l1 + jmpl %l1 + %lo(sparc_vfork), %g0 + add %sp, STACKFRAME_SZ, %o0 .align 4 linux_sparc_ni_syscall: diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index f6f498ba3198..3529e16ece20 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -154,10 +154,9 @@ extern unsigned long sun4m_cpu_startup; extern unsigned long sun4d_cpu_startup; /* process_32.c */ -asmlinkage int sparc_do_fork(unsigned long clone_flags, - unsigned long stack_start, - struct pt_regs *regs, - unsigned long stack_size); +asmlinkage int sparc_clone(struct pt_regs *regs); +asmlinkage int sparc_fork(struct pt_regs *regs); +asmlinkage int sparc_vfork(struct pt_regs *regs); /* signal_32.c */ asmlinkage void do_sigreturn(struct pt_regs *regs); diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c new file mode 100644 index 000000000000..9d81edafbad5 --- /dev/null +++ b/arch/sparc/kernel/process.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * This file handles the architecture independent parts of process handling.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage long sparc_fork(struct pt_regs *regs) +{ + unsigned long orig_i1 = regs->u_regs[UREG_I1]; + long ret; + struct kernel_clone_args args = { + .exit_signal = SIGCHLD, + /* Reuse the parent's stack for the child. */ + .stack = regs->u_regs[UREG_FP], + }; + + ret = _do_fork(&args); + + /* If we get an error and potentially restart the system + * call, we're screwed because copy_thread_tls() clobbered + * the parent's %o1. So detect that case and restore it + * here. + */ + if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + regs->u_regs[UREG_I1] = orig_i1; + + return ret; +} + +asmlinkage long sparc_vfork(struct pt_regs *regs) +{ + unsigned long orig_i1 = regs->u_regs[UREG_I1]; + long ret; + + struct kernel_clone_args args = { + .flags = CLONE_VFORK | CLONE_VM, + .exit_signal = SIGCHLD, + /* Reuse the parent's stack for the child. */ + .stack = regs->u_regs[UREG_FP], + }; + + ret = _do_fork(&args); + + /* If we get an error and potentially restart the system + * call, we're screwed because copy_thread_tls() clobbered + * the parent's %o1. So detect that case and restore it + * here. + */ + if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + regs->u_regs[UREG_I1] = orig_i1; + + return ret; +} + +asmlinkage long sparc_clone(struct pt_regs *regs) +{ + unsigned long orig_i1 = regs->u_regs[UREG_I1]; + unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); + long ret; + + struct kernel_clone_args args = { + .flags = (flags & ~CSIGNAL), + .exit_signal = (flags & CSIGNAL), + .tls = regs->u_regs[UREG_I3], + }; + +#ifdef CONFIG_COMPAT + if (test_thread_flag(TIF_32BIT)) { + args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); + args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); + args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); + } else +#endif + { + args.pidfd = (int __user *)regs->u_regs[UREG_I2]; + args.child_tid = (int __user *)regs->u_regs[UREG_I4]; + args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; + } + + /* Did userspace give setup a separate stack for the child or are we + * reusing the parent's? + */ + if (regs->u_regs[UREG_I1]) + args.stack = regs->u_regs[UREG_I1]; + else + args.stack = regs->u_regs[UREG_FP]; + + if (!legacy_clone_args_valid(&args)) + return -EINVAL; + + ret = _do_fork(&args); + + /* If we get an error and potentially restart the system + * call, we're screwed because copy_thread_tls() clobbered + * the parent's %o1. So detect that case and restore it + * here. + */ + if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) + regs->u_regs[UREG_I1] = orig_i1; + + return ret; +} diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 26cca65e9246..9c510e6625aa 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -258,33 +258,6 @@ clone_stackframe(struct sparc_stackf __user *dst, return sp; } -asmlinkage int sparc_do_fork(unsigned long clone_flags, - unsigned long stack_start, - struct pt_regs *regs, - unsigned long stack_size) -{ - unsigned long parent_tid_ptr, child_tid_ptr; - unsigned long orig_i1 = regs->u_regs[UREG_I1]; - long ret; - - parent_tid_ptr = regs->u_regs[UREG_I2]; - child_tid_ptr = regs->u_regs[UREG_I4]; - - ret = do_fork(clone_flags, stack_start, stack_size, - (int __user *) parent_tid_ptr, - (int __user *) child_tid_ptr); - - /* If we get an error and potentially restart the system - * call, we're screwed because copy_thread() clobbered - * the parent's %o1. So detect that case and restore it - * here. - */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) - regs->u_regs[UREG_I1] = orig_i1; - - return ret; -} - /* Copy a Sparc thread. The fork() return value conventions * under SunOS are nothing short of bletcherous: * Parent --> %o0 == childs pid, %o1 == 0 diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 0222f638bdb2..309e17f3d01c 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -573,103 +573,6 @@ void fault_in_user_windows(struct pt_regs *regs) force_sig(SIGSEGV); } -asmlinkage long sparc_fork(struct pt_regs *regs) -{ - unsigned long orig_i1 = regs->u_regs[UREG_I1]; - long ret; - struct kernel_clone_args args = { - .exit_signal = SIGCHLD, - /* Reuse the parent's stack for the child. */ - .stack = regs->u_regs[UREG_FP], - }; - - ret = _do_fork(&args); - - /* If we get an error and potentially restart the system - * call, we're screwed because copy_thread_tls() clobbered - * the parent's %o1. So detect that case and restore it - * here. - */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) - regs->u_regs[UREG_I1] = orig_i1; - - return ret; -} - -asmlinkage long sparc_vfork(struct pt_regs *regs) -{ - unsigned long orig_i1 = regs->u_regs[UREG_I1]; - long ret; - - struct kernel_clone_args args = { - .flags = CLONE_VFORK | CLONE_VM, - .exit_signal = SIGCHLD, - /* Reuse the parent's stack for the child. */ - .stack = regs->u_regs[UREG_FP], - }; - - ret = _do_fork(&args); - - /* If we get an error and potentially restart the system - * call, we're screwed because copy_thread_tls() clobbered - * the parent's %o1. So detect that case and restore it - * here. - */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) - regs->u_regs[UREG_I1] = orig_i1; - - return ret; -} - -asmlinkage long sparc_clone(struct pt_regs *regs) -{ - unsigned long orig_i1 = regs->u_regs[UREG_I1]; - unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); - long ret; - - struct kernel_clone_args args = { - .flags = (flags & ~CSIGNAL), - .exit_signal = (flags & CSIGNAL), - .tls = regs->u_regs[UREG_I3], - }; - -#ifdef CONFIG_COMPAT - if (test_thread_flag(TIF_32BIT)) { - args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); - args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); - args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); - } else -#endif - { - args.pidfd = (int __user *)regs->u_regs[UREG_I2]; - args.child_tid = (int __user *)regs->u_regs[UREG_I4]; - args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; - } - - /* Did userspace setup a separate stack for the child or are we - * copying the parent's? - */ - if (regs->u_regs[UREG_I1]) - args.stack = regs->u_regs[UREG_I1]; - else - args.stack = regs->u_regs[UREG_FP]; - - if (!legacy_clone_args_valid(&args)) - return -EINVAL; - - ret = _do_fork(&args); - - /* If we get an error and potentially restart the system - * call, we're screwed because copy_thread_tls() clobbered - * the parent's %o1. So detect that case and restore it - * here. - */ - if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) - regs->u_regs[UREG_I1] = orig_i1; - - return ret; -} - /* Copy a Sparc thread. The fork() return value conventions * under SunOS are nothing short of bletcherous: * Parent --> %o0 == childs pid, %o1 == 0 -- 2.26.2