aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-09-12 18:32:42 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-30 23:31:19 -0400
commit58254e1002a82eb383c5977ad9fd5a451b91fe29 (patch)
treee03b441b252ec3630ceedbe266311c0a24812fd9 /arch/powerpc
parentf322220d6159455da2b5a8a596d802c8695fed30 (diff)
powerpc: split ret_from_fork
... and get rid of in-kernel syscalls in kernel_thread() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/include/asm/processor.h3
-rw-r--r--arch/powerpc/kernel/entry_32.S11
-rw-r--r--arch/powerpc/kernel/entry_64.S10
-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.c34
8 files changed, 43 insertions, 84 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 352f416269ce..6e5a0979c085 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -139,6 +139,7 @@ config PPC
139 select GENERIC_CLOCKEVENTS 139 select GENERIC_CLOCKEVENTS
140 select GENERIC_STRNCPY_FROM_USER 140 select GENERIC_STRNCPY_FROM_USER
141 select GENERIC_STRNLEN_USER 141 select GENERIC_STRNLEN_USER
142 select GENERIC_KERNEL_THREAD
142 143
143config EARLY_PRINTK 144config EARLY_PRINTK
144 bool 145 bool
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 54b73a28c205..5376453d90cc 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -74,9 +74,6 @@ struct task_struct;
74void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); 74void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
75void release_thread(struct task_struct *); 75void release_thread(struct task_struct *);
76 76
77/* Create a new kernel thread. */
78extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
79
80/* Lazy FPU handling on uni-processor */ 77/* Lazy FPU handling on uni-processor */
81extern struct task_struct *last_task_used_math; 78extern struct task_struct *last_task_used_math;
82extern struct task_struct *last_task_used_altivec; 79extern struct task_struct *last_task_used_altivec;
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index ead5016b02d0..6eb330a87c36 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -435,6 +435,17 @@ 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
438/* Traced system call support */ 449/* Traced system call support */
439syscall_dotrace: 450syscall_dotrace:
440 SAVE_NVGPRS(r1) 451 SAVE_NVGPRS(r1)
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index b40e0b4815b3..d7f4fafc7515 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -370,6 +370,16 @@ _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
373 .section ".toc","aw" 383 .section ".toc","aw"
374DSCR_DEFAULT: 384DSCR_DEFAULT:
375 .tc dscr_default[TC],dscr_default 385 .tc dscr_default[TC],dscr_default
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 1a1f2ddfb581..3b06898fa175 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -734,30 +734,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
734extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ 734extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
735 735
736int copy_thread(unsigned long clone_flags, unsigned long usp, 736int copy_thread(unsigned long clone_flags, unsigned long usp,
737 unsigned long unused, struct task_struct *p, 737 unsigned long arg, struct task_struct *p,
738 struct pt_regs *regs) 738 struct pt_regs *regs)
739{ 739{
740 struct pt_regs *childregs, *kregs; 740 struct pt_regs *childregs, *kregs;
741 extern void ret_from_fork(void); 741 extern void ret_from_fork(void);
742 extern void ret_from_kernel_thread(void);
743 void (*f)(void);
742 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 744 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
743 745
744 CHECK_FULL_REGS(regs);
745 /* Copy registers */ 746 /* Copy registers */
746 sp -= sizeof(struct pt_regs); 747 sp -= sizeof(struct pt_regs);
747 childregs = (struct pt_regs *) sp; 748 childregs = (struct pt_regs *) sp;
748 *childregs = *regs; 749 if (!regs) {
749 if ((childregs->msr & MSR_PR) == 0) {
750 /* for kernel thread, set `current' and stackptr in new task */ 750 /* for kernel thread, set `current' and stackptr in new task */
751 memset(childregs, 0, sizeof(struct pt_regs));
751 childregs->gpr[1] = sp + sizeof(struct pt_regs); 752 childregs->gpr[1] = sp + sizeof(struct pt_regs);
752#ifdef CONFIG_PPC32 753#ifdef CONFIG_PPC64
753 childregs->gpr[2] = (unsigned long) p; 754 childregs->gpr[14] = *(unsigned long *)usp;
754#else 755 childregs->gpr[2] = ((unsigned long *)usp)[1],
755 clear_tsk_thread_flag(p, TIF_32BIT); 756 clear_tsk_thread_flag(p, TIF_32BIT);
757#else
758 childregs->gpr[14] = usp; /* function */
759 childregs->gpr[2] = (unsigned long) p;
756#endif 760#endif
761 childregs->gpr[15] = arg;
757 p->thread.regs = NULL; /* no user register state */ 762 p->thread.regs = NULL; /* no user register state */
763 f = ret_from_kernel_thread;
758 } else { 764 } else {
765 CHECK_FULL_REGS(regs);
766 *childregs = *regs;
759 childregs->gpr[1] = usp; 767 childregs->gpr[1] = usp;
760 p->thread.regs = childregs; 768 p->thread.regs = childregs;
769 childregs->gpr[3] = 0; /* Result from fork() */
761 if (clone_flags & CLONE_SETTLS) { 770 if (clone_flags & CLONE_SETTLS) {
762#ifdef CONFIG_PPC64 771#ifdef CONFIG_PPC64
763 if (!is_32bit_task()) 772 if (!is_32bit_task())
@@ -766,8 +775,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
766#endif 775#endif
767 childregs->gpr[2] = childregs->gpr[6]; 776 childregs->gpr[2] = childregs->gpr[6];
768 } 777 }
778
779 f = ret_from_fork;
769 } 780 }
770 childregs->gpr[3] = 0; /* Result from fork() */
771 sp -= STACK_FRAME_OVERHEAD; 781 sp -= STACK_FRAME_OVERHEAD;
772 782
773 /* 783 /*
@@ -806,19 +816,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
806 p->thread.dscr = current->thread.dscr; 816 p->thread.dscr = current->thread.dscr;
807 } 817 }
808#endif 818#endif
809
810 /* 819 /*
811 * The PPC64 ABI makes use of a TOC to contain function 820 * The PPC64 ABI makes use of a TOC to contain function
812 * pointers. The function (ret_from_except) is actually a pointer 821 * pointers. The function (ret_from_except) is actually a pointer
813 * to the TOC entry. The first entry is a pointer to the actual 822 * to the TOC entry. The first entry is a pointer to the actual
814 * function. 823 * function.
815 */ 824 */
816#ifdef CONFIG_PPC64 825#ifdef CONFIG_PPC64
817 kregs->nip = *((unsigned long *)ret_from_fork); 826 kregs->nip = *((unsigned long *)f);
818#else 827#else
819 kregs->nip = (unsigned long)ret_from_fork; 828 kregs->nip = (unsigned long)f;
820#endif 829#endif
821
822 return 0; 830 return 0;
823} 831}
824 832