mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									bfc7931c40
								
							
						
					
					
						commit
						6aabc1facd
					
				
					 2 changed files with 23 additions and 9 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue