From 138d1ce80ed96eff6638f454f0a1500a4aefd17b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 11 Oct 2012 08:41:43 -0400 Subject: powerpc: switch to saner kernel_execve() semantics Signed-off-by: Al Viro --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/unistd.h | 1 - arch/powerpc/kernel/entry_32.S | 5 ----- arch/powerpc/kernel/entry_64.S | 6 ------ arch/powerpc/kernel/process.c | 13 +++---------- 5 files changed, 4 insertions(+), 22 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a902a5c..5af5aa7 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -144,6 +144,7 @@ config PPC select GENERIC_KERNEL_THREAD select HAVE_MOD_ARCH_SPECIFIC select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_EXECVE config EARLY_PRINTK bool diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 921dce6..280068c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -56,7 +56,6 @@ #define __ARCH_WANT_COMPAT_SYS_SENDFILE #endif #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE /* * "Conditional" syscalls diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 9499385..d22e73e 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -444,11 +444,6 @@ ret_from_kernel_thread: PPC440EP_ERR42 blrl li r3,0 - b do_exit # no return - - .globl __ret_from_kernel_execve -__ret_from_kernel_execve: - addi r1,r3,-STACK_FRAME_OVERHEAD b ret_from_syscall /* Traced system call support */ diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 56e0ff0..2eb766a 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -378,12 +378,6 @@ _GLOBAL(ret_from_kernel_thread) mr r3,r15 blrl li r3,0 - b .do_exit # no return - -_GLOBAL(__ret_from_kernel_execve) - addi r1,r3,-STACK_FRAME_OVERHEAD - li r10,1 - std r10,SOFTE(r1) b syscall_exit .section ".toc","aw" diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index ba48233..9e685e2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -746,19 +746,21 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; if (!regs) { - /* for kernel thread, set `current' and stackptr in new task */ + struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] = sp + sizeof(struct pt_regs); #ifdef CONFIG_PPC64 childregs->gpr[14] = *(unsigned long *)usp; childregs->gpr[2] = ((unsigned long *)usp)[1], clear_tsk_thread_flag(p, TIF_32BIT); + childregs->softe = 1; #else childregs->gpr[14] = usp; /* function */ childregs->gpr[2] = (unsigned long) p; #endif childregs->gpr[15] = arg; p->thread.regs = NULL; /* no user register state */ + ti->flags |= _TIF_RESTOREALL; f = ret_from_kernel_thread; } else { CHECK_FULL_REGS(regs); @@ -1063,15 +1065,6 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, regs, 0, NULL, NULL); } -void __ret_from_kernel_execve(struct pt_regs *normal) -__noreturn; - -void ret_from_kernel_execve(struct pt_regs *normal) -{ - set_thread_flag(TIF_RESTOREALL); - __ret_from_kernel_execve(normal); -} - static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, unsigned long nbytes) { -- cgit v1.1 From 40792104b2550ee067f63c3ccc8ea04747dc5037 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 11 Oct 2012 10:10:35 -0400 Subject: powerpc: don't mess with r2 in copy_thread() and friends kernel_thread() callbacks are *not* in modules and are not going to be there. And it's not even read in ppc32 ret_from_kernel_thread(), so no need to bother with it there either. Signed-off-by: Al Viro --- arch/powerpc/kernel/entry_64.S | 1 - arch/powerpc/kernel/process.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2eb766a..8fdb051 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -373,7 +373,6 @@ _GLOBAL(ret_from_fork) _GLOBAL(ret_from_kernel_thread) bl .schedule_tail REST_NVGPRS(r1) - REST_GPR(2,r1) mtlr r14 mr r3,r15 blrl diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 9e685e2..7fc70f2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -751,12 +751,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, childregs->gpr[1] = sp + sizeof(struct pt_regs); #ifdef CONFIG_PPC64 childregs->gpr[14] = *(unsigned long *)usp; - childregs->gpr[2] = ((unsigned long *)usp)[1], clear_tsk_thread_flag(p, TIF_32BIT); childregs->softe = 1; #else childregs->gpr[14] = usp; /* function */ - childregs->gpr[2] = (unsigned long) p; #endif childregs->gpr[15] = arg; p->thread.regs = NULL; /* no user register state */ -- cgit v1.1 From 53b50f9483cce47d1a7aefd1c9f442c094a5b1f7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 21 Oct 2012 16:50:34 -0400 Subject: powerpc: take dereferencing to ret_from_kernel_thread() Signed-off-by: Al Viro --- arch/powerpc/kernel/entry_64.S | 1 + arch/powerpc/kernel/process.c | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 8fdb051..e9a906c 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -373,6 +373,7 @@ _GLOBAL(ret_from_fork) _GLOBAL(ret_from_kernel_thread) bl .schedule_tail REST_NVGPRS(r1) + ld r14, 0(r14) mtlr r14 mr r3,r15 blrl diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 7fc70f2..8c600c3 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -749,12 +749,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] = sp + sizeof(struct pt_regs); + childregs->gpr[14] = usp; /* function */ #ifdef CONFIG_PPC64 - childregs->gpr[14] = *(unsigned long *)usp; clear_tsk_thread_flag(p, TIF_32BIT); childregs->softe = 1; -#else - childregs->gpr[14] = usp; /* function */ #endif childregs->gpr[15] = arg; p->thread.regs = NULL; /* no user register state */ -- cgit v1.1 From 9d401279d682280a92db8193ede8415c34588207 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 21 Oct 2012 22:25:53 -0400 Subject: powerpc: don't bother with zero-extending arguments in sys_clone() ... since the syscall glue had been doing that for 9 years already. Signed-off-by: Al Viro --- arch/powerpc/kernel/process.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 8c600c3..471c52c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1025,8 +1025,6 @@ int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); } -#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) - int sys_clone(unsigned long clone_flags, unsigned long usp, int __user *parent_tidp, void __user *child_threadptr, int __user *child_tidp, int p6, @@ -1035,12 +1033,6 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, CHECK_FULL_REGS(regs); if (usp == 0) usp = regs->gpr[1]; /* stack pointer for child */ -#ifdef CONFIG_PPC64 - if (is_32bit_task()) { - parent_tidp = TRUNC_PTR(parent_tidp); - child_tidp = TRUNC_PTR(child_tidp); - } -#endif return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); } -- cgit v1.1 From 64c2f6596bd84b05a781baf034fdd56ce1192d36 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 21 Oct 2012 22:27:13 -0400 Subject: powerpc: don't bother with CHECK_FULL_REGS in sys_fork() et.al. copy_thread() will do it anyway. Signed-off-by: Al Viro --- arch/powerpc/kernel/process.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 471c52c..de9f032 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1030,7 +1030,6 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, int __user *child_tidp, int p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); if (usp == 0) usp = regs->gpr[1]; /* stack pointer for child */ return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); @@ -1040,7 +1039,6 @@ int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } @@ -1048,7 +1046,6 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - CHECK_FULL_REGS(regs); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } -- cgit v1.1 From ea516b11545afa5b1420621981c1411a62bef87e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 21 Oct 2012 22:28:43 -0400 Subject: powerpc: put the "zero usp means using parent's stack pointer" to copy_thread() simplifies callers, at that... Signed-off-by: Al Viro --- arch/powerpc/kernel/process.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index de9f032..3665d28 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -761,7 +761,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, } else { CHECK_FULL_REGS(regs); *childregs = *regs; - childregs->gpr[1] = usp; + if (usp) + childregs->gpr[1] = usp; p->thread.regs = childregs; childregs->gpr[3] = 0; /* Result from fork() */ if (clone_flags & CLONE_SETTLS) { @@ -1030,8 +1031,6 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, int __user *child_tidp, int p6, struct pt_regs *regs) { - if (usp == 0) - usp = regs->gpr[1]; /* stack pointer for child */ return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); } @@ -1039,14 +1038,14 @@ int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); + return do_fork(SIGCHLD, 0, regs, 0, NULL, NULL); } int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, regs, 0, NULL, NULL); } -- cgit v1.1 From ab75819d3942a34d151a34fd43f346d5d8a48148 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 21 Oct 2012 22:33:39 -0400 Subject: powerpc: make fork_idle() take the common "kernel thread" path in copy_thread() Signed-off-by: Al Viro --- arch/powerpc/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3665d28..f6d244d 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -745,7 +745,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, /* Copy registers */ sp -= sizeof(struct pt_regs); childregs = (struct pt_regs *) sp; - if (!regs) { + if (unlikely(p->flags & PF_KTHREAD)) { struct thread_info *ti = (void *)task_stack_page(p); memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] = sp + sizeof(struct pt_regs); -- cgit v1.1