162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * This file handles the architecture independent parts of process handling.. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/compat.h> 862306a36Sopenharmony_ci#include <linux/errno.h> 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/ptrace.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/sched/task.h> 1362306a36Sopenharmony_ci#include <linux/sched/task_stack.h> 1462306a36Sopenharmony_ci#include <linux/signal.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "kernel.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciasmlinkage long sparc_fork(struct pt_regs *regs) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci unsigned long orig_i1 = regs->u_regs[UREG_I1]; 2162306a36Sopenharmony_ci long ret; 2262306a36Sopenharmony_ci struct kernel_clone_args args = { 2362306a36Sopenharmony_ci .exit_signal = SIGCHLD, 2462306a36Sopenharmony_ci /* Reuse the parent's stack for the child. */ 2562306a36Sopenharmony_ci .stack = regs->u_regs[UREG_FP], 2662306a36Sopenharmony_ci }; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci ret = kernel_clone(&args); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* If we get an error and potentially restart the system 3162306a36Sopenharmony_ci * call, we're screwed because copy_thread() clobbered 3262306a36Sopenharmony_ci * the parent's %o1. So detect that case and restore it 3362306a36Sopenharmony_ci * here. 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_ci if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 3662306a36Sopenharmony_ci regs->u_regs[UREG_I1] = orig_i1; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci return ret; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciasmlinkage long sparc_vfork(struct pt_regs *regs) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci unsigned long orig_i1 = regs->u_regs[UREG_I1]; 4462306a36Sopenharmony_ci long ret; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci struct kernel_clone_args args = { 4762306a36Sopenharmony_ci .flags = CLONE_VFORK | CLONE_VM, 4862306a36Sopenharmony_ci .exit_signal = SIGCHLD, 4962306a36Sopenharmony_ci /* Reuse the parent's stack for the child. */ 5062306a36Sopenharmony_ci .stack = regs->u_regs[UREG_FP], 5162306a36Sopenharmony_ci }; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci ret = kernel_clone(&args); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* If we get an error and potentially restart the system 5662306a36Sopenharmony_ci * call, we're screwed because copy_thread() clobbered 5762306a36Sopenharmony_ci * the parent's %o1. So detect that case and restore it 5862306a36Sopenharmony_ci * here. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 6162306a36Sopenharmony_ci regs->u_regs[UREG_I1] = orig_i1; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci return ret; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciasmlinkage long sparc_clone(struct pt_regs *regs) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci unsigned long orig_i1 = regs->u_regs[UREG_I1]; 6962306a36Sopenharmony_ci unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); 7062306a36Sopenharmony_ci long ret; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci struct kernel_clone_args args = { 7362306a36Sopenharmony_ci .flags = (flags & ~CSIGNAL), 7462306a36Sopenharmony_ci .exit_signal = (flags & CSIGNAL), 7562306a36Sopenharmony_ci .tls = regs->u_regs[UREG_I3], 7662306a36Sopenharmony_ci }; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 7962306a36Sopenharmony_ci if (test_thread_flag(TIF_32BIT)) { 8062306a36Sopenharmony_ci args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); 8162306a36Sopenharmony_ci args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); 8262306a36Sopenharmony_ci args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); 8362306a36Sopenharmony_ci } else 8462306a36Sopenharmony_ci#endif 8562306a36Sopenharmony_ci { 8662306a36Sopenharmony_ci args.pidfd = (int __user *)regs->u_regs[UREG_I2]; 8762306a36Sopenharmony_ci args.child_tid = (int __user *)regs->u_regs[UREG_I4]; 8862306a36Sopenharmony_ci args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci /* Did userspace give setup a separate stack for the child or are we 9262306a36Sopenharmony_ci * reusing the parent's? 9362306a36Sopenharmony_ci */ 9462306a36Sopenharmony_ci if (regs->u_regs[UREG_I1]) 9562306a36Sopenharmony_ci args.stack = regs->u_regs[UREG_I1]; 9662306a36Sopenharmony_ci else 9762306a36Sopenharmony_ci args.stack = regs->u_regs[UREG_FP]; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci ret = kernel_clone(&args); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* If we get an error and potentially restart the system 10262306a36Sopenharmony_ci * call, we're screwed because copy_thread() clobbered 10362306a36Sopenharmony_ci * the parent's %o1. So detect that case and restore it 10462306a36Sopenharmony_ci * here. 10562306a36Sopenharmony_ci */ 10662306a36Sopenharmony_ci if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) 10762306a36Sopenharmony_ci regs->u_regs[UREG_I1] = orig_i1; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return ret; 11062306a36Sopenharmony_ci} 111