Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Al Viro 58254e10 f322220d

+43 -84
+1
arch/powerpc/Kconfig
··· 139 139 select GENERIC_CLOCKEVENTS 140 140 select GENERIC_STRNCPY_FROM_USER 141 141 select GENERIC_STRNLEN_USER 142 + select GENERIC_KERNEL_THREAD 142 143 143 144 config EARLY_PRINTK 144 145 bool
-3
arch/powerpc/include/asm/processor.h
··· 74 74 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); 75 75 void release_thread(struct task_struct *); 76 76 77 - /* Create a new kernel thread. */ 78 - extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 79 - 80 77 /* Lazy FPU handling on uni-processor */ 81 78 extern struct task_struct *last_task_used_math; 82 79 extern struct task_struct *last_task_used_altivec;
+11
arch/powerpc/kernel/entry_32.S
··· 435 435 li r3,0 436 436 b ret_from_syscall 437 437 438 + .globl ret_from_kernel_thread 439 + ret_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 449 /* Traced system call support */ 439 450 syscall_dotrace: 440 451 SAVE_NVGPRS(r1)
+10
arch/powerpc/kernel/entry_64.S
··· 370 370 li r3,0 371 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 383 .section ".toc","aw" 374 384 DSCR_DEFAULT: 375 385 .tc dscr_default[TC],dscr_default
-33
arch/powerpc/kernel/misc_32.S
··· 663 663 sub r3,r3,r4 664 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 */ 683 - 1: 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 694 - 2: lwz r30,8(r1) 695 - lwz r31,12(r1) 696 - addi r1,r1,16 697 - blr 698 - 699 666 #ifdef CONFIG_SMP 700 667 _GLOBAL(start_secondary_resume) 701 668 /* Reset stack */
-34
arch/powerpc/kernel/misc_64.S
··· 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 */ 426 - 1: 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 438 - 2: addi r1,r1,STACK_FRAME_OVERHEAD 439 - ld r29,-24(r1) 440 - ld r30,-16(r1) 441 - blr 442 - 443 - /* 444 410 * disable_kernel_fp() 445 411 * Disable the FPU. 446 412 */
-1
arch/powerpc/kernel/ppc_ksyms.c
··· 94 94 #endif /* CONFIG_PCI */ 95 95 96 96 EXPORT_SYMBOL(start_thread); 97 - EXPORT_SYMBOL(kernel_thread); 98 97 99 98 EXPORT_SYMBOL(giveup_fpu); 100 99 #ifdef CONFIG_ALTIVEC
+21 -13
arch/powerpc/kernel/process.c
··· 734 734 extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ 735 735 736 736 int 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 738 struct pt_regs *regs) 739 739 { 740 740 struct pt_regs *childregs, *kregs; 741 741 extern void ret_from_fork(void); 742 + extern void ret_from_kernel_thread(void); 743 + void (*f)(void); 742 744 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 743 745 744 - CHECK_FULL_REGS(regs); 745 746 /* Copy registers */ 746 747 sp -= sizeof(struct pt_regs); 747 748 childregs = (struct pt_regs *) sp; 748 - *childregs = *regs; 749 - if ((childregs->msr & MSR_PR) == 0) { 749 + if (!regs) { 750 750 /* for kernel thread, set `current' and stackptr in new task */ 751 + memset(childregs, 0, sizeof(struct pt_regs)); 751 752 childregs->gpr[1] = sp + sizeof(struct pt_regs); 752 - #ifdef CONFIG_PPC32 753 - childregs->gpr[2] = (unsigned long) p; 754 - #else 753 + #ifdef CONFIG_PPC64 754 + childregs->gpr[14] = *(unsigned long *)usp; 755 + childregs->gpr[2] = ((unsigned long *)usp)[1], 755 756 clear_tsk_thread_flag(p, TIF_32BIT); 757 + #else 758 + childregs->gpr[14] = usp; /* function */ 759 + childregs->gpr[2] = (unsigned long) p; 756 760 #endif 761 + childregs->gpr[15] = arg; 757 762 p->thread.regs = NULL; /* no user register state */ 763 + f = ret_from_kernel_thread; 758 764 } else { 765 + CHECK_FULL_REGS(regs); 766 + *childregs = *regs; 759 767 childregs->gpr[1] = usp; 760 768 p->thread.regs = childregs; 769 + childregs->gpr[3] = 0; /* Result from fork() */ 761 770 if (clone_flags & CLONE_SETTLS) { 762 771 #ifdef CONFIG_PPC64 763 772 if (!is_32bit_task()) ··· 775 766 #endif 776 767 childregs->gpr[2] = childregs->gpr[6]; 777 768 } 769 + 770 + f = ret_from_fork; 778 771 } 779 - childregs->gpr[3] = 0; /* Result from fork() */ 780 772 sp -= STACK_FRAME_OVERHEAD; 781 773 782 774 /* ··· 816 806 p->thread.dscr = current->thread.dscr; 817 807 } 818 808 #endif 819 - 820 809 /* 821 810 * The PPC64 ABI makes use of a TOC to contain function 822 811 * pointers. The function (ret_from_except) is actually a pointer 823 812 * to the TOC entry. The first entry is a pointer to the actual 824 813 * function. 825 - */ 814 + */ 826 815 #ifdef CONFIG_PPC64 827 - kregs->nip = *((unsigned long *)ret_from_fork); 816 + kregs->nip = *((unsigned long *)f); 828 817 #else 829 - kregs->nip = (unsigned long)ret_from_fork; 818 + kregs->nip = (unsigned long)f; 830 819 #endif 831 - 832 820 return 0; 833 821 } 834 822