| .. | .. |
|---|
| 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) { |
|---|