Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 
0003 /*
0004  * This file handles the architecture independent parts of process handling..
0005  */
0006 
0007 #include <linux/compat.h>
0008 #include <linux/errno.h>
0009 #include <linux/kernel.h>
0010 #include <linux/ptrace.h>
0011 #include <linux/sched.h>
0012 #include <linux/sched/task.h>
0013 #include <linux/sched/task_stack.h>
0014 #include <linux/signal.h>
0015 
0016 #include "kernel.h"
0017 
0018 asmlinkage long sparc_fork(struct pt_regs *regs)
0019 {
0020     unsigned long orig_i1 = regs->u_regs[UREG_I1];
0021     long ret;
0022     struct kernel_clone_args args = {
0023         .exit_signal    = SIGCHLD,
0024         /* Reuse the parent's stack for the child. */
0025         .stack      = regs->u_regs[UREG_FP],
0026     };
0027 
0028     ret = kernel_clone(&args);
0029 
0030     /* If we get an error and potentially restart the system
0031      * call, we're screwed because copy_thread() clobbered
0032      * the parent's %o1.  So detect that case and restore it
0033      * here.
0034      */
0035     if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
0036         regs->u_regs[UREG_I1] = orig_i1;
0037 
0038     return ret;
0039 }
0040 
0041 asmlinkage long sparc_vfork(struct pt_regs *regs)
0042 {
0043     unsigned long orig_i1 = regs->u_regs[UREG_I1];
0044     long ret;
0045 
0046     struct kernel_clone_args args = {
0047         .flags      = CLONE_VFORK | CLONE_VM,
0048         .exit_signal    = SIGCHLD,
0049         /* Reuse the parent's stack for the child. */
0050         .stack      = regs->u_regs[UREG_FP],
0051     };
0052 
0053     ret = kernel_clone(&args);
0054 
0055     /* If we get an error and potentially restart the system
0056      * call, we're screwed because copy_thread() clobbered
0057      * the parent's %o1.  So detect that case and restore it
0058      * here.
0059      */
0060     if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
0061         regs->u_regs[UREG_I1] = orig_i1;
0062 
0063     return ret;
0064 }
0065 
0066 asmlinkage long sparc_clone(struct pt_regs *regs)
0067 {
0068     unsigned long orig_i1 = regs->u_regs[UREG_I1];
0069     unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]);
0070     long ret;
0071 
0072     struct kernel_clone_args args = {
0073         .flags      = (flags & ~CSIGNAL),
0074         .exit_signal    = (flags & CSIGNAL),
0075         .tls        = regs->u_regs[UREG_I3],
0076     };
0077 
0078 #ifdef CONFIG_COMPAT
0079     if (test_thread_flag(TIF_32BIT)) {
0080         args.pidfd  = compat_ptr(regs->u_regs[UREG_I2]);
0081         args.child_tid  = compat_ptr(regs->u_regs[UREG_I4]);
0082         args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]);
0083     } else
0084 #endif
0085     {
0086         args.pidfd  = (int __user *)regs->u_regs[UREG_I2];
0087         args.child_tid  = (int __user *)regs->u_regs[UREG_I4];
0088         args.parent_tid = (int __user *)regs->u_regs[UREG_I2];
0089     }
0090 
0091     /* Did userspace give setup a separate stack for the child or are we
0092      * reusing the parent's?
0093      */
0094     if (regs->u_regs[UREG_I1])
0095         args.stack = regs->u_regs[UREG_I1];
0096     else
0097         args.stack = regs->u_regs[UREG_FP];
0098 
0099     ret = kernel_clone(&args);
0100 
0101     /* If we get an error and potentially restart the system
0102      * call, we're screwed because copy_thread() clobbered
0103      * the parent's %o1.  So detect that case and restore it
0104      * here.
0105      */
0106     if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK)
0107         regs->u_regs[UREG_I1] = orig_i1;
0108 
0109     return ret;
0110 }