diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-15 11:34:45 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-15 11:34:45 -0800 |
commit | c5e35d6c512c43105883043dd62cf7257ec3f9f0 (patch) | |
tree | 09905577d6de0d61e751c42774d5f7f2d1257015 /arch/unicore32/kernel/process.c | |
parent | ce95a36bb9dd8bb5de49e69b27238da2f415f230 (diff) | |
parent | c284464658acab50c67ff65ff3dc9215a0231ad2 (diff) |
Merge tag 'for-linus' of git://github.com/gxt/linux
Pull unicore32 update from Guan Xuetao.
* tag 'for-linus' of git://github.com/gxt/linux:
arch/unicore32: remove CONFIG_EXPERIMENTAL
unicore32: switch to generic sys_execve()
unicore32: switch to generic kernel_thread()/kernel_execve()
unicore32: Use Kbuild infrastructure for kvm_para.h
UAPI: (Scripted) Disintegrate arch/unicore32/include/asm
UniCore32-bugfix: Remove definitions in asm/bug.h to solve difference between native and cross compiler
UniCore32-bugfix: fix mismatch return value of __xchg_bad_pointer
UniCore32 bugfix: add missed CONFIG_ZONE_DMA
unicore32/mm/fault.c: Port OOM changes to do_pf
Diffstat (limited to 'arch/unicore32/kernel/process.c')
-rw-r--r-- | arch/unicore32/kernel/process.c | 58 |
1 files changed, 14 insertions, 44 deletions
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index b008586dad75..a8fe265ce2c0 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task) } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); +asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); int copy_thread(unsigned long clone_flags, unsigned long stack_start, @@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, struct thread_info *thread = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); - *childregs = *regs; - childregs->UCreg_00 = 0; - childregs->UCreg_sp = stack_start; - memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); thread->cpu_context.sp = (unsigned long)childregs; - thread->cpu_context.pc = (unsigned long)ret_from_fork; - - if (clone_flags & CLONE_SETTLS) - childregs->UCreg_16 = regs->UCreg_03; + if (unlikely(!regs)) { + thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; + thread->cpu_context.r4 = stack_start; + thread->cpu_context.r5 = stk_sz; + memset(childregs, 0, sizeof(struct pt_regs)); + } else { + thread->cpu_context.pc = (unsigned long)ret_from_fork; + *childregs = *regs; + childregs->UCreg_00 = 0; + childregs->UCreg_sp = stack_start; + if (clone_flags & CLONE_SETTLS) + childregs->UCreg_16 = regs->UCreg_03; + } return 0; } @@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp) } EXPORT_SYMBOL(dump_fpu); -/* - * Shuffle the argument into the correct register before calling the - * thread function. r1 is the thread argument, r2 is the pointer to - * the thread function, and r3 points to the exit function. - */ -asm(".pushsection .text\n" -" .align\n" -" .type kernel_thread_helper, #function\n" -"kernel_thread_helper:\n" -" mov.a asr, r7\n" -" mov r0, r4\n" -" mov lr, r6\n" -" mov pc, r5\n" -" .size kernel_thread_helper, . - kernel_thread_helper\n" -" .popsection"); - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.UCreg_04 = (unsigned long)arg; - regs.UCreg_05 = (unsigned long)fn; - regs.UCreg_06 = (unsigned long)do_exit; - regs.UCreg_07 = PRIV_MODE; - regs.UCreg_pc = (unsigned long)kernel_thread_helper; - regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT; - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; |