Merge tag 'at24-fixes-for-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / arch / sparc / kernel / process.c
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 }