Commit 58254e10 authored by Al Viro's avatar Al Viro

powerpc: split ret_from_fork

... and get rid of in-kernel syscalls in kernel_thread()
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent f322220d
...@@ -139,6 +139,7 @@ config PPC ...@@ -139,6 +139,7 @@ config PPC
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER select GENERIC_STRNLEN_USER
select GENERIC_KERNEL_THREAD
config EARLY_PRINTK config EARLY_PRINTK
bool bool
......
...@@ -74,9 +74,6 @@ struct task_struct; ...@@ -74,9 +74,6 @@ struct task_struct;
void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
void release_thread(struct task_struct *); void release_thread(struct task_struct *);
/* Create a new kernel thread. */
extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
/* Lazy FPU handling on uni-processor */ /* Lazy FPU handling on uni-processor */
extern struct task_struct *last_task_used_math; extern struct task_struct *last_task_used_math;
extern struct task_struct *last_task_used_altivec; extern struct task_struct *last_task_used_altivec;
......
...@@ -435,6 +435,17 @@ ret_from_fork: ...@@ -435,6 +435,17 @@ ret_from_fork:
li r3,0 li r3,0
b ret_from_syscall b ret_from_syscall
.globl ret_from_kernel_thread
ret_from_kernel_thread:
REST_NVGPRS(r1)
bl schedule_tail
mtlr r14
mr r3,r15
PPC440EP_ERR42
blrl
li r3,0
b do_exit # no return
/* Traced system call support */ /* Traced system call support */
syscall_dotrace: syscall_dotrace:
SAVE_NVGPRS(r1) SAVE_NVGPRS(r1)
......
...@@ -370,6 +370,16 @@ _GLOBAL(ret_from_fork) ...@@ -370,6 +370,16 @@ _GLOBAL(ret_from_fork)
li r3,0 li r3,0
b syscall_exit b syscall_exit
_GLOBAL(ret_from_kernel_thread)
bl .schedule_tail
REST_NVGPRS(r1)
REST_GPR(2,r1)
mtlr r14
mr r3,r15
blrl
li r3,0
b .do_exit # no return
.section ".toc","aw" .section ".toc","aw"
DSCR_DEFAULT: DSCR_DEFAULT:
.tc dscr_default[TC],dscr_default .tc dscr_default[TC],dscr_default
......
...@@ -663,39 +663,6 @@ _GLOBAL(abs) ...@@ -663,39 +663,6 @@ _GLOBAL(abs)
sub r3,r3,r4 sub r3,r3,r4
blr blr
/*
* Create a kernel thread
* kernel_thread(fn, arg, flags)
*/
_GLOBAL(kernel_thread)
stwu r1,-16(r1)
stw r30,8(r1)
stw r31,12(r1)
mr r30,r3 /* function */
mr r31,r4 /* argument */
ori r3,r5,CLONE_VM /* flags */
oris r3,r3,CLONE_UNTRACED>>16
li r4,0 /* new sp (unused) */
li r0,__NR_clone
sc
bns+ 1f /* did system call indicate error? */
neg r3,r3 /* if so, make return code negative */
1: cmpwi 0,r3,0 /* parent or child? */
bne 2f /* return if parent */
li r0,0 /* make top-level stack frame */
stwu r0,-16(r1)
mtlr r30 /* fn addr in lr */
mr r3,r31 /* load arg and call fn */
PPC440EP_ERR42
blrl
li r0,__NR_exit /* exit if function returns */
li r3,0
sc
2: lwz r30,8(r1)
lwz r31,12(r1)
addi r1,r1,16
blr
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
_GLOBAL(start_secondary_resume) _GLOBAL(start_secondary_resume)
/* Reset stack */ /* Reset stack */
......
...@@ -406,40 +406,6 @@ _GLOBAL(scom970_write) ...@@ -406,40 +406,6 @@ _GLOBAL(scom970_write)
#endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */ #endif /* CONFIG_CPU_FREQ_PMAC64 || CONFIG_CPU_FREQ_MAPLE */
/*
* Create a kernel thread
* kernel_thread(fn, arg, flags)
*/
_GLOBAL(kernel_thread)
std r29,-24(r1)
std r30,-16(r1)
stdu r1,-STACK_FRAME_OVERHEAD(r1)
mr r29,r3
mr r30,r4
ori r3,r5,CLONE_VM /* flags */
oris r3,r3,(CLONE_UNTRACED>>16)
li r4,0 /* new sp (unused) */
li r0,__NR_clone
sc
bns+ 1f /* did system call indicate error? */
neg r3,r3 /* if so, make return code negative */
1: cmpdi 0,r3,0 /* parent or child? */
bne 2f /* return if parent */
li r0,0
stdu r0,-STACK_FRAME_OVERHEAD(r1)
ld r2,8(r29)
ld r29,0(r29)
mtlr r29 /* fn addr in lr */
mr r3,r30 /* load arg and call fn */
blrl
li r0,__NR_exit /* exit after child exits */
li r3,0
sc
2: addi r1,r1,STACK_FRAME_OVERHEAD
ld r29,-24(r1)
ld r30,-16(r1)
blr
/* /*
* disable_kernel_fp() * disable_kernel_fp()
* Disable the FPU. * Disable the FPU.
......
...@@ -94,7 +94,6 @@ EXPORT_SYMBOL(pci_dram_offset); ...@@ -94,7 +94,6 @@ EXPORT_SYMBOL(pci_dram_offset);
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(giveup_fpu); EXPORT_SYMBOL(giveup_fpu);
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
......
...@@ -734,30 +734,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) ...@@ -734,30 +734,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
int copy_thread(unsigned long clone_flags, unsigned long usp, int copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long unused, struct task_struct *p, unsigned long arg, struct task_struct *p,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct pt_regs *childregs, *kregs; struct pt_regs *childregs, *kregs;
extern void ret_from_fork(void); extern void ret_from_fork(void);
extern void ret_from_kernel_thread(void);
void (*f)(void);
unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
CHECK_FULL_REGS(regs);
/* Copy registers */ /* Copy registers */
sp -= sizeof(struct pt_regs); sp -= sizeof(struct pt_regs);
childregs = (struct pt_regs *) sp; childregs = (struct pt_regs *) sp;
*childregs = *regs; if (!regs) {
if ((childregs->msr & MSR_PR) == 0) {
/* for kernel thread, set `current' and stackptr in new task */ /* for kernel thread, set `current' and stackptr in new task */
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gpr[1] = sp + sizeof(struct pt_regs); childregs->gpr[1] = sp + sizeof(struct pt_regs);
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC64
childregs->gpr[2] = (unsigned long) p; childregs->gpr[14] = *(unsigned long *)usp;
#else childregs->gpr[2] = ((unsigned long *)usp)[1],
clear_tsk_thread_flag(p, TIF_32BIT); clear_tsk_thread_flag(p, TIF_32BIT);
#else
childregs->gpr[14] = usp; /* function */
childregs->gpr[2] = (unsigned long) p;
#endif #endif
childregs->gpr[15] = arg;
p->thread.regs = NULL; /* no user register state */ p->thread.regs = NULL; /* no user register state */
f = ret_from_kernel_thread;
} else { } else {
CHECK_FULL_REGS(regs);
*childregs = *regs;
childregs->gpr[1] = usp; childregs->gpr[1] = usp;
p->thread.regs = childregs; p->thread.regs = childregs;
childregs->gpr[3] = 0; /* Result from fork() */
if (clone_flags & CLONE_SETTLS) { if (clone_flags & CLONE_SETTLS) {
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
if (!is_32bit_task()) if (!is_32bit_task())
...@@ -766,8 +775,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -766,8 +775,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
#endif #endif
childregs->gpr[2] = childregs->gpr[6]; childregs->gpr[2] = childregs->gpr[6];
} }
f = ret_from_fork;
} }
childregs->gpr[3] = 0; /* Result from fork() */
sp -= STACK_FRAME_OVERHEAD; sp -= STACK_FRAME_OVERHEAD;
/* /*
...@@ -806,19 +816,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ...@@ -806,19 +816,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
p->thread.dscr = current->thread.dscr; p->thread.dscr = current->thread.dscr;
} }
#endif #endif
/* /*
* The PPC64 ABI makes use of a TOC to contain function * The PPC64 ABI makes use of a TOC to contain function
* pointers. The function (ret_from_except) is actually a pointer * pointers. The function (ret_from_except) is actually a pointer
* to the TOC entry. The first entry is a pointer to the actual * to the TOC entry. The first entry is a pointer to the actual
* function. * function.
*/ */
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
kregs->nip = *((unsigned long *)ret_from_fork); kregs->nip = *((unsigned long *)f);
#else #else
kregs->nip = (unsigned long)ret_from_fork; kregs->nip = (unsigned long)f;
#endif #endif
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment