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 #include <linux/syscalls.h> 16 17 #include "kernel.h" 18 19 asmlinkage long sparc_fork(struct pt_regs *regs) 20 { 21 unsigned long orig_i1; 22 long ret; 23 struct kernel_clone_args args = { 24 .exit_signal = SIGCHLD, 25 }; 26 27 synchronize_user_stack(); 28 29 orig_i1 = regs->u_regs[UREG_I1]; 30 /* Reuse the parent's stack for the child. */ 31 args.stack = regs->u_regs[UREG_FP]; 32 33 ret = kernel_clone(&args); 34 35 /* If we get an error and potentially restart the system 36 * call, we're screwed because copy_thread() clobbered 37 * the parent's %o1. So detect that case and restore it 38 * here. 39 */ 40 if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 41 regs->u_regs[UREG_I1] = orig_i1; 42 43 return ret; 44 } 45 46 asmlinkage long sparc_vfork(struct pt_regs *regs) 47 { 48 unsigned long orig_i1; 49 long ret; 50 struct kernel_clone_args args = { 51 .flags = CLONE_VFORK | CLONE_VM, 52 .exit_signal = SIGCHLD, 53 }; 54 55 synchronize_user_stack(); 56 57 orig_i1 = regs->u_regs[UREG_I1]; 58 /* Reuse the parent's stack for the child. */ 59 args.stack = regs->u_regs[UREG_FP]; 60 61 ret = kernel_clone(&args); 62 63 /* If we get an error and potentially restart the system 64 * call, we're screwed because copy_thread() clobbered 65 * the parent's %o1. So detect that case and restore it 66 * here. 67 */ 68 if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 69 regs->u_regs[UREG_I1] = orig_i1; 70 71 return ret; 72 } 73 74 asmlinkage long sparc_clone(struct pt_regs *regs) 75 { 76 unsigned long orig_i1; 77 unsigned int flags; 78 long ret; 79 struct kernel_clone_args args = {0}; 80 81 synchronize_user_stack(); 82 83 orig_i1 = regs->u_regs[UREG_I1]; 84 flags = lower_32_bits(regs->u_regs[UREG_I0]); 85 args.flags = (flags & ~CSIGNAL); 86 args.exit_signal = (flags & CSIGNAL); 87 args.tls = regs->u_regs[UREG_I3]; 88 89 #ifdef CONFIG_COMPAT 90 if (test_thread_flag(TIF_32BIT)) { 91 args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); 92 args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); 93 args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); 94 } else 95 #endif 96 { 97 args.pidfd = (int __user *)regs->u_regs[UREG_I2]; 98 args.child_tid = (int __user *)regs->u_regs[UREG_I4]; 99 args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; 100 } 101 102 /* Did userspace give setup a separate stack for the child or are we 103 * reusing the parent's? 104 */ 105 if (regs->u_regs[UREG_I1]) 106 args.stack = regs->u_regs[UREG_I1]; 107 else 108 args.stack = regs->u_regs[UREG_FP]; 109 110 ret = kernel_clone(&args); 111 112 /* If we get an error and potentially restart the system 113 * call, we're screwed because copy_thread() clobbered 114 * the parent's %o1. So detect that case and restore it 115 * here. 116 */ 117 if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 118 regs->u_regs[UREG_I1] = orig_i1; 119 120 return ret; 121 } 122 123 asmlinkage long sparc_clone3(struct pt_regs *regs) 124 { 125 unsigned long sz; 126 struct clone_args __user *cl_args; 127 128 synchronize_user_stack(); 129 130 cl_args = (struct clone_args __user *)regs->u_regs[UREG_I0]; 131 sz = regs->u_regs[UREG_I1]; 132 133 return sys_clone3(cl_args, sz); 134 } 135