diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2020-01-13 13:30:40 +0300 |
---|---|---|
committer | Geert Uytterhoeven <geert@linux-m68k.org> | 2020-01-14 12:43:38 +0300 |
commit | 6aabc1facdb24e837cfea755ba46a6be22a8860f (patch) | |
tree | de32333495deb4c07de2b1eedfa8d3b7c029bebf /arch/m68k | |
parent | bfc7931c40908a3e5575c527754ef4be2e24c83b (diff) | |
download | linux-6aabc1facdb24e837cfea755ba46a6be22a8860f.tar.xz |
m68k: Implement copy_thread_tls()
This is required for clone3(), which passes the TLS value through a
struct rather than a register.
As do_fork() is only available if CONFIG_HAVE_COPY_THREAD_TLS is set,
m68k_clone() must be changed to call _do_fork() directly.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
Acked-by: Greg Ungerer <gerg@linux-m68k.org>
Link: https://lore.kernel.org/r/20200113103040.23661-1-geert@linux-m68k.org
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/Kconfig | 1 | ||||
-rw-r--r-- | arch/m68k/kernel/process.c | 31 |
2 files changed, 23 insertions, 9 deletions
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 6663f1741798..6ad6cdac74b3 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig @@ -14,6 +14,7 @@ config M68K select HAVE_AOUT if MMU select HAVE_ASM_MODVERSIONS select HAVE_DEBUG_BUGVERBOSE + select HAVE_COPY_THREAD_TLS select GENERIC_IRQ_SHOW select GENERIC_ATOMIC64 select HAVE_UID16 diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 22e6b8f4f958..8f0d9140700f 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -108,16 +108,28 @@ void flush_thread(void) * on top of pt_regs, which means that sys_clone() arguments would be * buried. We could, of course, copy them, but it's too costly for no * good reason - generic clone() would have to copy them *again* for - * do_fork() anyway. So in this case it's actually better to pass pt_regs * - * and extract arguments for do_fork() from there. Eventually we might - * go for calling do_fork() directly from the wrapper, but only after we - * are finished with do_fork() prototype conversion. + * _do_fork() anyway. So in this case it's actually better to pass pt_regs * + * and extract arguments for _do_fork() from there. Eventually we might + * go for calling _do_fork() directly from the wrapper, but only after we + * are finished with _do_fork() prototype conversion. */ asmlinkage int m68k_clone(struct pt_regs *regs) { /* regs will be equal to current_pt_regs() */ - return do_fork(regs->d1, regs->d2, 0, - (int __user *)regs->d3, (int __user *)regs->d4); + struct kernel_clone_args args = { + .flags = regs->d1 & ~CSIGNAL, + .pidfd = (int __user *)regs->d3, + .child_tid = (int __user *)regs->d4, + .parent_tid = (int __user *)regs->d3, + .exit_signal = regs->d1 & CSIGNAL, + .stack = regs->d2, + .tls = regs->d5, + }; + + if (!legacy_clone_args_valid(&args)) + return -EINVAL; + + return _do_fork(&args); } /* @@ -130,8 +142,9 @@ asmlinkage int m68k_clone3(struct pt_regs *regs) return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); } -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) +int copy_thread_tls(unsigned long clone_flags, unsigned long usp, + unsigned long arg, struct task_struct *p, + unsigned long tls) { struct fork_frame { struct switch_stack sw; @@ -166,7 +179,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.usp = usp ?: rdusp(); if (clone_flags & CLONE_SETTLS) - task_thread_info(p)->tp_value = frame->regs.d5; + task_thread_info(p)->tp_value = tls; #ifdef CONFIG_FPU if (!FPU_IS_EMU) { |