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