aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/process.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:49:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:49:08 -0400
commit8213a2f3eeafdecf06dd718cb4130372263f6067 (patch)
tree0d02e3201dac64d1429f8552ee1163d4a1ef1646 /arch/powerpc/kernel/process.c
parent40924754f2cabd5d9af4bcd4dcecc362b5e0baa1 (diff)
parent12f79be93d94698778ff2b3f921073fc5f6780d6 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull pile 2 of execve and kernel_thread unification work from Al Viro: "Stuff in there: kernel_thread/kernel_execve/sys_execve conversions for several more architectures plus assorted signal fixes and cleanups. There'll be more (in particular, real fixes for the alpha do_notify_resume() irq mess)..." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (43 commits) alpha: don't open-code trace_report_syscall_{enter,exit} Uninclude linux/freezer.h m32r: trim masks avr32: trim masks tile: don't bother with SIGTRAP in setup_frame microblaze: don't bother with SIGTRAP in setup_rt_frame() mn10300: don't bother with SIGTRAP in setup_frame() frv: no need to raise SIGTRAP in setup_frame() x86: get rid of duplicate code in case of CONFIG_VM86 unicore32: remove pointless test h8300: trim _TIF_WORK_MASK parisc: decide whether to go to slow path (tracesys) based on thread flags parisc: don't bother looping in do_signal() parisc: fix double restarts bury the rest of TIF_IRET sanitize tsk_is_polling() bury _TIF_RESTORE_SIGMASK unicore32: unobfuscate _TIF_WORK_MASK mips: NOTIFY_RESUME is not needed in TIF masks mips: merge the identical "return from syscall" per-ABI code ... Conflicts: arch/arm/include/asm/thread_info.h
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r--arch/powerpc/kernel/process.c59
1 files changed, 27 insertions, 32 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index d5ad666efd8b..ba48233500f6 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -733,30 +733,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
733extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ 733extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
734 734
735int copy_thread(unsigned long clone_flags, unsigned long usp, 735int copy_thread(unsigned long clone_flags, unsigned long usp,
736 unsigned long unused, struct task_struct *p, 736 unsigned long arg, struct task_struct *p,
737 struct pt_regs *regs) 737 struct pt_regs *regs)
738{ 738{
739 struct pt_regs *childregs, *kregs; 739 struct pt_regs *childregs, *kregs;
740 extern void ret_from_fork(void); 740 extern void ret_from_fork(void);
741 extern void ret_from_kernel_thread(void);
742 void (*f)(void);
741 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 743 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
742 744
743 CHECK_FULL_REGS(regs);
744 /* Copy registers */ 745 /* Copy registers */
745 sp -= sizeof(struct pt_regs); 746 sp -= sizeof(struct pt_regs);
746 childregs = (struct pt_regs *) sp; 747 childregs = (struct pt_regs *) sp;
747 *childregs = *regs; 748 if (!regs) {
748 if ((childregs->msr & MSR_PR) == 0) {
749 /* for kernel thread, set `current' and stackptr in new task */ 749 /* for kernel thread, set `current' and stackptr in new task */
750 memset(childregs, 0, sizeof(struct pt_regs));
750 childregs->gpr[1] = sp + sizeof(struct pt_regs); 751 childregs->gpr[1] = sp + sizeof(struct pt_regs);
751#ifdef CONFIG_PPC32 752#ifdef CONFIG_PPC64
752 childregs->gpr[2] = (unsigned long) p; 753 childregs->gpr[14] = *(unsigned long *)usp;
753#else 754 childregs->gpr[2] = ((unsigned long *)usp)[1],
754 clear_tsk_thread_flag(p, TIF_32BIT); 755 clear_tsk_thread_flag(p, TIF_32BIT);
756#else
757 childregs->gpr[14] = usp; /* function */
758 childregs->gpr[2] = (unsigned long) p;
755#endif 759#endif
760 childregs->gpr[15] = arg;
756 p->thread.regs = NULL; /* no user register state */ 761 p->thread.regs = NULL; /* no user register state */
762 f = ret_from_kernel_thread;
757 } else { 763 } else {
764 CHECK_FULL_REGS(regs);
765 *childregs = *regs;
758 childregs->gpr[1] = usp; 766 childregs->gpr[1] = usp;
759 p->thread.regs = childregs; 767 p->thread.regs = childregs;
768 childregs->gpr[3] = 0; /* Result from fork() */
760 if (clone_flags & CLONE_SETTLS) { 769 if (clone_flags & CLONE_SETTLS) {
761#ifdef CONFIG_PPC64 770#ifdef CONFIG_PPC64
762 if (!is_32bit_task()) 771 if (!is_32bit_task())
@@ -765,8 +774,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
765#endif 774#endif
766 childregs->gpr[2] = childregs->gpr[6]; 775 childregs->gpr[2] = childregs->gpr[6];
767 } 776 }
777
778 f = ret_from_fork;
768 } 779 }
769 childregs->gpr[3] = 0; /* Result from fork() */
770 sp -= STACK_FRAME_OVERHEAD; 780 sp -= STACK_FRAME_OVERHEAD;
771 781
772 /* 782 /*
@@ -805,19 +815,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
805 p->thread.dscr = current->thread.dscr; 815 p->thread.dscr = current->thread.dscr;
806 } 816 }
807#endif 817#endif
808
809 /* 818 /*
810 * The PPC64 ABI makes use of a TOC to contain function 819 * The PPC64 ABI makes use of a TOC to contain function
811 * pointers. The function (ret_from_except) is actually a pointer 820 * pointers. The function (ret_from_except) is actually a pointer
812 * to the TOC entry. The first entry is a pointer to the actual 821 * to the TOC entry. The first entry is a pointer to the actual
813 * function. 822 * function.
814 */ 823 */
815#ifdef CONFIG_PPC64 824#ifdef CONFIG_PPC64
816 kregs->nip = *((unsigned long *)ret_from_fork); 825 kregs->nip = *((unsigned long *)f);
817#else 826#else
818 kregs->nip = (unsigned long)ret_from_fork; 827 kregs->nip = (unsigned long)f;
819#endif 828#endif
820
821 return 0; 829 return 0;
822} 830}
823 831
@@ -1055,26 +1063,13 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
1055 regs, 0, NULL, NULL); 1063 regs, 0, NULL, NULL);
1056} 1064}
1057 1065
1058int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, 1066void __ret_from_kernel_execve(struct pt_regs *normal)
1059 unsigned long a3, unsigned long a4, unsigned long a5, 1067__noreturn;
1060 struct pt_regs *regs) 1068
1069void ret_from_kernel_execve(struct pt_regs *normal)
1061{ 1070{
1062 int error; 1071 set_thread_flag(TIF_RESTOREALL);
1063 char *filename; 1072 __ret_from_kernel_execve(normal);
1064
1065 filename = getname((const char __user *) a0);
1066 error = PTR_ERR(filename);
1067 if (IS_ERR(filename))
1068 goto out;
1069 flush_fp_to_thread(current);
1070 flush_altivec_to_thread(current);
1071 flush_spe_to_thread(current);
1072 error = do_execve(filename,
1073 (const char __user *const __user *) a1,
1074 (const char __user *const __user *) a2, regs);
1075 putname(filename);
1076out:
1077 return error;
1078} 1073}
1079 1074
1080static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, 1075static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,