1a4261d4bSChristian Brauner // SPDX-License-Identifier: GPL-2.0 2a4261d4bSChristian Brauner 3a4261d4bSChristian Brauner /* 4a4261d4bSChristian Brauner * This file handles the architecture independent parts of process handling.. 5a4261d4bSChristian Brauner */ 6a4261d4bSChristian Brauner 7a4261d4bSChristian Brauner #include <linux/compat.h> 8a4261d4bSChristian Brauner #include <linux/errno.h> 9a4261d4bSChristian Brauner #include <linux/kernel.h> 10a4261d4bSChristian Brauner #include <linux/ptrace.h> 11a4261d4bSChristian Brauner #include <linux/sched.h> 12a4261d4bSChristian Brauner #include <linux/sched/task.h> 13a4261d4bSChristian Brauner #include <linux/sched/task_stack.h> 14a4261d4bSChristian Brauner #include <linux/signal.h> 15a4261d4bSChristian Brauner 16a4261d4bSChristian Brauner #include "kernel.h" 17a4261d4bSChristian Brauner 18a4261d4bSChristian Brauner asmlinkage long sparc_fork(struct pt_regs *regs) 19a4261d4bSChristian Brauner { 20a4261d4bSChristian Brauner unsigned long orig_i1 = regs->u_regs[UREG_I1]; 21a4261d4bSChristian Brauner long ret; 22a4261d4bSChristian Brauner struct kernel_clone_args args = { 23a4261d4bSChristian Brauner .exit_signal = SIGCHLD, 24a4261d4bSChristian Brauner /* Reuse the parent's stack for the child. */ 25a4261d4bSChristian Brauner .stack = regs->u_regs[UREG_FP], 26a4261d4bSChristian Brauner }; 27a4261d4bSChristian Brauner 28a4261d4bSChristian Brauner ret = _do_fork(&args); 29a4261d4bSChristian Brauner 30a4261d4bSChristian Brauner /* If we get an error and potentially restart the system 31*714acdbdSChristian Brauner * call, we're screwed because copy_thread() clobbered 32a4261d4bSChristian Brauner * the parent's %o1. So detect that case and restore it 33a4261d4bSChristian Brauner * here. 34a4261d4bSChristian Brauner */ 35a4261d4bSChristian Brauner if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 36a4261d4bSChristian Brauner regs->u_regs[UREG_I1] = orig_i1; 37a4261d4bSChristian Brauner 38a4261d4bSChristian Brauner return ret; 39a4261d4bSChristian Brauner } 40a4261d4bSChristian Brauner 41a4261d4bSChristian Brauner asmlinkage long sparc_vfork(struct pt_regs *regs) 42a4261d4bSChristian Brauner { 43a4261d4bSChristian Brauner unsigned long orig_i1 = regs->u_regs[UREG_I1]; 44a4261d4bSChristian Brauner long ret; 45a4261d4bSChristian Brauner 46a4261d4bSChristian Brauner struct kernel_clone_args args = { 47a4261d4bSChristian Brauner .flags = CLONE_VFORK | CLONE_VM, 48a4261d4bSChristian Brauner .exit_signal = SIGCHLD, 49a4261d4bSChristian Brauner /* Reuse the parent's stack for the child. */ 50a4261d4bSChristian Brauner .stack = regs->u_regs[UREG_FP], 51a4261d4bSChristian Brauner }; 52a4261d4bSChristian Brauner 53a4261d4bSChristian Brauner ret = _do_fork(&args); 54a4261d4bSChristian Brauner 55a4261d4bSChristian Brauner /* If we get an error and potentially restart the system 56*714acdbdSChristian Brauner * call, we're screwed because copy_thread() clobbered 57a4261d4bSChristian Brauner * the parent's %o1. So detect that case and restore it 58a4261d4bSChristian Brauner * here. 59a4261d4bSChristian Brauner */ 60a4261d4bSChristian Brauner if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 61a4261d4bSChristian Brauner regs->u_regs[UREG_I1] = orig_i1; 62a4261d4bSChristian Brauner 63a4261d4bSChristian Brauner return ret; 64a4261d4bSChristian Brauner } 65a4261d4bSChristian Brauner 66a4261d4bSChristian Brauner asmlinkage long sparc_clone(struct pt_regs *regs) 67a4261d4bSChristian Brauner { 68a4261d4bSChristian Brauner unsigned long orig_i1 = regs->u_regs[UREG_I1]; 69a4261d4bSChristian Brauner unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); 70a4261d4bSChristian Brauner long ret; 71a4261d4bSChristian Brauner 72a4261d4bSChristian Brauner struct kernel_clone_args args = { 73a4261d4bSChristian Brauner .flags = (flags & ~CSIGNAL), 74a4261d4bSChristian Brauner .exit_signal = (flags & CSIGNAL), 75a4261d4bSChristian Brauner .tls = regs->u_regs[UREG_I3], 76a4261d4bSChristian Brauner }; 77a4261d4bSChristian Brauner 78a4261d4bSChristian Brauner #ifdef CONFIG_COMPAT 79a4261d4bSChristian Brauner if (test_thread_flag(TIF_32BIT)) { 80a4261d4bSChristian Brauner args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); 81a4261d4bSChristian Brauner args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); 82a4261d4bSChristian Brauner args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); 83a4261d4bSChristian Brauner } else 84a4261d4bSChristian Brauner #endif 85a4261d4bSChristian Brauner { 86a4261d4bSChristian Brauner args.pidfd = (int __user *)regs->u_regs[UREG_I2]; 87a4261d4bSChristian Brauner args.child_tid = (int __user *)regs->u_regs[UREG_I4]; 88a4261d4bSChristian Brauner args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; 89a4261d4bSChristian Brauner } 90a4261d4bSChristian Brauner 91a4261d4bSChristian Brauner /* Did userspace give setup a separate stack for the child or are we 92a4261d4bSChristian Brauner * reusing the parent's? 93a4261d4bSChristian Brauner */ 94a4261d4bSChristian Brauner if (regs->u_regs[UREG_I1]) 95a4261d4bSChristian Brauner args.stack = regs->u_regs[UREG_I1]; 96a4261d4bSChristian Brauner else 97a4261d4bSChristian Brauner args.stack = regs->u_regs[UREG_FP]; 98a4261d4bSChristian Brauner 99a4261d4bSChristian Brauner ret = _do_fork(&args); 100a4261d4bSChristian Brauner 101a4261d4bSChristian Brauner /* If we get an error and potentially restart the system 102*714acdbdSChristian Brauner * call, we're screwed because copy_thread() clobbered 103a4261d4bSChristian Brauner * the parent's %o1. So detect that case and restore it 104a4261d4bSChristian Brauner * here. 105a4261d4bSChristian Brauner */ 106a4261d4bSChristian Brauner if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 107a4261d4bSChristian Brauner regs->u_regs[UREG_I1] = orig_i1; 108a4261d4bSChristian Brauner 109a4261d4bSChristian Brauner return ret; 110a4261d4bSChristian Brauner } 111