.. | .. |
---|
30 | 30 | #include <linux/init_task.h> |
---|
31 | 31 | #include <linux/mqueue.h> |
---|
32 | 32 | #include <linux/rcupdate.h> |
---|
33 | | - |
---|
| 33 | +#include <linux/syscalls.h> |
---|
34 | 34 | #include <linux/uaccess.h> |
---|
| 35 | + |
---|
35 | 36 | #include <asm/traps.h> |
---|
36 | 37 | #include <asm/machdep.h> |
---|
37 | 38 | #include <asm/setup.h> |
---|
38 | | -#include <asm/pgtable.h> |
---|
39 | 39 | |
---|
40 | 40 | |
---|
41 | 41 | asmlinkage void ret_from_fork(void); |
---|
.. | .. |
---|
107 | 107 | * on top of pt_regs, which means that sys_clone() arguments would be |
---|
108 | 108 | * buried. We could, of course, copy them, but it's too costly for no |
---|
109 | 109 | * good reason - generic clone() would have to copy them *again* for |
---|
110 | | - * do_fork() anyway. So in this case it's actually better to pass pt_regs * |
---|
111 | | - * and extract arguments for do_fork() from there. Eventually we might |
---|
112 | | - * go for calling do_fork() directly from the wrapper, but only after we |
---|
113 | | - * are finished with do_fork() prototype conversion. |
---|
| 110 | + * kernel_clone() anyway. So in this case it's actually better to pass pt_regs * |
---|
| 111 | + * and extract arguments for kernel_clone() from there. Eventually we might |
---|
| 112 | + * go for calling kernel_clone() directly from the wrapper, but only after we |
---|
| 113 | + * are finished with kernel_clone() prototype conversion. |
---|
114 | 114 | */ |
---|
115 | 115 | asmlinkage int m68k_clone(struct pt_regs *regs) |
---|
116 | 116 | { |
---|
117 | 117 | /* regs will be equal to current_pt_regs() */ |
---|
118 | | - return do_fork(regs->d1, regs->d2, 0, |
---|
119 | | - (int __user *)regs->d3, (int __user *)regs->d4); |
---|
| 118 | + struct kernel_clone_args args = { |
---|
| 119 | + .flags = regs->d1 & ~CSIGNAL, |
---|
| 120 | + .pidfd = (int __user *)regs->d3, |
---|
| 121 | + .child_tid = (int __user *)regs->d4, |
---|
| 122 | + .parent_tid = (int __user *)regs->d3, |
---|
| 123 | + .exit_signal = regs->d1 & CSIGNAL, |
---|
| 124 | + .stack = regs->d2, |
---|
| 125 | + .tls = regs->d5, |
---|
| 126 | + }; |
---|
| 127 | + |
---|
| 128 | + return kernel_clone(&args); |
---|
120 | 129 | } |
---|
121 | 130 | |
---|
122 | | -int copy_thread(unsigned long clone_flags, unsigned long usp, |
---|
123 | | - unsigned long arg, struct task_struct *p) |
---|
| 131 | +/* |
---|
| 132 | + * Because extra registers are saved on the stack after the sys_clone3() |
---|
| 133 | + * arguments, this C wrapper extracts them from pt_regs * and then calls the |
---|
| 134 | + * generic sys_clone3() implementation. |
---|
| 135 | + */ |
---|
| 136 | +asmlinkage int m68k_clone3(struct pt_regs *regs) |
---|
| 137 | +{ |
---|
| 138 | + return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); |
---|
| 139 | +} |
---|
| 140 | + |
---|
| 141 | +int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
---|
| 142 | + struct task_struct *p, unsigned long tls) |
---|
124 | 143 | { |
---|
125 | 144 | struct fork_frame { |
---|
126 | 145 | struct switch_stack sw; |
---|
.. | .. |
---|
138 | 157 | */ |
---|
139 | 158 | p->thread.fs = get_fs().seg; |
---|
140 | 159 | |
---|
141 | | - if (unlikely(p->flags & PF_KTHREAD)) { |
---|
| 160 | + if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { |
---|
142 | 161 | /* kernel thread */ |
---|
143 | 162 | memset(frame, 0, sizeof(struct fork_frame)); |
---|
144 | 163 | frame->regs.sr = PS_S; |
---|
.. | .. |
---|
155 | 174 | p->thread.usp = usp ?: rdusp(); |
---|
156 | 175 | |
---|
157 | 176 | if (clone_flags & CLONE_SETTLS) |
---|
158 | | - task_thread_info(p)->tp_value = frame->regs.d5; |
---|
| 177 | + task_thread_info(p)->tp_value = tls; |
---|
159 | 178 | |
---|
160 | 179 | #ifdef CONFIG_FPU |
---|
161 | 180 | if (!FPU_IS_EMU) { |
---|