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

unicore32: switch to generic kernel_thread()/kernel_execve()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-and-Tested-by: Guan Xuetao <gxt@mprc.pku.edu.cn>

authored by

Al Viro and committed by
Guan Xuetao
38e99353 ddd2d384

+23 -99
+2
arch/unicore32/Kconfig
··· 16 16 select ARCH_WANT_FRAME_POINTERS 17 17 select GENERIC_IOMAP 18 18 select MODULES_USE_ELF_REL 19 + select GENERIC_KERNEL_THREAD 20 + select GENERIC_KERNEL_EXECVE 19 21 help 20 22 UniCore-32 is 32-bit Instruction Set Architecture, 21 23 including a series of low-power-consumption RISC chip
-5
arch/unicore32/include/asm/processor.h
··· 72 72 73 73 #define cpu_relax() barrier() 74 74 75 - /* 76 - * Create a new kernel thread 77 - */ 78 - extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 79 - 80 75 #define task_pt_regs(p) \ 81 76 ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) 82 77
+7 -8
arch/unicore32/kernel/entry.S
··· 573 573 */ 574 574 ENTRY(ret_from_fork) 575 575 b.l schedule_tail 576 - get_thread_info tsk 577 - ldw r1, [tsk+], #TI_FLAGS @ check for syscall tracing 578 - mov why, #1 579 - cand.a r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls? 580 - beq ret_slow_syscall 581 - mov r1, sp 582 - mov r0, #1 @ trace exit [IP = 1] 583 - b.l syscall_trace 584 576 b ret_slow_syscall 585 577 ENDPROC(ret_from_fork) 578 + 579 + ENTRY(ret_from_kernel_thread) 580 + b.l schedule_tail 581 + mov r0, r5 582 + adr lr, ret_slow_syscall 583 + mov pc, r4 584 + ENDPROC(ret_from_kernel_thread) 586 585 587 586 /*============================================================================= 588 587 * SWI handler
+14 -44
arch/unicore32/kernel/process.c
··· 258 258 } 259 259 260 260 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 261 + asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); 261 262 262 263 int 263 264 copy_thread(unsigned long clone_flags, unsigned long stack_start, ··· 267 266 struct thread_info *thread = task_thread_info(p); 268 267 struct pt_regs *childregs = task_pt_regs(p); 269 268 270 - *childregs = *regs; 271 - childregs->UCreg_00 = 0; 272 - childregs->UCreg_sp = stack_start; 273 - 274 269 memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); 275 270 thread->cpu_context.sp = (unsigned long)childregs; 276 - thread->cpu_context.pc = (unsigned long)ret_from_fork; 271 + if (unlikely(!regs)) { 272 + thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; 273 + thread->cpu_context.r4 = stack_start; 274 + thread->cpu_context.r5 = stk_sz; 275 + memset(childregs, 0, sizeof(struct pt_regs)); 276 + } else { 277 + thread->cpu_context.pc = (unsigned long)ret_from_fork; 278 + *childregs = *regs; 279 + childregs->UCreg_00 = 0; 280 + childregs->UCreg_sp = stack_start; 277 281 278 - if (clone_flags & CLONE_SETTLS) 279 - childregs->UCreg_16 = regs->UCreg_03; 280 - 282 + if (clone_flags & CLONE_SETTLS) 283 + childregs->UCreg_16 = regs->UCreg_03; 284 + } 281 285 return 0; 282 286 } 283 287 ··· 310 304 return used_math != 0; 311 305 } 312 306 EXPORT_SYMBOL(dump_fpu); 313 - 314 - /* 315 - * Shuffle the argument into the correct register before calling the 316 - * thread function. r1 is the thread argument, r2 is the pointer to 317 - * the thread function, and r3 points to the exit function. 318 - */ 319 - asm(".pushsection .text\n" 320 - " .align\n" 321 - " .type kernel_thread_helper, #function\n" 322 - "kernel_thread_helper:\n" 323 - " mov.a asr, r7\n" 324 - " mov r0, r4\n" 325 - " mov lr, r6\n" 326 - " mov pc, r5\n" 327 - " .size kernel_thread_helper, . - kernel_thread_helper\n" 328 - " .popsection"); 329 - 330 - /* 331 - * Create a kernel thread. 332 - */ 333 - pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 334 - { 335 - struct pt_regs regs; 336 - 337 - memset(&regs, 0, sizeof(regs)); 338 - 339 - regs.UCreg_04 = (unsigned long)arg; 340 - regs.UCreg_05 = (unsigned long)fn; 341 - regs.UCreg_06 = (unsigned long)do_exit; 342 - regs.UCreg_07 = PRIV_MODE; 343 - regs.UCreg_pc = (unsigned long)kernel_thread_helper; 344 - regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT; 345 - 346 - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 347 - } 348 - EXPORT_SYMBOL(kernel_thread); 349 307 350 308 unsigned long get_wchan(struct task_struct *p) 351 309 {
-42
arch/unicore32/kernel/sys.c
··· 63 63 return error; 64 64 } 65 65 66 - int kernel_execve(const char *filename, 67 - const char *const argv[], 68 - const char *const envp[]) 69 - { 70 - struct pt_regs regs; 71 - int ret; 72 - 73 - memset(&regs, 0, sizeof(struct pt_regs)); 74 - ret = do_execve(filename, 75 - (const char __user *const __user *)argv, 76 - (const char __user *const __user *)envp, &regs); 77 - if (ret < 0) 78 - goto out; 79 - 80 - /* 81 - * Save argc to the register structure for userspace. 82 - */ 83 - regs.UCreg_00 = ret; 84 - 85 - /* 86 - * We were successful. We won't be returning to our caller, but 87 - * instead to user space by manipulating the kernel stack. 88 - */ 89 - asm("add r0, %0, %1\n\t" 90 - "mov r1, %2\n\t" 91 - "mov r2, %3\n\t" 92 - "mov r22, #0\n\t" /* not a syscall */ 93 - "mov r23, %0\n\t" /* thread structure */ 94 - "b.l memmove\n\t" /* copy regs to top of stack */ 95 - "mov sp, r0\n\t" /* reposition stack pointer */ 96 - "b ret_to_user" 97 - : 98 - : "r" (current_thread_info()), 99 - "Ir" (THREAD_START_SP - sizeof(regs)), 100 - "r" (&regs), 101 - "Ir" (sizeof(regs)) 102 - : "r0", "r1", "r2", "r3", "ip", "lr", "memory"); 103 - 104 - out: 105 - return ret; 106 - } 107 - 108 66 /* Note: used by the compat code even in 64-bit Linux. */ 109 67 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, 110 68 unsigned long, prot, unsigned long, flags,