aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
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
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')
-rw-r--r--arch/powerpc/kernel/entry_32.S16
-rw-r--r--arch/powerpc/kernel/entry_64.S16
-rw-r--r--arch/powerpc/kernel/misc.S7
-rw-r--r--arch/powerpc/kernel/misc_32.S33
-rw-r--r--arch/powerpc/kernel/misc_64.S34
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c1
-rw-r--r--arch/powerpc/kernel/process.c59
-rw-r--r--arch/powerpc/kernel/signal_32.c1
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c22
9 files changed, 59 insertions, 130 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index af37528da49f..9499385676e7 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -435,6 +435,22 @@ ret_from_fork:
435 li r3,0 435 li r3,0
436 b ret_from_syscall 436 b ret_from_syscall
437 437
438 .globl ret_from_kernel_thread
439ret_from_kernel_thread:
440 REST_NVGPRS(r1)
441 bl schedule_tail
442 mtlr r14
443 mr r3,r15
444 PPC440EP_ERR42
445 blrl
446 li r3,0
447 b do_exit # no return
448
449 .globl __ret_from_kernel_execve
450__ret_from_kernel_execve:
451 addi r1,r3,-STACK_FRAME_OVERHEAD
452 b ret_from_syscall
453
438/* Traced system call support */ 454/* Traced system call support */
439syscall_dotrace: 455syscall_dotrace:
440 SAVE_NVGPRS(r1) 456 SAVE_NVGPRS(r1)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 0e931aaffca2..56e0ff0878b5 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -370,6 +370,22 @@ _GLOBAL(ret_from_fork)
370 li r3,0 370 li r3,0
371 b syscall_exit 371 b syscall_exit
372 372
373_GLOBAL(ret_from_kernel_thread)
374 bl .schedule_tail
375 REST_NVGPRS(r1)
376 REST_GPR(2,r1)
377 mtlr r14
378 mr r3,r15
379 blrl
380 li r3,0
381 b .do_exit # no return
382
383_GLOBAL(__ret_from_kernel_execve)
384 addi r1,r3,-STACK_FRAME_OVERHEAD
385 li r10,1
386 std r10,SOFTE(r1)
387 b syscall_exit
388
373 .section ".toc","aw" 389 .section ".toc","aw"
374DSCR_DEFAULT: 390DSCR_DEFAULT:
375 .tc dscr_default[TC],dscr_default 391 .tc dscr_default[TC],dscr_default
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index ba16874fe294..7ce26d45777e 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -54,13 +54,6 @@ _GLOBAL(add_reloc_offset)
54 .align 3 54 .align 3
552: PPC_LONG 1b 552: PPC_LONG 1b
56 56
57_GLOBAL(kernel_execve)
58 li r0,__NR_execve
59 sc
60 bnslr
61 neg r3,r3
62 blr
63
64_GLOBAL(setjmp) 57_GLOBAL(setjmp)
65 mflr r0 58 mflr r0
66 PPC_STL r0,0(r3) 59 PPC_STL r0,0(r3)
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 407e293aad2f..19e096bd0e73 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -663,39 +663,6 @@ _GLOBAL(abs)
663 sub r3,r3,r4 663 sub r3,r3,r4
664 blr 664 blr
665 665
666/*
667 * Create a kernel thread
668 * kernel_thread(fn, arg, flags)
669 */
670_GLOBAL(kernel_thread)
671 stwu r1,-16(r1)
672 stw r30,8(r1)
673 stw r31,12(r1)
674 mr r30,r3 /* function */
675 mr r31,r4 /* argument */
676 ori r3,r5,CLONE_VM /* flags */
677 oris r3,r3,CLONE_UNTRACED>>16
678 li r4,0 /* new sp (unused) */
679 li r0,__NR_clone
680 sc
681 bns+ 1f /* did system call indicate error? */
682 neg r3,r3 /* if so, make return code negative */
6831: cmpwi 0,r3,0 /* parent or child? */
684 bne 2f /* return if parent */
685 li r0,0 /* make top-level stack frame */
686 stwu r0,-16(r1)
687 mtlr r30 /* fn addr in lr */
688 mr r3,r31 /* load arg and call fn */
689 PPC440EP_ERR42
690 blrl
691 li r0,__NR_exit /* exit if function returns */
692 li r3,0
693 sc
6942: lwz r30,8(r1)
695 lwz r31,12(r1)
696 addi r1,r1,16
697 blr
698
699#ifdef CONFIG_SMP 666#ifdef CONFIG_SMP
700_GLOBAL(start_secondary_resume) 667_GLOBAL(start_secondary_resume)
701 /* Reset stack */ 668 /* Reset stack */
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 565b78625a32..5cfa8008693b 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -407,40 +407,6 @@ _GLOBAL(scom970_write)
407 407
408 408
409/* 409/*
410 * Create a kernel thread
411 * kernel_thread(fn, arg, flags)
412 */
413_GLOBAL(kernel_thread)
414 std r29,-24(r1)
415 std r30,-16(r1)
416 stdu r1,-STACK_FRAME_OVERHEAD(r1)
417 mr r29,r3
418 mr r30,r4
419 ori r3,r5,CLONE_VM /* flags */
420 oris r3,r3,(CLONE_UNTRACED>>16)
421 li r4,0 /* new sp (unused) */
422 li r0,__NR_clone
423 sc
424 bns+ 1f /* did system call indicate error? */
425 neg r3,r3 /* if so, make return code negative */
4261: cmpdi 0,r3,0 /* parent or child? */
427 bne 2f /* return if parent */
428 li r0,0
429 stdu r0,-STACK_FRAME_OVERHEAD(r1)
430 ld r2,8(r29)
431 ld r29,0(r29)
432 mtlr r29 /* fn addr in lr */
433 mr r3,r30 /* load arg and call fn */
434 blrl
435 li r0,__NR_exit /* exit after child exits */
436 li r3,0
437 sc
4382: addi r1,r1,STACK_FRAME_OVERHEAD
439 ld r29,-24(r1)
440 ld r30,-16(r1)
441 blr
442
443/*
444 * disable_kernel_fp() 410 * disable_kernel_fp()
445 * Disable the FPU. 411 * Disable the FPU.
446 */ 412 */
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 3e4031581c65..19e4288d8486 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -94,7 +94,6 @@ EXPORT_SYMBOL(pci_dram_offset);
94#endif /* CONFIG_PCI */ 94#endif /* CONFIG_PCI */
95 95
96EXPORT_SYMBOL(start_thread); 96EXPORT_SYMBOL(start_thread);
97EXPORT_SYMBOL(kernel_thread);
98 97
99EXPORT_SYMBOL(giveup_fpu); 98EXPORT_SYMBOL(giveup_fpu);
100#ifdef CONFIG_ALTIVEC 99#ifdef CONFIG_ALTIVEC
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,
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 8b4c049aee20..804e323c139d 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -35,7 +35,6 @@
35#include <linux/stddef.h> 35#include <linux/stddef.h>
36#include <linux/tty.h> 36#include <linux/tty.h>
37#include <linux/binfmts.h> 37#include <linux/binfmts.h>
38#include <linux/freezer.h>
39#endif 38#endif
40 39
41#include <asm/uaccess.h> 40#include <asm/uaccess.h>
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index abd1112da54f..9c2ed90ece8f 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -156,28 +156,6 @@ asmlinkage long compat_sys_sendfile64_wrapper(u32 out_fd, u32 in_fd,
156 (off_t __user *)offset, count); 156 (off_t __user *)offset, count);
157} 157}
158 158
159long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
160 unsigned long a3, unsigned long a4, unsigned long a5,
161 struct pt_regs *regs)
162{
163 int error;
164 char * filename;
165
166 filename = getname((char __user *) a0);
167 error = PTR_ERR(filename);
168 if (IS_ERR(filename))
169 goto out;
170 flush_fp_to_thread(current);
171 flush_altivec_to_thread(current);
172
173 error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
174
175 putname(filename);
176
177out:
178 return error;
179}
180
181/* Note: it is necessary to treat option as an unsigned int, 159/* Note: it is necessary to treat option as an unsigned int,
182 * with the corresponding cast to a signed int to insure that the 160 * with the corresponding cast to a signed int to insure that the
183 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) 161 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)