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

Merge branches 'no-rebases', 'arch-avr32', 'arch-blackfin', 'arch-cris', 'arch-h8300', 'arch-m32r', 'arch-mn10300', 'arch-score', 'arch-sh' and 'arch-powerpc' into for-next

Al Viro f4091322 d2125043

+993 -2792
+2
arch/arm64/Kconfig
··· 7 7 select GENERIC_IOMAP 8 8 select GENERIC_IRQ_PROBE 9 9 select GENERIC_IRQ_SHOW 10 + select GENERIC_KERNEL_EXECVE 11 + select GENERIC_KERNEL_THREAD 10 12 select GENERIC_SMP_IDLE_THREAD 11 13 select GENERIC_TIME_VSYSCALL 12 14 select HARDIRQS_SW_RESEND
-5
arch/arm64/include/asm/processor.h
··· 128 128 extern struct task_struct *cpu_switch_to(struct task_struct *prev, 129 129 struct task_struct *next); 130 130 131 - /* 132 - * Create a new kernel thread 133 - */ 134 - extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 135 - 136 131 #define task_pt_regs(p) \ 137 132 ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) 138 133
+6 -8
arch/arm64/include/asm/syscalls.h
··· 23 23 /* 24 24 * System call wrappers implemented in kernel/entry.S. 25 25 */ 26 - asmlinkage long sys_execve_wrapper(const char __user *filename, 27 - const char __user *const __user *argv, 28 - const char __user *const __user *envp); 29 - asmlinkage long sys_clone_wrapper(unsigned long clone_flags, 30 - unsigned long newsp, 31 - void __user *parent_tid, 32 - unsigned long tls_val, 33 - void __user *child_tid); 34 26 asmlinkage long sys_rt_sigreturn_wrapper(void); 35 27 asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss, 36 28 stack_t __user *uoss); 29 + 30 + /* 31 + * AArch64 sys_clone implementation has a different prototype than the generic 32 + * one (additional TLS value argument). 33 + */ 34 + #define sys_clone sys_clone 37 35 38 36 #include <asm-generic/syscalls.h> 39 37
+1
arch/arm64/include/asm/unistd.h
··· 25 25 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 26 26 #define __ARCH_WANT_COMPAT_SYS_SENDFILE 27 27 #endif 28 + #define __ARCH_WANT_SYS_EXECVE 28 29 #include <uapi/asm/unistd.h>
+4 -4
arch/arm64/include/asm/unistd32.h
··· 23 23 24 24 __SYSCALL(0, sys_restart_syscall) 25 25 __SYSCALL(1, sys_exit) 26 - __SYSCALL(2, compat_sys_fork_wrapper) 26 + __SYSCALL(2, compat_sys_fork) 27 27 __SYSCALL(3, sys_read) 28 28 __SYSCALL(4, sys_write) 29 29 __SYSCALL(5, compat_sys_open) ··· 32 32 __SYSCALL(8, sys_creat) 33 33 __SYSCALL(9, sys_link) 34 34 __SYSCALL(10, sys_unlink) 35 - __SYSCALL(11, compat_sys_execve_wrapper) 35 + __SYSCALL(11, compat_sys_execve) 36 36 __SYSCALL(12, sys_chdir) 37 37 __SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */ 38 38 __SYSCALL(14, sys_mknod) ··· 141 141 __SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */ 142 142 __SYSCALL(118, sys_fsync) 143 143 __SYSCALL(119, compat_sys_sigreturn_wrapper) 144 - __SYSCALL(120, compat_sys_clone_wrapper) 144 + __SYSCALL(120, sys_clone) 145 145 __SYSCALL(121, sys_setdomainname) 146 146 __SYSCALL(122, sys_newuname) 147 147 __SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */ ··· 211 211 __SYSCALL(187, compat_sys_sendfile) 212 212 __SYSCALL(188, sys_ni_syscall) /* 188 reserved */ 213 213 __SYSCALL(189, sys_ni_syscall) /* 189 reserved */ 214 - __SYSCALL(190, compat_sys_vfork_wrapper) 214 + __SYSCALL(190, compat_sys_vfork) 215 215 __SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */ 216 216 __SYSCALL(192, sys_mmap_pgoff) 217 217 __SYSCALL(193, compat_sys_truncate64_wrapper)
+5 -12
arch/arm64/kernel/entry.S
··· 594 594 /* 595 595 * "slow" syscall return path. 596 596 */ 597 - ENTRY(ret_to_user) 597 + ret_to_user: 598 598 disable_irq // disable interrupts 599 599 ldr x1, [tsk, #TI_FLAGS] 600 600 and x2, x1, #_TIF_WORK_MASK ··· 611 611 */ 612 612 ENTRY(ret_from_fork) 613 613 bl schedule_tail 614 - get_thread_info tsk 614 + cbz x19, 1f // not a kernel thread 615 + mov x0, x20 616 + blr x19 617 + 1: get_thread_info tsk 615 618 b ret_to_user 616 619 ENDPROC(ret_from_fork) 617 620 ··· 676 673 /* 677 674 * Special system call wrappers. 678 675 */ 679 - ENTRY(sys_execve_wrapper) 680 - mov x3, sp 681 - b sys_execve 682 - ENDPROC(sys_execve_wrapper) 683 - 684 - ENTRY(sys_clone_wrapper) 685 - mov x5, sp 686 - b sys_clone 687 - ENDPROC(sys_clone_wrapper) 688 - 689 676 ENTRY(sys_rt_sigreturn_wrapper) 690 677 mov x0, sp 691 678 b sys_rt_sigreturn
+33 -56
arch/arm64/kernel/process.c
··· 240 240 struct pt_regs *childregs = task_pt_regs(p); 241 241 unsigned long tls = p->thread.tp_value; 242 242 243 - *childregs = *regs; 244 - childregs->regs[0] = 0; 245 - 246 - if (is_compat_thread(task_thread_info(p))) 247 - childregs->compat_sp = stack_start; 248 - else { 249 - /* 250 - * Read the current TLS pointer from tpidr_el0 as it may be 251 - * out-of-sync with the saved value. 252 - */ 253 - asm("mrs %0, tpidr_el0" : "=r" (tls)); 254 - childregs->sp = stack_start; 255 - } 256 - 257 243 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); 258 - p->thread.cpu_context.sp = (unsigned long)childregs; 259 - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 260 244 261 - /* If a TLS pointer was passed to clone, use that for the new thread. */ 262 - if (clone_flags & CLONE_SETTLS) 263 - tls = regs->regs[3]; 245 + if (likely(regs)) { 246 + *childregs = *regs; 247 + childregs->regs[0] = 0; 248 + if (is_compat_thread(task_thread_info(p))) { 249 + if (stack_start) 250 + childregs->compat_sp = stack_start; 251 + } else { 252 + /* 253 + * Read the current TLS pointer from tpidr_el0 as it may be 254 + * out-of-sync with the saved value. 255 + */ 256 + asm("mrs %0, tpidr_el0" : "=r" (tls)); 257 + if (stack_start) { 258 + /* 16-byte aligned stack mandatory on AArch64 */ 259 + if (stack_start & 15) 260 + return -EINVAL; 261 + childregs->sp = stack_start; 262 + } 263 + } 264 + /* 265 + * If a TLS pointer was passed to clone (4th argument), use it 266 + * for the new thread. 267 + */ 268 + if (clone_flags & CLONE_SETTLS) 269 + tls = regs->regs[3]; 270 + } else { 271 + memset(childregs, 0, sizeof(struct pt_regs)); 272 + childregs->pstate = PSR_MODE_EL1h; 273 + p->thread.cpu_context.x19 = stack_start; 274 + p->thread.cpu_context.x20 = stk_sz; 275 + } 276 + p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 277 + p->thread.cpu_context.sp = (unsigned long)childregs; 264 278 p->thread.tp_value = tls; 265 279 266 280 ptrace_hw_copy_thread(p); ··· 322 308 323 309 return last; 324 310 } 325 - 326 - /* 327 - * Shuffle the argument into the correct register before calling the 328 - * thread function. x1 is the thread argument, x2 is the pointer to 329 - * the thread function, and x3 points to the exit function. 330 - */ 331 - extern void kernel_thread_helper(void); 332 - asm( ".section .text\n" 333 - " .align\n" 334 - " .type kernel_thread_helper, #function\n" 335 - "kernel_thread_helper:\n" 336 - " mov x0, x1\n" 337 - " mov x30, x3\n" 338 - " br x2\n" 339 - " .size kernel_thread_helper, . - kernel_thread_helper\n" 340 - " .previous"); 341 - 342 - #define kernel_thread_exit do_exit 343 - 344 - /* 345 - * Create a kernel thread. 346 - */ 347 - pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 348 - { 349 - struct pt_regs regs; 350 - 351 - memset(&regs, 0, sizeof(regs)); 352 - 353 - regs.regs[1] = (unsigned long)arg; 354 - regs.regs[2] = (unsigned long)fn; 355 - regs.regs[3] = (unsigned long)kernel_thread_exit; 356 - regs.pc = (unsigned long)kernel_thread_helper; 357 - regs.pstate = PSR_MODE_EL1h; 358 - 359 - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 360 - } 361 - EXPORT_SYMBOL(kernel_thread); 362 311 363 312 unsigned long get_wchan(struct task_struct *p) 364 313 {
+3 -73
arch/arm64/kernel/sys.c
··· 31 31 */ 32 32 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, 33 33 int __user *parent_tidptr, unsigned long tls_val, 34 - int __user *child_tidptr, struct pt_regs *regs) 34 + int __user *child_tidptr) 35 35 { 36 - if (!newsp) 37 - newsp = regs->sp; 38 - /* 16-byte aligned stack mandatory on AArch64 */ 39 - if (newsp & 15) 40 - return -EINVAL; 41 - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 36 + return do_fork(clone_flags, newsp, current_pt_regs(), 0, 37 + parent_tidptr, child_tidptr); 42 38 } 43 - 44 - /* 45 - * sys_execve() executes a new program. 46 - */ 47 - asmlinkage long sys_execve(const char __user *filenamei, 48 - const char __user *const __user *argv, 49 - const char __user *const __user *envp, 50 - struct pt_regs *regs) 51 - { 52 - long error; 53 - struct filename *filename; 54 - 55 - filename = getname(filenamei); 56 - error = PTR_ERR(filename); 57 - if (IS_ERR(filename)) 58 - goto out; 59 - error = do_execve(filename->name, argv, envp, regs); 60 - putname(filename); 61 - out: 62 - return error; 63 - } 64 - 65 - int kernel_execve(const char *filename, 66 - const char *const argv[], 67 - const char *const envp[]) 68 - { 69 - struct pt_regs regs; 70 - int ret; 71 - 72 - memset(&regs, 0, sizeof(struct pt_regs)); 73 - ret = do_execve(filename, 74 - (const char __user *const __user *)argv, 75 - (const char __user *const __user *)envp, &regs); 76 - if (ret < 0) 77 - goto out; 78 - 79 - /* 80 - * Save argc to the register structure for userspace. 81 - */ 82 - regs.regs[0] = ret; 83 - 84 - /* 85 - * We were successful. We won't be returning to our caller, but 86 - * instead to user space by manipulating the kernel stack. 87 - */ 88 - asm( "add x0, %0, %1\n\t" 89 - "mov x1, %2\n\t" 90 - "mov x2, %3\n\t" 91 - "bl memmove\n\t" /* copy regs to top of stack */ 92 - "mov x27, #0\n\t" /* not a syscall */ 93 - "mov x28, %0\n\t" /* thread structure */ 94 - "mov sp, x0\n\t" /* reposition stack pointer */ 95 - "b ret_to_user" 96 - : 97 - : "r" (current_thread_info()), 98 - "Ir" (THREAD_START_SP - sizeof(regs)), 99 - "r" (&regs), 100 - "Ir" (sizeof(regs)) 101 - : "x0", "x1", "x2", "x27", "x28", "x30", "memory"); 102 - 103 - out: 104 - return ret; 105 - } 106 - EXPORT_SYMBOL(kernel_execve); 107 39 108 40 asmlinkage long sys_mmap(unsigned long addr, unsigned long len, 109 41 unsigned long prot, unsigned long flags, ··· 50 118 /* 51 119 * Wrappers to pass the pt_regs argument. 52 120 */ 53 - #define sys_execve sys_execve_wrapper 54 - #define sys_clone sys_clone_wrapper 55 121 #define sys_rt_sigreturn sys_rt_sigreturn_wrapper 56 122 #define sys_sigaltstack sys_sigaltstack_wrapper 57 123
-19
arch/arm64/kernel/sys32.S
··· 26 26 /* 27 27 * System call wrappers for the AArch32 compatibility layer. 28 28 */ 29 - compat_sys_fork_wrapper: 30 - mov x0, sp 31 - b compat_sys_fork 32 - ENDPROC(compat_sys_fork_wrapper) 33 - 34 - compat_sys_vfork_wrapper: 35 - mov x0, sp 36 - b compat_sys_vfork 37 - ENDPROC(compat_sys_vfork_wrapper) 38 - 39 - compat_sys_execve_wrapper: 40 - mov x3, sp 41 - b compat_sys_execve 42 - ENDPROC(compat_sys_execve_wrapper) 43 - 44 - compat_sys_clone_wrapper: 45 - mov x5, sp 46 - b compat_sys_clone 47 - ENDPROC(compat_sys_clone_wrapper) 48 29 49 30 compat_sys_sigreturn_wrapper: 50 31 mov x0, sp
+5 -33
arch/arm64/kernel/sys_compat.c
··· 28 28 #include <asm/cacheflush.h> 29 29 #include <asm/unistd32.h> 30 30 31 - asmlinkage int compat_sys_fork(struct pt_regs *regs) 31 + asmlinkage int compat_sys_fork(void) 32 32 { 33 - return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL); 33 + return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL); 34 34 } 35 35 36 - asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp, 37 - int __user *parent_tidptr, int tls_val, 38 - int __user *child_tidptr, struct pt_regs *regs) 36 + asmlinkage int compat_sys_vfork(void) 39 37 { 40 - if (!newsp) 41 - newsp = regs->compat_sp; 42 - 43 - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); 44 - } 45 - 46 - asmlinkage int compat_sys_vfork(struct pt_regs *regs) 47 - { 48 - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp, 49 - regs, 0, NULL, NULL); 50 - } 51 - 52 - asmlinkage int compat_sys_execve(const char __user *filenamei, 53 - compat_uptr_t argv, compat_uptr_t envp, 54 - struct pt_regs *regs) 55 - { 56 - int error; 57 - struct filename *filename; 58 - 59 - filename = getname(filenamei); 60 - error = PTR_ERR(filename); 61 - if (IS_ERR(filename)) 62 - goto out; 63 - error = compat_do_execve(filename->name, compat_ptr(argv), 64 - compat_ptr(envp), regs); 65 - putname(filename); 66 - out: 67 - return error; 38 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 39 + current_pt_regs(), 0, NULL, NULL); 68 40 } 69 41 70 42 asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
+2
arch/avr32/Kconfig
··· 17 17 select GENERIC_CLOCKEVENTS 18 18 select HAVE_MOD_ARCH_SPECIFIC 19 19 select MODULES_USE_ELF_RELA 20 + select GENERIC_KERNEL_THREAD 21 + select GENERIC_KERNEL_EXECVE 20 22 help 21 23 AVR32 is a high-performance 32-bit RISC microprocessor core, 22 24 designed for cost-sensitive embedded applications, with particular
-3
arch/avr32/include/asm/processor.h
··· 142 142 /* Free all resources held by a thread */ 143 143 extern void release_thread(struct task_struct *); 144 144 145 - /* Create a kernel thread without removing it from tasklists */ 146 - extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 147 - 148 145 /* Return saved PC of a blocked thread */ 149 146 #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) 150 147
+1
arch/avr32/include/asm/unistd.h
··· 39 39 #define __ARCH_WANT_SYS_GETPGRP 40 40 #define __ARCH_WANT_SYS_RT_SIGACTION 41 41 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 42 + #define __ARCH_WANT_SYS_EXECVE 42 43 43 44 /* 44 45 * "Conditional" syscalls
+1 -1
arch/avr32/kernel/Makefile
··· 7 7 obj-$(CONFIG_SUBARCH_AVR32B) += entry-avr32b.o 8 8 obj-y += syscall_table.o syscall-stubs.o irq.o 9 9 obj-y += setup.o traps.o ocd.o ptrace.o 10 - obj-y += signal.o sys_avr32.o process.o time.o 10 + obj-y += signal.o process.o time.o 11 11 obj-y += switch_to.o cpu.o 12 12 obj-$(CONFIG_MODULES) += module.o avr32_ksyms.o 13 13 obj-$(CONFIG_KPROBES) += kprobes.o
+8 -6
arch/avr32/kernel/entry-avr32b.S
··· 251 251 .global ret_from_fork 252 252 ret_from_fork: 253 253 call schedule_tail 254 + mov r12, 0 255 + rjmp syscall_return 254 256 255 - /* check for syscall tracing */ 256 - get_thread_info r0 257 - ld.w r1, r0[TI_flags] 258 - andl r1, _TIF_ALLWORK_MASK, COH 259 - brne syscall_exit_work 260 - rjmp syscall_exit_cont 257 + .global ret_from_kernel_thread 258 + ret_from_kernel_thread: 259 + call schedule_tail 260 + mov r12, r0 261 + mov lr, r2 /* syscall_return */ 262 + mov pc, r1 261 263 262 264 syscall_trace_enter: 263 265 pushm r8-r12
+16 -70
arch/avr32/kernel/process.c
··· 69 69 } 70 70 71 71 /* 72 - * PC is actually discarded when returning from a system call -- the 73 - * return address must be stored in LR. This function will make sure 74 - * LR points to do_exit before starting the thread. 75 - * 76 - * Also, when returning from fork(), r12 is 0, so we must copy the 77 - * argument as well. 78 - * 79 - * r0 : The argument to the main thread function 80 - * r1 : The address of do_exit 81 - * r2 : The address of the main thread function 82 - */ 83 - asmlinkage extern void kernel_thread_helper(void); 84 - __asm__(" .type kernel_thread_helper, @function\n" 85 - "kernel_thread_helper:\n" 86 - " mov r12, r0\n" 87 - " mov lr, r2\n" 88 - " mov pc, r1\n" 89 - " .size kernel_thread_helper, . - kernel_thread_helper"); 90 - 91 - int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 92 - { 93 - struct pt_regs regs; 94 - 95 - memset(&regs, 0, sizeof(regs)); 96 - 97 - regs.r0 = (unsigned long)arg; 98 - regs.r1 = (unsigned long)fn; 99 - regs.r2 = (unsigned long)do_exit; 100 - regs.lr = (unsigned long)kernel_thread_helper; 101 - regs.pc = (unsigned long)kernel_thread_helper; 102 - regs.sr = MODE_SUPERVISOR; 103 - 104 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 105 - 0, &regs, 0, NULL, NULL); 106 - } 107 - EXPORT_SYMBOL(kernel_thread); 108 - 109 - /* 110 72 * Free current thread data structures etc 111 73 */ 112 74 void exit_thread(void) ··· 294 332 } 295 333 296 334 asmlinkage void ret_from_fork(void); 335 + asmlinkage void ret_from_kernel_thread(void); 336 + asmlinkage void syscall_return(void); 297 337 298 338 int copy_thread(unsigned long clone_flags, unsigned long usp, 299 - unsigned long unused, 339 + unsigned long arg, 300 340 struct task_struct *p, struct pt_regs *regs) 301 341 { 302 - struct pt_regs *childregs; 342 + struct pt_regs *childregs = task_pt_regs(p); 303 343 304 - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1; 305 - *childregs = *regs; 306 - 307 - if (user_mode(regs)) 344 + if (unlikely(!regs)) { 345 + memset(childregs, 0, sizeof(struct pt_regs)); 346 + p->thread.cpu_context.r0 = arg; 347 + p->thread.cpu_context.r1 = usp; /* fn */ 348 + p->thread.cpu_context.r2 = syscall_return; 349 + p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread; 350 + childregs->sr = MODE_SUPERVISOR; 351 + } else { 352 + *childregs = *regs; 308 353 childregs->sp = usp; 309 - else 310 - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 311 - 312 - childregs->r12 = 0; /* Set return value for child */ 354 + childregs->r12 = 0; /* Set return value for child */ 355 + p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 356 + } 313 357 314 358 p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM; 315 359 p->thread.cpu_context.ksp = (unsigned long)childregs; 316 - p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 317 360 318 361 clear_tsk_thread_flag(p, TIF_DEBUG); 319 362 if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG)) ··· 348 381 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 349 382 0, NULL, NULL); 350 383 } 351 - 352 - asmlinkage int sys_execve(const char __user *ufilename, 353 - const char __user *const __user *uargv, 354 - const char __user *const __user *uenvp, 355 - struct pt_regs *regs) 356 - { 357 - int error; 358 - struct filename *filename; 359 - 360 - filename = getname(ufilename); 361 - error = PTR_ERR(filename); 362 - if (IS_ERR(filename)) 363 - goto out; 364 - 365 - error = do_execve(filename->name, uargv, uenvp, regs); 366 - putname(filename); 367 - 368 - out: 369 - return error; 370 - } 371 - 372 384 373 385 /* 374 386 * This function is supposed to answer the question "who called
-24
arch/avr32/kernel/sys_avr32.c
··· 1 - /* 2 - * Copyright (C) 2004-2006 Atmel Corporation 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - */ 8 - #include <linux/unistd.h> 9 - 10 - int kernel_execve(const char *file, 11 - const char *const *argv, 12 - const char *const *envp) 13 - { 14 - register long scno asm("r8") = __NR_execve; 15 - register long sc1 asm("r12") = (long)file; 16 - register long sc2 asm("r11") = (long)argv; 17 - register long sc3 asm("r10") = (long)envp; 18 - 19 - asm volatile("scall" 20 - : "=r"(sc1) 21 - : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3) 22 - : "cc", "memory"); 23 - return sc1; 24 - }
-6
arch/avr32/kernel/syscall-stubs.S
··· 50 50 mov r12, sp 51 51 rjmp sys_vfork 52 52 53 - .global __sys_execve 54 - .type __sys_execve,@function 55 - __sys_execve: 56 - mov r9, sp 57 - rjmp sys_execve 58 - 59 53 .global __sys_mmap2 60 54 .type __sys_mmap2,@function 61 55 __sys_mmap2:
+1 -1
arch/avr32/kernel/syscall_table.S
··· 24 24 .long sys_creat 25 25 .long sys_link 26 26 .long sys_unlink /* 10 */ 27 - .long __sys_execve 27 + .long sys_execve 28 28 .long sys_chdir 29 29 .long sys_time 30 30 .long sys_mknod
+2
arch/blackfin/Kconfig
··· 45 45 select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS 46 46 select HAVE_MOD_ARCH_SPECIFIC 47 47 select MODULES_USE_ELF_RELA 48 + select GENERIC_KERNEL_THREAD 49 + select GENERIC_KERNEL_EXECVE 48 50 49 51 config GENERIC_CSUM 50 52 def_bool y
-2
arch/blackfin/include/asm/processor.h
··· 75 75 { 76 76 } 77 77 78 - extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); 79 - 80 78 /* 81 79 * Free current thread data structures etc.. 82 80 */
+1
arch/blackfin/include/asm/unistd.h
··· 446 446 #define __ARCH_WANT_SYS_NICE 447 447 #define __ARCH_WANT_SYS_RT_SIGACTION 448 448 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 449 + #define __ARCH_WANT_SYS_EXECVE 449 450 450 451 /* 451 452 * "Conditional" syscalls
+8 -14
arch/blackfin/kernel/entry.S
··· 46 46 SP += -12; 47 47 pseudo_long_call _schedule_tail, p5; 48 48 SP += 12; 49 - r0 = [sp + PT_IPEND]; 50 - cc = bittst(r0,1); 51 - if cc jump .Lin_kernel; 49 + p1 = [sp++]; 50 + r0 = [sp++]; 51 + cc = p1 == 0; 52 + if cc jump .Lfork; 53 + sp += -12; 54 + call (p1); 55 + sp += 12; 56 + .Lfork: 52 57 RESTORE_CONTEXT 53 58 rti; 54 - .Lin_kernel: 55 - bitclr(r0,1); 56 - [sp + PT_IPEND] = r0; 57 - /* do a 'fake' RTI by jumping to [RETI] 58 - * to avoid clearing supervisor mode in child 59 - */ 60 - r0 = [sp + PT_PC]; 61 - [sp + PT_P0] = r0; 62 - 63 - RESTORE_ALL_SYS 64 - jump (p0); 65 59 ENDPROC(_ret_from_fork) 66 60 67 61 ENTRY(_sys_vfork)
+17 -58
arch/blackfin/kernel/process.c
··· 102 102 } 103 103 104 104 /* 105 - * This gets run with P1 containing the 106 - * function to call, and R1 containing 107 - * the "args". Note P0 is clobbered on the way here. 108 - */ 109 - void kernel_thread_helper(void); 110 - __asm__(".section .text\n" 111 - ".align 4\n" 112 - "_kernel_thread_helper:\n\t" 113 - "\tsp += -12;\n\t" 114 - "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous"); 115 - 116 - /* 117 - * Create a kernel thread. 118 - */ 119 - pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) 120 - { 121 - struct pt_regs regs; 122 - 123 - memset(&regs, 0, sizeof(regs)); 124 - 125 - regs.r1 = (unsigned long)arg; 126 - regs.p1 = (unsigned long)fn; 127 - regs.pc = (unsigned long)kernel_thread_helper; 128 - regs.orig_p0 = -1; 129 - /* Set bit 2 to tell ret_from_fork we should be returning to kernel 130 - mode. */ 131 - regs.ipend = 0x8002; 132 - __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):); 133 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, 134 - NULL); 135 - } 136 - EXPORT_SYMBOL(kernel_thread); 137 - 138 - /* 139 105 * Do necessary setup to start up a newly executed thread. 140 106 * 141 107 * pass the data segment into user programs if it exists, ··· 159 193 struct task_struct *p, struct pt_regs *regs) 160 194 { 161 195 struct pt_regs *childregs; 196 + unsigned long *v; 162 197 163 198 childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; 164 - *childregs = *regs; 165 - childregs->r0 = 0; 199 + v = ((unsigned long *)childregs) - 2; 200 + if (unlikely(!regs)) { 201 + memset(childregs, 0, sizeof(struct pt_regs)); 202 + v[0] = usp; 203 + v[1] = topstk; 204 + childregs->orig_p0 = -1; 205 + childregs->ipend = 0x8000; 206 + __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); 207 + p->thread.usp = 0; 208 + } else { 209 + *childregs = *regs; 210 + childregs->r0 = 0; 211 + p->thread.usp = usp; 212 + v[0] = v[1] = 0; 213 + } 166 214 167 - p->thread.usp = usp; 168 - p->thread.ksp = (unsigned long)childregs; 215 + p->thread.ksp = (unsigned long)v; 169 216 p->thread.pc = (unsigned long)ret_from_fork; 170 217 171 218 return 0; 172 - } 173 - 174 - /* 175 - * sys_execve() executes a new program. 176 - */ 177 - asmlinkage int sys_execve(const char __user *name, 178 - const char __user *const __user *argv, 179 - const char __user *const __user *envp) 180 - { 181 - int error; 182 - struct filename *filename; 183 - struct pt_regs *regs = (struct pt_regs *)((&name) + 6); 184 - 185 - filename = getname(name); 186 - error = PTR_ERR(filename); 187 - if (IS_ERR(filename)) 188 - return error; 189 - error = do_execve(filename->name, argv, envp, regs); 190 - putname(filename); 191 - return error; 192 219 } 193 220 194 221 unsigned long get_wchan(struct task_struct *p)
-55
arch/blackfin/mach-common/entry.S
··· 530 530 jump .Lsyscall_really_exit; 531 531 ENDPROC(_trap) 532 532 533 - ENTRY(_kernel_execve) 534 - link SIZEOF_PTREGS; 535 - p0 = sp; 536 - r3 = SIZEOF_PTREGS / 4; 537 - r4 = 0(x); 538 - .Lclear_regs: 539 - [p0++] = r4; 540 - r3 += -1; 541 - cc = r3 == 0; 542 - if !cc jump .Lclear_regs (bp); 543 - 544 - p0 = sp; 545 - sp += -16; 546 - [sp + 12] = p0; 547 - pseudo_long_call _do_execve, p5; 548 - SP += 16; 549 - cc = r0 == 0; 550 - if ! cc jump .Lexecve_failed; 551 - /* Success. Copy our temporary pt_regs to the top of the kernel 552 - * stack and do a normal exception return. 553 - */ 554 - r1 = sp; 555 - r0 = (-KERNEL_STACK_SIZE) (x); 556 - r1 = r1 & r0; 557 - p2 = r1; 558 - p3 = [p2]; 559 - r0 = KERNEL_STACK_SIZE - 4 (z); 560 - p1 = r0; 561 - p1 = p1 + p2; 562 - 563 - p0 = fp; 564 - r4 = [p0--]; 565 - r3 = SIZEOF_PTREGS / 4; 566 - .Lcopy_regs: 567 - r4 = [p0--]; 568 - [p1--] = r4; 569 - r3 += -1; 570 - cc = r3 == 0; 571 - if ! cc jump .Lcopy_regs (bp); 572 - 573 - r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); 574 - p1 = r0; 575 - p1 = p1 + p2; 576 - sp = p1; 577 - r0 = syscfg; 578 - [SP + PT_SYSCFG] = r0; 579 - [p3 + (TASK_THREAD + THREAD_KSP)] = sp; 580 - 581 - RESTORE_CONTEXT; 582 - rti; 583 - .Lexecve_failed: 584 - unlink; 585 - rts; 586 - ENDPROC(_kernel_execve) 587 - 588 533 ENTRY(_system_call) 589 534 /* Store IPEND */ 590 535 p2.l = lo(IPEND);
+1
arch/c6x/Kconfig
··· 18 18 select OF_EARLY_FLATTREE 19 19 select GENERIC_CLOCKEVENTS 20 20 select GENERIC_KERNEL_THREAD 21 + select GENERIC_KERNEL_EXECVE 21 22 select MODULES_USE_ELF_RELA 22 23 23 24 config MMU
-1
arch/c6x/include/uapi/asm/unistd.h
··· 14 14 * more details. 15 15 */ 16 16 17 - #define __ARCH_WANT_KERNEL_EXECVE 18 17 #define __ARCH_WANT_SYS_EXECVE 19 18 20 19 /* Use the standard ABI for syscalls. */
+1 -11
arch/c6x/kernel/entry.S
··· 413 413 0: 414 414 B .S2 B10 /* call fn */ 415 415 LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */ 416 - MVKL .S2 sys_exit,B11 417 - MVKH .S2 sys_exit,B11 418 - ADDKPC .S2 0f,B3,1 419 - 0: 420 - BNOP .S2 B11,5 /* jump to sys_exit */ 416 + ADDKPC .S2 ret_from_fork_2,B3,3 421 417 ENDPROC(ret_from_kernel_thread) 422 - 423 - ENTRY(ret_from_kernel_execve) 424 - GET_THREAD_INFO A12 425 - BNOP .S2 syscall_exit,4 426 - ADD .D2X A4,-8,SP 427 - ENDPROC(ret_from_kernel_execve) 428 418 429 419 ;; 430 420 ;; These are the interrupt handlers, responsible for calling __do_IRQ()
+2
arch/cris/Kconfig
··· 49 49 select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 50 50 select GENERIC_CMOS_UPDATE 51 51 select MODULES_USE_ELF_RELA 52 + select GENERIC_KERNEL_THREAD 53 + select GENERIC_KERNEL_EXECVE 52 54 53 55 config HZ 54 56 int
+9 -8
arch/cris/arch-v10/kernel/entry.S
··· 35 35 .globl system_call 36 36 .globl ret_from_intr 37 37 .globl ret_from_fork 38 + .globl ret_from_kernel_thread 38 39 .globl resume 39 40 .globl multiple_interrupt 40 41 .globl hwbreakpoint ··· 82 81 jsr schedule_tail 83 82 ba ret_from_sys_call 84 83 nop 85 - 84 + 85 + ret_from_kernel_thread: 86 + jsr schedule_tail 87 + move.d $r2, $r10 ; argument is here 88 + jsr $r1 ; call the payload 89 + moveq 0, $r9 ; no syscall restarts, TYVM... 90 + ba ret_from_sys_call 91 + 86 92 ret_from_intr: 87 93 ;; check for resched if preemptive kernel or if we're going back to user-mode 88 94 ;; this test matches the user_regs(regs) macro ··· 593 585 pop $r0 ; Restore r0. 594 586 ba do_sigtrap ; SIGTRAP the offending process. 595 587 pop $dccr ; Restore dccr in delay slot. 596 - 597 - .global kernel_execve 598 - kernel_execve: 599 - move.d __NR_execve, $r9 600 - break 13 601 - ret 602 - nop 603 588 604 589 .data 605 590
+24 -82
arch/cris/arch-v10/kernel/process.c
··· 17 17 #include <arch/svinto.h> 18 18 #include <linux/init.h> 19 19 #include <arch/system.h> 20 + #include <asm/ptrace.h> 20 21 21 22 #ifdef CONFIG_ETRAX_GPIO 22 23 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ ··· 82 81 return task_pt_regs(t)->irp; 83 82 } 84 83 85 - static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) 86 - { 87 - fn(arg); 88 - do_exit(-1); /* Should never be called, return bad exit value */ 89 - } 90 - 91 - /* 92 - * Create a kernel thread 93 - */ 94 - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 95 - { 96 - struct pt_regs regs; 97 - 98 - memset(&regs, 0, sizeof(regs)); 99 - 100 - /* Don't use r10 since that is set to 0 in copy_thread */ 101 - regs.r11 = (unsigned long)fn; 102 - regs.r12 = (unsigned long)arg; 103 - regs.irp = (unsigned long)kernel_thread_helper; 104 - regs.dccr = 1 << I_DCCR_BITNR; 105 - 106 - /* Ok, create the new process.. */ 107 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 108 - } 109 - 110 84 /* setup the child's kernel stack with a pt_regs and switch_stack on it. 111 85 * it will be un-nested during _resume and _ret_from_sys_call when the 112 86 * new thread is scheduled. ··· 91 115 * 92 116 */ 93 117 asmlinkage void ret_from_fork(void); 118 + asmlinkage void ret_from_kernel_thread(void); 94 119 95 120 int copy_thread(unsigned long clone_flags, unsigned long usp, 96 - unsigned long unused, 121 + unsigned long arg, 97 122 struct task_struct *p, struct pt_regs *regs) 98 123 { 99 - struct pt_regs * childregs; 100 - struct switch_stack *swstack; 124 + struct pt_regs *childregs = task_pt_regs(p); 125 + struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; 101 126 102 127 /* put the pt_regs structure at the end of the new kernel stack page and fix it up 103 128 * remember that the task_struct doubles as the kernel stack for the task 104 129 */ 105 130 106 - childregs = task_pt_regs(p); 107 - 131 + if (unlikely(p->flags & PF_KTHREAD)) { 132 + memset(swstack, 0, 133 + sizeof(struct switch_stack) + sizeof(struct pt_regs)); 134 + swstack->r1 = usp; 135 + swstack->r2 = arg; 136 + childregs->dccr = 1 << I_DCCR_BITNR; 137 + swstack->return_ip = (unsigned long) ret_from_kernel_thread; 138 + p->thread.ksp = (unsigned long) swstack; 139 + p->thread.usp = 0; 140 + return 0; 141 + } 108 142 *childregs = *regs; /* struct copy of pt_regs */ 109 - 110 - p->set_child_tid = p->clear_child_tid = NULL; 111 143 112 144 childregs->r10 = 0; /* child returns 0 after a fork/clone */ 113 - 114 - /* put the switch stack right below the pt_regs */ 115 145 116 - swstack = ((struct switch_stack *)childregs) - 1; 146 + /* put the switch stack right below the pt_regs */ 117 147 118 148 swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ 119 149 ··· 129 147 130 148 /* fix the user-mode stackpointer */ 131 149 132 - p->thread.usp = usp; 150 + p->thread.usp = usp; 133 151 134 152 /* and the kernel-mode one */ 135 153 ··· 143 161 return 0; 144 162 } 145 163 146 - /* 147 - * Be aware of the "magic" 7th argument in the four system-calls below. 148 - * They need the latest stackframe, which is put as the 7th argument by 149 - * entry.S. The previous arguments are dummies or actually used, but need 150 - * to be defined to reach the 7th argument. 151 - * 152 - * N.B.: Another method to get the stackframe is to use current_regs(). But 153 - * it returns the latest stack-frame stacked when going from _user mode_ and 154 - * some of these (at least sys_clone) are called from kernel-mode sometimes 155 - * (for example during kernel_thread, above) and thus cannot use it. Thus, 156 - * to be sure not to get any surprises, we use the method for the other calls 157 - * as well. 158 - */ 159 - 160 - asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, 161 - struct pt_regs *regs) 164 + asmlinkage int sys_fork(void) 162 165 { 163 - return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); 166 + return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); 164 167 } 165 168 166 169 /* if newusp is 0, we just grab the old usp */ 167 170 /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ 168 171 asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, 169 - int* parent_tid, int* child_tid, long mof, long srp, 170 - struct pt_regs *regs) 172 + int* parent_tid, int* child_tid) 171 173 { 172 174 if (!newusp) 173 175 newusp = rdusp(); 174 - return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); 176 + return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); 175 177 } 176 178 177 179 /* vfork is a system call in i386 because of register-pressure - maybe 178 180 * we can remove it and handle it in libc but we put it here until then. 179 181 */ 180 182 181 - asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, 182 - struct pt_regs *regs) 183 + asmlinkage int sys_vfork(void) 183 184 { 184 - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); 185 - } 186 - 187 - /* 188 - * sys_execve() executes a new program. 189 - */ 190 - asmlinkage int sys_execve(const char *fname, 191 - const char *const *argv, 192 - const char *const *envp, 193 - long r13, long mof, long srp, 194 - struct pt_regs *regs) 195 - { 196 - int error; 197 - struct filename *filename; 198 - 199 - filename = getname(fname); 200 - error = PTR_ERR(filename); 201 - 202 - if (IS_ERR(filename)) 203 - goto out; 204 - error = do_execve(filename->name, argv, envp, regs); 205 - putname(filename); 206 - out: 207 - return error; 185 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); 208 186 } 209 187 210 188 unsigned long get_wchan(struct task_struct *p)
+13 -9
arch/cris/arch-v32/kernel/entry.S
··· 31 31 .globl system_call 32 32 .globl ret_from_intr 33 33 .globl ret_from_fork 34 + .globl ret_from_kernel_thread 34 35 .globl resume 35 36 .globl multiple_interrupt 36 37 .globl nmi_interrupt ··· 84 83 ba ret_from_sys_call 85 84 nop 86 85 .size ret_from_fork, . - ret_from_fork 86 + 87 + .type ret_from_kernel_thread,@function 88 + ret_from_kernel_thread: 89 + jsr schedule_tail 90 + nop 91 + move.d $r2, $r10 92 + jsr $r1 93 + nop 94 + moveq 0, $r9 ; no syscall restarts, TYVM... 95 + ba ret_from_sys_call 96 + nop 97 + .size ret_from_kernel_thread, . - ret_from_kernel_thread 87 98 88 99 .type ret_from_intr,@function 89 100 ret_from_intr: ··· 543 530 _ugdb_handle_exception: 544 531 ba do_sigtrap ; SIGTRAP the offending process. 545 532 move.d [$sp+], $r0 ; Restore R0 in delay slot. 546 - 547 - .global kernel_execve 548 - .type kernel_execve,@function 549 - kernel_execve: 550 - move.d __NR_execve, $r9 551 - break 13 552 - ret 553 - nop 554 - .size kernel_execve, . - kernel_execve 555 533 556 534 .data 557 535
+22 -74
arch/cris/arch-v32/kernel/process.c
··· 16 16 #include <hwregs/reg_map.h> 17 17 #include <hwregs/timer_defs.h> 18 18 #include <hwregs/intr_vect_defs.h> 19 + #include <asm/ptrace.h> 19 20 20 21 extern void stop_watchdog(void); 21 22 ··· 95 94 return task_pt_regs(t)->erp; 96 95 } 97 96 98 - static void 99 - kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) 100 - { 101 - fn(arg); 102 - do_exit(-1); /* Should never be called, return bad exit value. */ 103 - } 104 - 105 - /* Create a kernel thread. */ 106 - int 107 - kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 108 - { 109 - struct pt_regs regs; 110 - 111 - memset(&regs, 0, sizeof(regs)); 112 - 113 - /* Don't use r10 since that is set to 0 in copy_thread. */ 114 - regs.r11 = (unsigned long) fn; 115 - regs.r12 = (unsigned long) arg; 116 - regs.erp = (unsigned long) kernel_thread_helper; 117 - regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); 118 - 119 - /* Create the new process. */ 120 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 121 - } 122 - 123 97 /* 124 98 * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. 125 99 * It will be unnested during _resume and _ret_from_sys_call when the new thread ··· 105 129 */ 106 130 107 131 extern asmlinkage void ret_from_fork(void); 132 + extern asmlinkage void ret_from_kernel_thread(void); 108 133 109 134 int 110 135 copy_thread(unsigned long clone_flags, unsigned long usp, 111 - unsigned long unused, 136 + unsigned long arg, 112 137 struct task_struct *p, struct pt_regs *regs) 113 138 { 114 - struct pt_regs *childregs; 115 - struct switch_stack *swstack; 139 + struct pt_regs *childregs = task_pt_regs(p); 140 + struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; 116 141 117 142 /* 118 143 * Put the pt_regs structure at the end of the new kernel stack page and 119 144 * fix it up. Note: the task_struct doubles as the kernel stack for the 120 145 * task. 121 146 */ 122 - childregs = task_pt_regs(p); 147 + if (unlikely(p->flags & PF_KTHREAD)) { 148 + memset(swstack, 0, 149 + sizeof(struct switch_stack) + sizeof(struct pt_regs)); 150 + swstack->r1 = usp; 151 + swstack->r2 = arg; 152 + childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); 153 + swstack->return_ip = (unsigned long) ret_from_kernel_thread; 154 + p->thread.ksp = (unsigned long) swstack; 155 + p->thread.usp = 0; 156 + return 0; 157 + } 123 158 *childregs = *regs; /* Struct copy of pt_regs. */ 124 - p->set_child_tid = p->clear_child_tid = NULL; 125 159 childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ 126 160 127 161 /* Set a new TLS ? ··· 142 156 } 143 157 144 158 /* Put the switch stack right below the pt_regs. */ 145 - swstack = ((struct switch_stack *) childregs) - 1; 146 159 147 160 /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ 148 161 swstack->r9 = 0; ··· 159 174 return 0; 160 175 } 161 176 162 - /* 163 - * Be aware of the "magic" 7th argument in the four system-calls below. 164 - * They need the latest stackframe, which is put as the 7th argument by 165 - * entry.S. The previous arguments are dummies or actually used, but need 166 - * to be defined to reach the 7th argument. 167 - * 168 - * N.B.: Another method to get the stackframe is to use current_regs(). But 169 - * it returns the latest stack-frame stacked when going from _user mode_ and 170 - * some of these (at least sys_clone) are called from kernel-mode sometimes 171 - * (for example during kernel_thread, above) and thus cannot use it. Thus, 172 - * to be sure not to get any surprises, we use the method for the other calls 173 - * as well. 174 - */ 175 177 asmlinkage int 176 - sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, 177 - struct pt_regs *regs) 178 + sys_fork(void) 178 179 { 179 - return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); 180 + return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); 180 181 } 181 182 182 183 /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ 183 184 asmlinkage int 184 185 sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid, 185 - unsigned long tls, long srp, struct pt_regs *regs) 186 + unsigned long tls) 186 187 { 187 188 if (!newusp) 188 189 newusp = rdusp(); 189 190 190 - return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); 191 + return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); 191 192 } 192 193 193 194 /* ··· 181 210 * we can remove it and handle it in libc but we put it here until then. 182 211 */ 183 212 asmlinkage int 184 - sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, 185 - struct pt_regs *regs) 213 + sys_vfork(void) 186 214 { 187 - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); 188 - } 189 - 190 - /* sys_execve() executes a new program. */ 191 - asmlinkage int 192 - sys_execve(const char *fname, 193 - const char *const *argv, 194 - const char *const *envp, long r13, long mof, long srp, 195 - struct pt_regs *regs) 196 - { 197 - int error; 198 - struct filename *filename; 199 - 200 - filename = getname(fname); 201 - error = PTR_ERR(filename); 202 - 203 - if (IS_ERR(filename)) 204 - goto out; 205 - 206 - error = do_execve(filename->name, argv, envp, regs); 207 - putname(filename); 208 - out: 209 - return error; 215 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); 210 216 } 211 217 212 218 unsigned long
-2
arch/cris/include/asm/processor.h
··· 49 49 #define task_pt_regs(task) user_regs(task_thread_info(task)) 50 50 #define current_regs() task_pt_regs(current) 51 51 52 - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 53 - 54 52 unsigned long get_wchan(struct task_struct *p); 55 53 56 54 #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
+1
arch/cris/include/asm/unistd.h
··· 371 371 #define __ARCH_WANT_SYS_SIGPROCMASK 372 372 #define __ARCH_WANT_SYS_RT_SIGACTION 373 373 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 374 + #define __ARCH_WANT_SYS_EXECVE 374 375 375 376 /* 376 377 * "Conditional" syscalls
-1
arch/cris/kernel/crisksyms.c
··· 30 30 extern void iounmap(volatile void * __iomem); 31 31 32 32 /* Platform dependent support */ 33 - EXPORT_SYMBOL(kernel_thread); 34 33 EXPORT_SYMBOL(get_cmos_time); 35 34 EXPORT_SYMBOL(loops_per_usec); 36 35
+2
arch/h8300/Kconfig
··· 8 8 select GENERIC_IRQ_SHOW 9 9 select GENERIC_CPU_DEVICES 10 10 select MODULES_USE_ELF_RELA 11 + select GENERIC_KERNEL_THREAD 12 + select GENERIC_KERNEL_EXECVE 11 13 12 14 config SYMBOL_PREFIX 13 15 string
-2
arch/h8300/include/asm/processor.h
··· 107 107 { 108 108 } 109 109 110 - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 111 - 112 110 /* 113 111 * Free current thread data structures etc.. 114 112 */
+2
arch/h8300/include/asm/ptrace.h
··· 60 60 #define user_mode(regs) (!((regs)->ccr & PS_S)) 61 61 #define instruction_pointer(regs) ((regs)->pc) 62 62 #define profile_pc(regs) instruction_pointer(regs) 63 + #define current_pt_regs() ((struct pt_regs *) \ 64 + (THREAD_SIZE + (unsigned long)current_thread_info()) - 1) 63 65 #endif /* __KERNEL__ */ 64 66 #endif /* __ASSEMBLY__ */ 65 67 #endif /* _H8300_PTRACE_H */
+1
arch/h8300/include/asm/unistd.h
··· 356 356 #define __ARCH_WANT_SYS_SIGPROCMASK 357 357 #define __ARCH_WANT_SYS_RT_SIGACTION 358 358 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 359 + #define __ARCH_WANT_SYS_EXECVE 359 360 360 361 /* 361 362 * "Conditional" syscalls
+9
arch/h8300/kernel/entry.S
··· 158 158 .globl SYMBOL_NAME(system_call) 159 159 .globl SYMBOL_NAME(ret_from_exception) 160 160 .globl SYMBOL_NAME(ret_from_fork) 161 + .globl SYMBOL_NAME(ret_from_kernel_thread) 161 162 .globl SYMBOL_NAME(ret_from_interrupt) 162 163 .globl SYMBOL_NAME(interrupt_redirect_table) 163 164 .globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp) ··· 329 328 SYMBOL_NAME_LABEL(ret_from_fork) 330 329 mov.l er2,er0 331 330 jsr @SYMBOL_NAME(schedule_tail) 331 + jmp @SYMBOL_NAME(ret_from_exception) 332 + 333 + SYMBOL_NAME_LABEL(ret_from_kernel_thread) 334 + mov.l er2,er0 335 + jsr @SYMBOL_NAME(schedule_tail) 336 + mov.l @(LER4:16,sp),er0 337 + mov.l @(LER5:16,sp),er1 338 + jsr @er1 332 339 jmp @SYMBOL_NAME(ret_from_exception) 333 340 334 341 SYMBOL_NAME_LABEL(resume)
-1
arch/h8300/kernel/h8300_ksyms.c
··· 33 33 34 34 EXPORT_SYMBOL(ip_fast_csum); 35 35 36 - EXPORT_SYMBOL(kernel_thread); 37 36 EXPORT_SYMBOL(enable_irq); 38 37 EXPORT_SYMBOL(disable_irq); 39 38
+8 -54
arch/h8300/kernel/process.c
··· 47 47 EXPORT_SYMBOL(pm_power_off); 48 48 49 49 asmlinkage void ret_from_fork(void); 50 + asmlinkage void ret_from_kernel_thread(void); 50 51 51 52 /* 52 53 * The idle loop on an H8/300.. ··· 123 122 printk("\n"); 124 123 } 125 124 126 - /* 127 - * Create a kernel thread 128 - */ 129 - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 130 - { 131 - long retval; 132 - long clone_arg; 133 - mm_segment_t fs; 134 - 135 - fs = get_fs(); 136 - set_fs (KERNEL_DS); 137 - clone_arg = flags | CLONE_VM; 138 - __asm__("mov.l sp,er3\n\t" 139 - "sub.l er2,er2\n\t" 140 - "mov.l %2,er1\n\t" 141 - "mov.l %1,er0\n\t" 142 - "trapa #0\n\t" 143 - "cmp.l sp,er3\n\t" 144 - "beq 1f\n\t" 145 - "mov.l %4,er0\n\t" 146 - "mov.l %3,er1\n\t" 147 - "jsr @er1\n\t" 148 - "mov.l %5,er0\n\t" 149 - "trapa #0\n" 150 - "1:\n\t" 151 - "mov.l er0,%0" 152 - :"=r"(retval) 153 - :"i"(__NR_clone),"g"(clone_arg),"g"(fn),"g"(arg),"i"(__NR_exit) 154 - :"er0","er1","er2","er3"); 155 - set_fs (fs); 156 - return retval; 157 - } 158 - 159 125 void flush_thread(void) 160 126 { 161 127 } ··· 166 198 167 199 childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; 168 200 201 + if (unlikely(p->flags & PF_KTHREAD)) { 202 + memset(childregs, 0, sizeof(struct pt_regs)); 203 + childregs->retpc = (unsigned long) ret_from_kernel_thread; 204 + childregs->er4 = topstk; /* arg */ 205 + childregs->er5 = usp; /* fn */ 206 + p->thread.ksp = (unsigned long)childregs; 207 + } 169 208 *childregs = *regs; 170 209 childregs->retpc = (unsigned long) ret_from_fork; 171 210 childregs->er0 = 0; ··· 181 206 p->thread.ksp = (unsigned long)childregs; 182 207 183 208 return 0; 184 - } 185 - 186 - /* 187 - * sys_execve() executes a new program. 188 - */ 189 - asmlinkage int sys_execve(const char *name, 190 - const char *const *argv, 191 - const char *const *envp, 192 - int dummy, ...) 193 - { 194 - int error; 195 - struct filename *filename; 196 - struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); 197 - 198 - filename = getname(name); 199 - error = PTR_ERR(filename); 200 - if (IS_ERR(filename)) 201 - return error; 202 - error = do_execve(filename->name, argv, envp, regs); 203 - putname(filename); 204 - return error; 205 209 } 206 210 207 211 unsigned long thread_saved_pc(struct task_struct *tsk)
-26
arch/h8300/kernel/sys_h8300.c
··· 46 46 ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0); 47 47 } 48 48 #endif 49 - 50 - /* 51 - * Do a system call from kernel instead of calling sys_execve so we 52 - * end up with proper pt_regs. 53 - */ 54 - asmlinkage 55 - int kernel_execve(const char *filename, 56 - const char *const argv[], 57 - const char *const envp[]) 58 - { 59 - register long res __asm__("er0"); 60 - register const char *const *_c __asm__("er3") = envp; 61 - register const char *const *_b __asm__("er2") = argv; 62 - register const char * _a __asm__("er1") = filename; 63 - __asm__ __volatile__ ("mov.l %1,er0\n\t" 64 - "trapa #0\n\t" 65 - : "=r" (res) 66 - : "g" (__NR_execve), 67 - "g" (_a), 68 - "g" (_b), 69 - "g" (_c) 70 - : "cc", "memory"); 71 - return res; 72 - } 73 - 74 -
+2
arch/hexagon/Kconfig
··· 31 31 select GENERIC_CLOCKEVENTS 32 32 select GENERIC_CLOCKEVENTS_BROADCAST 33 33 select MODULES_USE_ELF_RELA 34 + select GENERIC_KERNEL_THREAD 35 + select GENERIC_KERNEL_EXECVE 34 36 ---help--- 35 37 Qualcomm Hexagon is a processor architecture designed for high 36 38 performance and low power across a wide variety of applications.
-1
arch/hexagon/include/asm/processor.h
··· 34 34 struct task_struct; 35 35 36 36 /* this is defined in arch/process.c */ 37 - extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 38 37 extern unsigned long thread_saved_pc(struct task_struct *tsk); 39 38 40 39 extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
+4
arch/hexagon/include/uapi/asm/ptrace.h
··· 32 32 extern int regs_query_register_offset(const char *name); 33 33 extern const char *regs_query_register_name(unsigned int offset); 34 34 35 + #define current_pt_regs() \ 36 + ((struct pt_regs *) \ 37 + ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) 38 + 35 39 #endif
+1
arch/hexagon/include/uapi/asm/unistd.h
··· 27 27 */ 28 28 29 29 #define sys_mmap2 sys_mmap_pgoff 30 + #define __ARCH_WANT_SYS_EXECVE 30 31 31 32 #include <asm-generic/unistd.h>
+32 -70
arch/hexagon/kernel/process.c
··· 26 26 #include <linux/slab.h> 27 27 28 28 /* 29 - * Kernel thread creation. The desired kernel function is "wrapped" 30 - * in the kernel_thread_helper function, which does cleanup 31 - * afterwards. 32 - */ 33 - static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) 34 - { 35 - do_exit(fn(arg)); 36 - } 37 - 38 - int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 39 - { 40 - struct pt_regs regs; 41 - 42 - memset(&regs, 0, sizeof(regs)); 43 - /* 44 - * Yes, we're exploting illicit knowledge of the ABI here. 45 - */ 46 - regs.r00 = (unsigned long) arg; 47 - regs.r01 = (unsigned long) fn; 48 - pt_set_elr(&regs, (unsigned long)kernel_thread_helper); 49 - pt_set_kmode(&regs); 50 - 51 - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 52 - } 53 - EXPORT_SYMBOL(kernel_thread); 54 - 55 - /* 56 29 * Program thread launch. Often defined as a macro in processor.h, 57 30 * but we're shooting for a small footprint and it's not an inner-loop 58 31 * performance-critical operation. ··· 87 114 * Copy architecture-specific thread state 88 115 */ 89 116 int copy_thread(unsigned long clone_flags, unsigned long usp, 90 - unsigned long unused, struct task_struct *p, 117 + unsigned long arg, struct task_struct *p, 91 118 struct pt_regs *regs) 92 119 { 93 120 struct thread_info *ti = task_thread_info(p); ··· 98 125 childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) - 99 126 sizeof(*childregs)); 100 127 101 - memcpy(childregs, regs, sizeof(*childregs)); 102 128 ti->regs = childregs; 103 129 104 130 /* 105 131 * Establish kernel stack pointer and initial PC for new thread 132 + * Note that unlike the usual situation, we do not copy the 133 + * parent's callee-saved here; those are in pt_regs and whatever 134 + * we leave here will be overridden on return to userland. 106 135 */ 107 136 ss = (struct hexagon_switch_stack *) ((unsigned long) childregs - 108 137 sizeof(*ss)); 109 138 ss->lr = (unsigned long)ret_from_fork; 110 139 p->thread.switch_sp = ss; 111 - 112 - /* If User mode thread, set pt_reg stack pointer as per parameter */ 113 - if (user_mode(childregs)) { 114 - pt_set_rte_sp(childregs, usp); 115 - 116 - /* Child sees zero return value */ 117 - childregs->r00 = 0; 118 - 119 - /* 120 - * The clone syscall has the C signature: 121 - * int [r0] clone(int flags [r0], 122 - * void *child_frame [r1], 123 - * void *parent_tid [r2], 124 - * void *child_tid [r3], 125 - * void *thread_control_block [r4]); 126 - * ugp is used to provide TLS support. 127 - */ 128 - if (clone_flags & CLONE_SETTLS) 129 - childregs->ugp = childregs->r04; 130 - 131 - /* 132 - * Parent sees new pid -- not necessary, not even possible at 133 - * this point in the fork process 134 - * Might also want to set things like ti->addr_limit 135 - */ 136 - } else { 137 - /* 138 - * If kernel thread, resume stack is kernel stack base. 139 - * Note that this is pointer arithmetic on pt_regs * 140 - */ 141 - pt_set_rte_sp(childregs, (unsigned long)(childregs + 1)); 142 - /* 143 - * We need the current thread_info fast path pointer 144 - * set up in pt_regs. The register to be used is 145 - * parametric for assembler code, but the mechanism 146 - * doesn't drop neatly into C. Needs to be fixed. 147 - */ 148 - childregs->THREADINFO_REG = (unsigned long) ti; 140 + if (unlikely(p->flags & PF_KTHREAD)) { 141 + memset(childregs, 0, sizeof(struct pt_regs)); 142 + /* r24 <- fn, r25 <- arg */ 143 + ss->r2524 = usp | ((u64)arg << 32); 144 + pt_set_kmode(childregs); 145 + return 0; 149 146 } 147 + memcpy(childregs, regs, sizeof(*childregs)); 148 + ss->r2524 = 0; 149 + 150 + pt_set_rte_sp(childregs, usp); 151 + 152 + /* Child sees zero return value */ 153 + childregs->r00 = 0; 150 154 151 155 /* 152 - * thread_info pointer is pulled out of task_struct "stack" 153 - * field on switch_to. 156 + * The clone syscall has the C signature: 157 + * int [r0] clone(int flags [r0], 158 + * void *child_frame [r1], 159 + * void *parent_tid [r2], 160 + * void *child_tid [r3], 161 + * void *thread_control_block [r4]); 162 + * ugp is used to provide TLS support. 154 163 */ 155 - p->stack = (void *)ti; 164 + if (clone_flags & CLONE_SETTLS) 165 + childregs->ugp = childregs->r04; 166 + 167 + /* 168 + * Parent sees new pid -- not necessary, not even possible at 169 + * this point in the fork process 170 + * Might also want to set things like ti->addr_limit 171 + */ 156 172 157 173 return 0; 158 174 }
+2 -2
arch/hexagon/kernel/signal.c
··· 249 249 */ 250 250 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) 251 251 { 252 - struct pt_regs *regs = current_thread_info()->regs; 252 + struct pt_regs *regs = current_pt_regs(); 253 253 254 254 return do_sigaltstack(uss, uoss, regs->r29); 255 255 } 256 256 257 257 asmlinkage int sys_rt_sigreturn(void) 258 258 { 259 - struct pt_regs *regs = current_thread_info()->regs; 259 + struct pt_regs *regs = current_pt_regs(); 260 260 struct rt_sigframe __user *frame; 261 261 sigset_t blocked; 262 262
+1 -43
arch/hexagon/kernel/syscall.c
··· 35 35 * See signal.c for signal-related system call wrappers. 36 36 */ 37 37 38 - asmlinkage int sys_execve(char __user *ufilename, 39 - const char __user *const __user *argv, 40 - const char __user *const __user *envp) 41 - { 42 - struct pt_regs *pregs = current_thread_info()->regs; 43 - struct filename *filename; 44 - int retval; 45 - 46 - filename = getname(ufilename); 47 - retval = PTR_ERR(filename); 48 - if (IS_ERR(filename)) 49 - return retval; 50 - 51 - retval = do_execve(filename->name, argv, envp, pregs); 52 - putname(filename); 53 - 54 - return retval; 55 - } 56 - 57 38 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 58 39 unsigned long parent_tidp, unsigned long child_tidp) 59 40 { 60 - struct pt_regs *pregs = current_thread_info()->regs; 41 + struct pt_regs *pregs = current_pt_regs(); 61 42 62 43 if (!newsp) 63 44 newsp = pregs->SP; 64 45 return do_fork(clone_flags, newsp, pregs, 0, (int __user *)parent_tidp, 65 46 (int __user *)child_tidp); 66 - } 67 - 68 - /* 69 - * Do a system call from the kernel, so as to have a proper pt_regs 70 - * and recycle the sys_execvpe infrustructure. 71 - */ 72 - int kernel_execve(const char *filename, 73 - const char *const argv[], const char *const envp[]) 74 - { 75 - register unsigned long __a0 asm("r0") = (unsigned long) filename; 76 - register unsigned long __a1 asm("r1") = (unsigned long) argv; 77 - register unsigned long __a2 asm("r2") = (unsigned long) envp; 78 - int retval; 79 - 80 - __asm__ volatile( 81 - " R6 = #%4;\n" 82 - " trap0(#1);\n" 83 - " %0 = R0;\n" 84 - : "=r" (retval) 85 - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) 86 - ); 87 - 88 - return retval; 89 47 }
+4
arch/hexagon/kernel/vm_entry.S
··· 266 266 .globl ret_from_fork 267 267 ret_from_fork: 268 268 call schedule_tail 269 + P0 = cmp.eq(R24, #0); 270 + if P0 jump return_from_syscall 271 + R0 = R25; 272 + callr R24 269 273 jump return_from_syscall
+2
arch/ia64/Kconfig
··· 42 42 select GENERIC_TIME_VSYSCALL_OLD 43 43 select HAVE_MOD_ARCH_SPECIFIC 44 44 select MODULES_USE_ELF_RELA 45 + select GENERIC_KERNEL_THREAD 46 + select GENERIC_KERNEL_EXECVE 45 47 default y 46 48 help 47 49 The Itanium Processor Family is Intel's 64-bit successor to
-16
arch/ia64/include/asm/processor.h
··· 340 340 */ 341 341 #define release_thread(dead_task) 342 342 343 - /* 344 - * This is the mechanism for creating a new kernel thread. 345 - * 346 - * NOTE 1: Only a kernel-only process (ie the swapper or direct 347 - * descendants who haven't done an "execve()") should use this: it 348 - * will work within a system call from a "real" process, but the 349 - * process memory space will not be free'd until both the parent and 350 - * the child have exited. 351 - * 352 - * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get 353 - * into trouble in init/main.c when the child thread returns to 354 - * do_basic_setup() and the timing is such that free_initmem() has 355 - * been called already. 356 - */ 357 - extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); 358 - 359 343 /* Get wait channel for task P. */ 360 344 extern unsigned long get_wchan (struct task_struct *p); 361 345
+1
arch/ia64/include/asm/unistd.h
··· 29 29 30 30 #define __ARCH_WANT_SYS_RT_SIGACTION 31 31 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 32 + #define __ARCH_WANT_SYS_EXECVE 32 33 33 34 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) 34 35
+23 -16
arch/ia64/kernel/entry.S
··· 61 61 * Allocate 8 input registers since ptrace() may clobber them 62 62 */ 63 63 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) 64 - alloc loc1=ar.pfs,8,2,4,0 64 + alloc loc1=ar.pfs,8,2,3,0 65 65 mov loc0=rp 66 66 .body 67 67 mov out0=in0 // filename 68 68 ;; // stop bit between alloc and call 69 69 mov out1=in1 // argv 70 70 mov out2=in2 // envp 71 - add out3=16,sp // regs 72 71 br.call.sptk.many rp=sys_execve 73 72 .ret0: 74 73 cmp4.ge p6,p7=r8,r0 ··· 75 76 sxt4 r8=r8 // return 64-bit result 76 77 ;; 77 78 stf.spill [sp]=f0 78 - (p6) cmp.ne pKStk,pUStk=r0,r0 // a successful execve() lands us in user-mode... 79 79 mov rp=loc0 80 80 (p6) mov ar.pfs=r0 // clear ar.pfs on success 81 81 (p7) br.ret.sptk.many rp ··· 482 484 br.ret.sptk.many rp 483 485 END(prefetch_stack) 484 486 485 - GLOBAL_ENTRY(kernel_execve) 486 - rum psr.ac 487 - mov r15=__NR_execve // put syscall number in place 488 - break __BREAK_SYSCALL 489 - br.ret.sptk.many rp 490 - END(kernel_execve) 491 - 492 - GLOBAL_ENTRY(clone) 493 - mov r15=__NR_clone // put syscall number in place 494 - break __BREAK_SYSCALL 495 - br.ret.sptk.many rp 496 - END(clone) 497 - 498 487 /* 499 488 * Invoke a system call, but do some tracing before and after the call. 500 489 * We MUST preserve the current register frame throughout this routine ··· 585 600 .ret4: br.cond.sptk ia64_leave_kernel 586 601 END(ia64_strace_leave_kernel) 587 602 603 + ENTRY(call_payload) 604 + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(0) 605 + /* call the kernel_thread payload; fn is in r4, arg - in r5 */ 606 + alloc loc1=ar.pfs,0,3,1,0 607 + mov loc0=rp 608 + mov loc2=gp 609 + mov out0=r5 // arg 610 + ld8 r14 = [r4], 8 // fn.address 611 + ;; 612 + mov b6 = r14 613 + ld8 gp = [r4] // fn.gp 614 + ;; 615 + br.call.sptk.many rp=b6 // fn(arg) 616 + .ret12: mov gp=loc2 617 + mov rp=loc0 618 + mov ar.pfs=loc1 619 + /* ... and if it has returned, we are going to userland */ 620 + cmp.ne pKStk,pUStk=r0,r0 621 + br.ret.sptk.many rp 622 + END(call_payload) 623 + 588 624 GLOBAL_ENTRY(ia64_ret_from_clone) 589 625 PT_REGS_UNWIND_INFO(0) 590 626 { /* ··· 622 616 br.call.sptk.many rp=ia64_invoke_schedule_tail 623 617 } 624 618 .ret8: 619 + (pKStk) br.call.sptk.many rp=call_payload 625 620 adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 626 621 ;; 627 622 ld4 r2=[r2]
-13
arch/ia64/kernel/head.S
··· 1093 1093 END(cycle_to_cputime) 1094 1094 #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ 1095 1095 1096 - GLOBAL_ENTRY(start_kernel_thread) 1097 - .prologue 1098 - .save rp, r0 // this is the end of the call-chain 1099 - .body 1100 - alloc r2 = ar.pfs, 0, 0, 2, 0 1101 - mov out0 = r9 1102 - mov out1 = r11;; 1103 - br.call.sptk.many rp = kernel_thread_helper;; 1104 - mov out0 = r8 1105 - br.call.sptk.many rp = sys_exit;; 1106 - 1: br.sptk.few 1b // not reached 1107 - END(start_kernel_thread) 1108 - 1109 1096 #ifdef CONFIG_IA64_BRL_EMU 1110 1097 1111 1098 /*
+58 -100
arch/ia64/kernel/process.c
··· 401 401 struct pt_regs *child_ptregs; 402 402 int retval = 0; 403 403 404 - #ifdef CONFIG_SMP 405 - /* 406 - * For SMP idle threads, fork_by_hand() calls do_fork with 407 - * NULL regs. 408 - */ 409 - if (!regs) 410 - return 0; 411 - #endif 412 - 413 - stack = ((struct switch_stack *) regs) - 1; 414 - 415 404 child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; 416 405 child_stack = (struct switch_stack *) child_ptregs - 1; 417 406 418 - /* copy parent's switch_stack & pt_regs to child: */ 419 - memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); 420 - 421 407 rbs = (unsigned long) current + IA64_RBS_OFFSET; 422 408 child_rbs = (unsigned long) p + IA64_RBS_OFFSET; 423 - rbs_size = stack->ar_bspstore - rbs; 424 - 425 - /* copy the parent's register backing store to the child: */ 426 - memcpy((void *) child_rbs, (void *) rbs, rbs_size); 427 - 428 - if (likely(user_mode(child_ptregs))) { 429 - if (clone_flags & CLONE_SETTLS) 430 - child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ 431 - if (user_stack_base) { 432 - child_ptregs->r12 = user_stack_base + user_stack_size - 16; 433 - child_ptregs->ar_bspstore = user_stack_base; 434 - child_ptregs->ar_rnat = 0; 435 - child_ptregs->loadrs = 0; 436 - } 437 - } else { 438 - /* 439 - * Note: we simply preserve the relative position of 440 - * the stack pointer here. There is no need to 441 - * allocate a scratch area here, since that will have 442 - * been taken care of by the caller of sys_clone() 443 - * already. 444 - */ 445 - child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ 446 - child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ 447 - } 448 - child_stack->ar_bspstore = child_rbs + rbs_size; 449 - child_stack->b0 = (unsigned long) &ia64_ret_from_clone; 450 409 451 410 /* copy parts of thread_struct: */ 452 411 p->thread.ksp = (unsigned long) child_stack - 16; 453 - 454 - /* stop some PSR bits from being inherited. 455 - * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() 456 - * therefore we must specify them explicitly here and not include them in 457 - * IA64_PSR_BITS_TO_CLEAR. 458 - */ 459 - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) 460 - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); 461 412 462 413 /* 463 414 * NOTE: The calling convention considers all floating point ··· 431 480 # define THREAD_FLAGS_TO_SET 0 432 481 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) 433 482 | THREAD_FLAGS_TO_SET); 483 + 434 484 ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ 485 + 486 + if (unlikely(p->flags & PF_KTHREAD)) { 487 + if (unlikely(!user_stack_base)) { 488 + /* fork_idle() called us */ 489 + return 0; 490 + } 491 + memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); 492 + child_stack->r4 = user_stack_base; /* payload */ 493 + child_stack->r5 = user_stack_size; /* argument */ 494 + /* 495 + * Preserve PSR bits, except for bits 32-34 and 37-45, 496 + * which we can't read. 497 + */ 498 + child_ptregs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; 499 + /* mark as valid, empty frame */ 500 + child_ptregs->cr_ifs = 1UL << 63; 501 + child_stack->ar_fpsr = child_ptregs->ar_fpsr 502 + = ia64_getreg(_IA64_REG_AR_FPSR); 503 + child_stack->pr = (1 << PRED_KERNEL_STACK); 504 + child_stack->ar_bspstore = child_rbs; 505 + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; 506 + 507 + /* stop some PSR bits from being inherited. 508 + * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() 509 + * therefore we must specify them explicitly here and not include them in 510 + * IA64_PSR_BITS_TO_CLEAR. 511 + */ 512 + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) 513 + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); 514 + 515 + return 0; 516 + } 517 + stack = ((struct switch_stack *) regs) - 1; 518 + /* copy parent's switch_stack & pt_regs to child: */ 519 + memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); 520 + 521 + /* copy the parent's register backing store to the child: */ 522 + rbs_size = stack->ar_bspstore - rbs; 523 + memcpy((void *) child_rbs, (void *) rbs, rbs_size); 524 + if (clone_flags & CLONE_SETTLS) 525 + child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ 526 + if (user_stack_base) { 527 + child_ptregs->r12 = user_stack_base + user_stack_size - 16; 528 + child_ptregs->ar_bspstore = user_stack_base; 529 + child_ptregs->ar_rnat = 0; 530 + child_ptregs->loadrs = 0; 531 + } 532 + child_stack->ar_bspstore = child_rbs + rbs_size; 533 + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; 534 + 535 + /* stop some PSR bits from being inherited. 536 + * the psr.up/psr.pp bits must be cleared on fork but inherited on execve() 537 + * therefore we must specify them explicitly here and not include them in 538 + * IA64_PSR_BITS_TO_CLEAR. 539 + */ 540 + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) 541 + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); 435 542 436 543 #ifdef CONFIG_PERFMON 437 544 if (current->thread.pfm_context) ··· 615 606 { 616 607 unw_init_running(do_dump_fpu, dst); 617 608 return 1; /* f0-f31 are always valid so we always return 1 */ 618 - } 619 - 620 - long 621 - sys_execve (const char __user *filename, 622 - const char __user *const __user *argv, 623 - const char __user *const __user *envp, 624 - struct pt_regs *regs) 625 - { 626 - struct filename *fname; 627 - int error; 628 - 629 - fname = getname(filename); 630 - error = PTR_ERR(fname); 631 - if (IS_ERR(fname)) 632 - goto out; 633 - error = do_execve(fname->name, argv, envp, regs); 634 - putname(fname); 635 - out: 636 - return error; 637 - } 638 - 639 - pid_t 640 - kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) 641 - { 642 - extern void start_kernel_thread (void); 643 - unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread; 644 - struct { 645 - struct switch_stack sw; 646 - struct pt_regs pt; 647 - } regs; 648 - 649 - memset(&regs, 0, sizeof(regs)); 650 - regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ 651 - regs.pt.r1 = helper_fptr[1]; /* set GP */ 652 - regs.pt.r9 = (unsigned long) fn; /* 1st argument */ 653 - regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ 654 - /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ 655 - regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; 656 - regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ 657 - regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); 658 - regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; 659 - regs.sw.pr = (1 << PRED_KERNEL_STACK); 660 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL); 661 - } 662 - EXPORT_SYMBOL(kernel_thread); 663 - 664 - /* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ 665 - int 666 - kernel_thread_helper (int (*fn)(void *), void *arg) 667 - { 668 - return (*fn)(arg); 669 609 } 670 610 671 611 /*
+2
arch/m32r/Kconfig
··· 15 15 select GENERIC_ATOMIC64 16 16 select ARCH_USES_GETTIMEOFFSET 17 17 select MODULES_USE_ELF_RELA 18 + select GENERIC_KERNEL_THREAD 19 + select GENERIC_KERNEL_EXECVE 18 20 19 21 config SBUS 20 22 bool
-5
arch/m32r/include/asm/processor.h
··· 118 118 /* Free all resources held by a thread. */ 119 119 extern void release_thread(struct task_struct *); 120 120 121 - /* 122 - * create a kernel thread without removing it from tasklists 123 - */ 124 - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 125 - 126 121 /* Copy and release all segment info associated with a VM */ 127 122 extern void copy_segments(struct task_struct *p, struct mm_struct * mm); 128 123 extern void release_segments(struct mm_struct * mm);
+2
arch/m32r/include/asm/ptrace.h
··· 139 139 140 140 #define task_pt_regs(task) \ 141 141 ((struct pt_regs *)(task_stack_page(task) + THREAD_SIZE) - 1) 142 + #define current_pt_regs() ((struct pt_regs *) \ 143 + ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) 142 144 143 145 #endif /* __KERNEL */ 144 146
+1
arch/m32r/include/asm/unistd.h
··· 352 352 #define __ARCH_WANT_SYS_OLDUMOUNT 353 353 #define __ARCH_WANT_SYS_RT_SIGACTION 354 354 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 355 + #define __ARCH_WANT_SYS_EXECVE 355 356 356 357 #define __IGNORE_lchown 357 358 #define __IGNORE_setuid
+9
arch/m32r/kernel/entry.S
··· 125 125 and \reg, sp 126 126 .endm 127 127 128 + ENTRY(ret_from_kernel_thread) 129 + pop r0 130 + bl schedule_tail 131 + GET_THREAD_INFO(r8) 132 + ld r0, R0(r8) 133 + ld r1, R1(r8) 134 + jl r1 135 + bra syscall_exit 136 + 128 137 ENTRY(ret_from_fork) 129 138 pop r0 130 139 bl schedule_tail
+25 -79
arch/m32r/kernel/process.c
··· 165 165 } 166 166 167 167 /* 168 - * Create a kernel thread 169 - */ 170 - 171 - /* 172 - * This is the mechanism for creating a new kernel thread. 173 - * 174 - * NOTE! Only a kernel-only process(ie the swapper or direct descendants 175 - * who haven't done an "execve()") should use this: it will work within 176 - * a system call from a "real" process, but the process memory space will 177 - * not be free'd until both the parent and the child have exited. 178 - */ 179 - static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg) 180 - { 181 - fn(arg); 182 - do_exit(-1); 183 - } 184 - 185 - int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 186 - { 187 - struct pt_regs regs; 188 - 189 - memset(&regs, 0, sizeof (regs)); 190 - regs.r1 = (unsigned long)fn; 191 - regs.r2 = (unsigned long)arg; 192 - 193 - regs.bpc = (unsigned long)kernel_thread_helper; 194 - 195 - regs.psw = M32R_PSW_BIE; 196 - 197 - /* Ok, create the new process. */ 198 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, 199 - NULL); 200 - } 201 - 202 - /* 203 168 * Free current thread data structures etc.. 204 169 */ 205 170 void exit_thread(void) ··· 192 227 } 193 228 194 229 int copy_thread(unsigned long clone_flags, unsigned long spu, 195 - unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) 230 + unsigned long arg, struct task_struct *tsk, struct pt_regs *regs) 196 231 { 197 232 struct pt_regs *childregs = task_pt_regs(tsk); 198 233 extern void ret_from_fork(void); 234 + extern void ret_from_kernel_thread(void); 199 235 200 - /* Copy registers */ 201 - *childregs = *regs; 202 - 203 - childregs->spu = spu; 204 - childregs->r0 = 0; /* Child gets zero as return value */ 205 - regs->r0 = tsk->pid; 236 + if (unlikely(tsk->flags & PF_KTHREAD)) { 237 + memset(childregs, 0, sizeof(struct pt_regs)); 238 + childregs->psw = M32R_PSW_BIE; 239 + childregs->r1 = spu; /* fn */ 240 + childregs->r0 = arg; 241 + tsk->thread.lr = (unsigned long)ret_from_kernel_thread; 242 + } else { 243 + /* Copy registers */ 244 + *childregs = *regs; 245 + childregs->spu = spu; 246 + childregs->r0 = 0; /* Child gets zero as return value */ 247 + tsk->thread.lr = (unsigned long)ret_from_fork; 248 + } 206 249 tsk->thread.sp = (unsigned long)childregs; 207 - tsk->thread.lr = (unsigned long)ret_from_fork; 208 250 209 251 return 0; 210 252 } 211 253 212 - asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, 213 - unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, 214 - struct pt_regs regs) 254 + asmlinkage int sys_fork(void) 215 255 { 216 256 #ifdef CONFIG_MMU 217 - return do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL); 257 + struct pt_regs *regs = current_pt_regs(); 258 + return do_fork(SIGCHLD, regs->spu, regs, 0, NULL, NULL); 218 259 #else 219 260 return -EINVAL; 220 261 #endif /* CONFIG_MMU */ ··· 228 257 229 258 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 230 259 unsigned long parent_tidptr, 231 - unsigned long child_tidptr, 232 - unsigned long r4, unsigned long r5, unsigned long r6, 233 - struct pt_regs regs) 260 + unsigned long child_tidptr) 234 261 { 262 + struct pt_regs *regs = current_pt_regs(); 235 263 if (!newsp) 236 - newsp = regs.spu; 264 + newsp = regs->spu; 237 265 238 - return do_fork(clone_flags, newsp, &regs, 0, 266 + return do_fork(clone_flags, newsp, regs, 0, 239 267 (int __user *)parent_tidptr, (int __user *)child_tidptr); 240 268 } 241 269 ··· 248 278 * do not have enough call-clobbered registers to hold all 249 279 * the information you need. 250 280 */ 251 - asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2, 252 - unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, 253 - struct pt_regs regs) 281 + asmlinkage int sys_vfork(void) 254 282 { 255 - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0, 283 + struct pt_regs *regs = current_pt_regs(); 284 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->spu, regs, 0, 256 285 NULL, NULL); 257 - } 258 - 259 - /* 260 - * sys_execve() executes a new program. 261 - */ 262 - asmlinkage int sys_execve(const char __user *ufilename, 263 - const char __user *const __user *uargv, 264 - const char __user *const __user *uenvp, 265 - unsigned long r3, unsigned long r4, unsigned long r5, 266 - unsigned long r6, struct pt_regs regs) 267 - { 268 - int error; 269 - struct filename *filename; 270 - 271 - filename = getname(ufilename); 272 - error = PTR_ERR(filename); 273 - if (IS_ERR(filename)) 274 - goto out; 275 - 276 - error = do_execve(filename->name, uargv, uenvp, &regs); 277 - putname(filename); 278 - out: 279 - return error; 280 286 } 281 287 282 288 /*
-21
arch/m32r/kernel/sys_m32r.c
··· 88 88 /* Not implemented yet. */ 89 89 return -ENOSYS; 90 90 } 91 - 92 - /* 93 - * Do a system call from kernel instead of calling sys_execve so we 94 - * end up with proper pt_regs. 95 - */ 96 - int kernel_execve(const char *filename, 97 - const char *const argv[], 98 - const char *const envp[]) 99 - { 100 - register long __scno __asm__ ("r7") = __NR_execve; 101 - register long __arg3 __asm__ ("r2") = (long)(envp); 102 - register long __arg2 __asm__ ("r1") = (long)(argv); 103 - register long __res __asm__ ("r0") = (long)(filename); 104 - __asm__ __volatile__ ( 105 - "trap #" SYSCALL_VECTOR "|| nop" 106 - : "=r" (__res) 107 - : "r" (__scno), "0" (__res), "r" (__arg2), 108 - "r" (__arg3) 109 - : "memory"); 110 - return __res; 111 - }
+1
arch/m68k/Kconfig
··· 16 16 select ARCH_WANT_IPC_PARSE_VERSION 17 17 select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE 18 18 select GENERIC_KERNEL_THREAD 19 + select GENERIC_KERNEL_EXECVE 19 20 select HAVE_MOD_ARCH_SPECIFIC 20 21 select MODULES_USE_ELF_REL 21 22 select MODULES_USE_ELF_RELA
-1
arch/m68k/include/asm/unistd.h
··· 32 32 #define __ARCH_WANT_SYS_RT_SIGACTION 33 33 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 34 34 #define __ARCH_WANT_SYS_EXECVE 35 - #define __ARCH_WANT_KERNEL_EXECVE 36 35 37 36 /* 38 37 * "Conditional" syscalls
-7
arch/m68k/kernel/entry.S
··· 115 115 | a3 contains the kernel thread payload, d7 - its argument 116 116 movel %d1,%sp@- 117 117 jsr schedule_tail 118 - GET_CURRENT(%d0) 119 118 movel %d7,(%sp) 120 119 jsr %a3@ 121 120 addql #4,%sp 122 - movel %d0,(%sp) 123 - jra sys_exit 124 - 125 - ENTRY(ret_from_kernel_execve) 126 - movel 4(%sp), %sp 127 - GET_CURRENT(%d0) 128 121 jra ret_from_exception 129 122 130 123 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
+2
arch/microblaze/Kconfig
··· 26 26 select GENERIC_ATOMIC64 27 27 select GENERIC_CLOCKEVENTS 28 28 select MODULES_USE_ELF_RELA 29 + select GENERIC_KERNEL_THREAD 30 + select GENERIC_KERNEL_EXECVE 29 31 30 32 config SWAP 31 33 def_bool n
+1 -7
arch/microblaze/include/asm/processor.h
··· 31 31 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp); 32 32 33 33 extern void ret_from_fork(void); 34 + extern void ret_from_kernel_thread(void); 34 35 35 36 # endif /* __ASSEMBLY__ */ 36 37 ··· 78 77 extern unsigned long thread_saved_pc(struct task_struct *t); 79 78 80 79 extern unsigned long get_wchan(struct task_struct *p); 81 - 82 - /* 83 - * create a kernel thread without removing it from tasklists 84 - */ 85 - extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 86 80 87 81 # define KSTK_EIP(tsk) (0) 88 82 # define KSTK_ESP(tsk) (0) ··· 126 130 extern inline void release_thread(struct task_struct *dead_task) 127 131 { 128 132 } 129 - 130 - extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 131 133 132 134 /* Free current thread data structures etc. */ 133 135 static inline void exit_thread(void)
+1
arch/microblaze/include/asm/unistd.h
··· 422 422 #define __ARCH_WANT_SYS_SIGPROCMASK 423 423 #define __ARCH_WANT_SYS_RT_SIGACTION 424 424 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 425 + #define __ARCH_WANT_SYS_EXECVE 425 426 426 427 /* 427 428 * "Conditional" syscalls
+8 -4
arch/microblaze/kernel/entry-nommu.S
··· 474 474 brid ret_to_user 475 475 nop 476 476 477 + ENTRY(ret_from_kernel_thread) 478 + brlid r15, schedule_tail 479 + addk r5, r0, r3 480 + brald r15, r20 481 + addk r5, r0, r19 482 + brid ret_to_user 483 + addk r3, r0, r0 484 + 477 485 work_pending: 478 486 enable_irq 479 487 ··· 566 558 sys_clone: 567 559 brid microblaze_clone 568 560 addk r7, r1, r0 569 - 570 - sys_execve: 571 - brid microblaze_execve 572 - addk r8, r1, r0 573 561 574 562 sys_rt_sigreturn_wrapper: 575 563 brid sys_rt_sigreturn
+10 -23
arch/microblaze/kernel/entry.S
··· 293 293 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ 294 294 addi r14, r14, 4 /* return address is 4 byte after call */ 295 295 296 - mfs r1, rmsr 297 - nop 298 - andi r1, r1, MSR_UMS 299 - bnei r1, 1f 300 - 301 - /* Kernel-mode state save - kernel execve */ 302 - lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ 303 - tophys(r1,r1); 304 - 305 - addik r1, r1, -PT_SIZE; /* Make room on the stack. */ 306 - SAVE_REGS 307 - 308 - swi r1, r1, PT_MODE; /* pt_regs -> kernel mode */ 309 - brid 2f; 310 - nop; /* Fill delay slot */ 311 - 312 - /* User-mode state save. */ 313 - 1: 314 296 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 315 297 tophys(r1,r1); 316 298 lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ ··· 461 479 saved context). */ 462 480 C_ENTRY(ret_from_fork): 463 481 bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 464 - add r3, r5, r0; /* switch_thread returns the prev task */ 482 + add r5, r3, r0; /* switch_thread returns the prev task */ 465 483 /* ( in the delay slot ) */ 466 484 brid ret_from_trap; /* Do normal trap return */ 467 485 add r3, r0, r0; /* Child's fork call should return 0. */ 486 + 487 + C_ENTRY(ret_from_kernel_thread): 488 + bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 489 + add r5, r3, r0; /* switch_thread returns the prev task */ 490 + /* ( in the delay slot ) */ 491 + brald r15, r20 /* fn was left in r20 */ 492 + addk r5, r0, r19 /* ... and argument - in r19 */ 493 + brid ret_from_trap 494 + add r3, r0, r0 468 495 469 496 C_ENTRY(sys_vfork): 470 497 brid microblaze_vfork /* Do real work (tail-call) */ ··· 488 497 /* do_fork will pick up TLS from regs->r10. */ 489 498 brid do_fork /* Do real work (tail-call) */ 490 499 add r8, r0, r0; /* Arg 3: (unused) */ 491 - 492 - C_ENTRY(sys_execve): 493 - brid microblaze_execve; /* Do real work (tail-call).*/ 494 - addik r8, r1, 0; /* add user context as 4th arg */ 495 500 496 501 C_ENTRY(sys_rt_sigreturn_wrapper): 497 502 brid sys_rt_sigreturn /* Do real work */
+21 -51
arch/microblaze/kernel/process.c
··· 119 119 } 120 120 121 121 int copy_thread(unsigned long clone_flags, unsigned long usp, 122 - unsigned long unused, 122 + unsigned long arg, 123 123 struct task_struct *p, struct pt_regs *regs) 124 124 { 125 125 struct pt_regs *childregs = task_pt_regs(p); 126 126 struct thread_info *ti = task_thread_info(p); 127 127 128 + if (unlikely(p->flags & PF_KTHREAD)) { 129 + /* if we're creating a new kernel thread then just zeroing all 130 + * the registers. That's OK for a brand new thread.*/ 131 + memset(childregs, 0, sizeof(struct pt_regs)); 132 + memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 133 + ti->cpu_context.r1 = (unsigned long)childregs; 134 + ti->cpu_context.r20 = (unsigned long)usp; /* fn */ 135 + ti->cpu_context.r19 = (unsigned long)arg; 136 + childregs->pt_mode = 1; 137 + local_save_flags(childregs->msr); 138 + #ifdef CONFIG_MMU 139 + ti->cpu_context.msr = childregs->msr & ~MSR_IE; 140 + #endif 141 + ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8; 142 + return 0; 143 + } 128 144 *childregs = *regs; 129 - if (user_mode(regs)) 130 - childregs->r1 = usp; 131 - else 132 - childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; 145 + childregs->r1 = usp; 133 146 134 - #ifndef CONFIG_MMU 135 147 memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 136 148 ti->cpu_context.r1 = (unsigned long)childregs; 149 + #ifndef CONFIG_MMU 137 150 ti->cpu_context.msr = (unsigned long)childregs->msr; 138 151 #else 152 + childregs->msr |= MSR_UMS; 139 153 140 - /* if creating a kernel thread then update the current reg (we don't 141 - * want to use the parent's value when restoring by POP_STATE) */ 142 - if (kernel_mode(regs)) 143 - /* save new current on stack to use POP_STATE */ 144 - childregs->CURRENT_TASK = (unsigned long)p; 145 - /* if returning to user then use the parent's value of this register */ 146 - 147 - /* if we're creating a new kernel thread then just zeroing all 148 - * the registers. That's OK for a brand new thread.*/ 149 - /* Pls. note that some of them will be restored in POP_STATE */ 150 - if (kernel_mode(regs)) 151 - memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); 152 - /* if this thread is created for fork/vfork/clone, then we want to 153 - * restore all the parent's context */ 154 - /* in addition to the registers which will be restored by POP_STATE */ 155 - else { 156 - ti->cpu_context = *(struct cpu_context *)regs; 157 - childregs->msr |= MSR_UMS; 158 - } 159 - 160 - /* FIXME STATE_SAVE_PT_OFFSET; */ 161 - ti->cpu_context.r1 = (unsigned long)childregs; 162 154 /* we should consider the fact that childregs is a copy of the parent 163 155 * regs which were saved immediately after entering the kernel state 164 156 * before enabling VM. This MSR will be restored in switch_to and ··· 201 209 } 202 210 #endif 203 211 204 - static void kernel_thread_helper(int (*fn)(void *), void *arg) 205 - { 206 - fn(arg); 207 - do_exit(-1); 208 - } 209 - 210 - int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 211 - { 212 - struct pt_regs regs; 213 - 214 - memset(&regs, 0, sizeof(regs)); 215 - /* store them in non-volatile registers */ 216 - regs.r5 = (unsigned long)fn; 217 - regs.r6 = (unsigned long)arg; 218 - local_save_flags(regs.msr); 219 - regs.pc = (unsigned long)kernel_thread_helper; 220 - regs.pt_mode = 1; 221 - 222 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, 223 - &regs, 0, NULL, NULL); 224 - } 225 - EXPORT_SYMBOL_GPL(kernel_thread); 226 - 227 212 unsigned long get_wchan(struct task_struct *p) 228 213 { 229 214 /* TBD (used by procfs) */ ··· 215 246 regs->pt_mode = 0; 216 247 #ifdef CONFIG_MMU 217 248 regs->msr |= MSR_UMS; 249 + regs->msr &= ~MSR_VM; 218 250 #endif 219 251 } 220 252
-39
arch/microblaze/kernel/sys_microblaze.c
··· 48 48 return do_fork(flags, stack, regs, 0, NULL, NULL); 49 49 } 50 50 51 - asmlinkage long microblaze_execve(const char __user *filenamei, 52 - const char __user *const __user *argv, 53 - const char __user *const __user *envp, 54 - struct pt_regs *regs) 55 - { 56 - int error; 57 - struct filename *filename; 58 - 59 - filename = getname(filenamei); 60 - error = PTR_ERR(filename); 61 - if (IS_ERR(filename)) 62 - goto out; 63 - error = do_execve(filename->name, argv, envp, regs); 64 - putname(filename); 65 - out: 66 - return error; 67 - } 68 - 69 51 asmlinkage long sys_mmap(unsigned long addr, unsigned long len, 70 52 unsigned long prot, unsigned long flags, 71 53 unsigned long fd, off_t pgoff) ··· 56 74 return -EINVAL; 57 75 58 76 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT); 59 - } 60 - 61 - /* 62 - * Do a system call from kernel instead of calling sys_execve so we 63 - * end up with proper pt_regs. 64 - */ 65 - int kernel_execve(const char *filename, 66 - const char *const argv[], 67 - const char *const envp[]) 68 - { 69 - register const char *__a __asm__("r5") = filename; 70 - register const void *__b __asm__("r6") = argv; 71 - register const void *__c __asm__("r7") = envp; 72 - register unsigned long __syscall __asm__("r12") = __NR_execve; 73 - register unsigned long __ret __asm__("r3"); 74 - __asm__ __volatile__ ("brki r14, 0x8" 75 - : "=r" (__ret), "=r" (__syscall) 76 - : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) 77 - : "r4", "r8", "r9", 78 - "r10", "r11", "r14", "cc", "memory"); 79 - return __ret; 80 77 }
+2
arch/mips/Kconfig
··· 40 40 select HAVE_MOD_ARCH_SPECIFIC 41 41 select MODULES_USE_ELF_REL 42 42 select MODULES_USE_ELF_RELA if 64BIT 43 + select GENERIC_KERNEL_THREAD 44 + select GENERIC_KERNEL_EXECVE 43 45 44 46 menu "Machine selection" 45 47
-2
arch/mips/include/asm/processor.h
··· 310 310 /* Free all resources held by a thread. */ 311 311 #define release_thread(thread) do { } while(0) 312 312 313 - extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 314 - 315 313 extern unsigned long thread_saved_pc(struct task_struct *tsk); 316 314 317 315 /*
+6
arch/mips/include/asm/ptrace.h
··· 61 61 die(str, regs); 62 62 } 63 63 64 + #define current_pt_regs() \ 65 + ({ \ 66 + unsigned long sp = (unsigned long)__builtin_frame_address(0); \ 67 + (struct pt_regs *)((sp | (THREAD_SIZE - 1)) + 1 - 32) - 1; \ 68 + }) 69 + 64 70 #endif /* _ASM_PTRACE_H */
+1
arch/mips/include/asm/unistd.h
··· 20 20 #define __ARCH_OMIT_COMPAT_SYS_GETDENTS64 21 21 #define __ARCH_WANT_OLD_READDIR 22 22 #define __ARCH_WANT_SYS_ALARM 23 + #define __ARCH_WANT_SYS_EXECVE 23 24 #define __ARCH_WANT_SYS_GETHOSTNAME 24 25 #define __ARCH_WANT_SYS_IPC 25 26 #define __ARCH_WANT_SYS_PAUSE
+6
arch/mips/kernel/entry.S
··· 65 65 b need_resched 66 66 #endif 67 67 68 + FEXPORT(ret_from_kernel_thread) 69 + jal schedule_tail # a0 = struct task_struct *prev 70 + move a0, s1 71 + jal s0 72 + j syscall_exit 73 + 68 74 FEXPORT(ret_from_fork) 69 75 jal schedule_tail # a0 = struct task_struct *prev 70 76
-21
arch/mips/kernel/linux32.c
··· 3 3 * 4 4 * Copyright (C) 2000 Silicon Graphics, Inc. 5 5 * Written by Ulf Carlsson (ulfc@engr.sgi.com) 6 - * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) 7 6 */ 8 7 #include <linux/compiler.h> 9 8 #include <linux/mm.h> ··· 72 73 goto out; 73 74 error = sys_mmap_pgoff(addr, len, prot, flags, fd, 74 75 pgoff >> (PAGE_SHIFT-12)); 75 - out: 76 - return error; 77 - } 78 - 79 - /* 80 - * sys_execve() executes a new program. 81 - */ 82 - asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) 83 - { 84 - int error; 85 - struct filename *filename; 86 - 87 - filename = getname(compat_ptr(regs.regs[4])); 88 - error = PTR_ERR(filename); 89 - if (IS_ERR(filename)) 90 - goto out; 91 - error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]), 92 - compat_ptr(regs.regs[6]), &regs); 93 - putname(filename); 94 - 95 76 out: 96 77 return error; 97 78 }
-2
arch/mips/kernel/mips_ksyms.c
··· 32 32 EXPORT_SYMBOL(memcpy); 33 33 EXPORT_SYMBOL(memmove); 34 34 35 - EXPORT_SYMBOL(kernel_thread); 36 - 37 35 /* 38 36 * Functions that operate on entire pages. Mostly used by memory management. 39 37 */
+22 -40
arch/mips/kernel/process.c
··· 84 84 } 85 85 86 86 asmlinkage void ret_from_fork(void); 87 + asmlinkage void ret_from_kernel_thread(void); 87 88 88 89 void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) 89 90 { ··· 114 113 } 115 114 116 115 int copy_thread(unsigned long clone_flags, unsigned long usp, 117 - unsigned long unused, struct task_struct *p, struct pt_regs *regs) 116 + unsigned long arg, struct task_struct *p, struct pt_regs *regs) 118 117 { 119 118 struct thread_info *ti = task_thread_info(p); 120 119 struct pt_regs *childregs; ··· 137 136 childregs = (struct pt_regs *) childksp - 1; 138 137 /* Put the stack after the struct pt_regs. */ 139 138 childksp = (unsigned long) childregs; 139 + p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); 140 + if (unlikely(p->flags & PF_KTHREAD)) { 141 + unsigned long status = p->thread.cp0_status; 142 + memset(childregs, 0, sizeof(struct pt_regs)); 143 + ti->addr_limit = KERNEL_DS; 144 + p->thread.reg16 = usp; /* fn */ 145 + p->thread.reg17 = arg; 146 + p->thread.reg29 = childksp; 147 + p->thread.reg31 = (unsigned long) ret_from_kernel_thread; 148 + #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 149 + status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | 150 + ((status & (ST0_KUC | ST0_IEC)) << 2); 151 + #else 152 + status |= ST0_EXL; 153 + #endif 154 + childregs->cp0_status = status; 155 + return 0; 156 + } 140 157 *childregs = *regs; 141 158 childregs->regs[7] = 0; /* Clear error flag */ 142 - 143 159 childregs->regs[2] = 0; /* Child gets zero as return value */ 160 + childregs->regs[29] = usp; 161 + ti->addr_limit = USER_DS; 144 162 145 - if (childregs->cp0_status & ST0_CU0) { 146 - childregs->regs[28] = (unsigned long) ti; 147 - childregs->regs[29] = childksp; 148 - ti->addr_limit = KERNEL_DS; 149 - } else { 150 - childregs->regs[29] = usp; 151 - ti->addr_limit = USER_DS; 152 - } 153 163 p->thread.reg29 = (unsigned long) childregs; 154 164 p->thread.reg31 = (unsigned long) ret_from_fork; 155 165 ··· 168 156 * New tasks lose permission to use the fpu. This accelerates context 169 157 * switching for most programs since they don't use the fpu. 170 158 */ 171 - p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1); 172 159 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); 173 160 174 161 #ifdef CONFIG_MIPS_MT_SMTC ··· 230 219 memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu)); 231 220 232 221 return 1; 233 - } 234 - 235 - /* 236 - * Create a kernel thread 237 - */ 238 - static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) 239 - { 240 - do_exit(fn(arg)); 241 - } 242 - 243 - long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 244 - { 245 - struct pt_regs regs; 246 - 247 - memset(&regs, 0, sizeof(regs)); 248 - 249 - regs.regs[4] = (unsigned long) arg; 250 - regs.regs[5] = (unsigned long) fn; 251 - regs.cp0_epc = (unsigned long) kernel_thread_helper; 252 - regs.cp0_status = read_c0_status(); 253 - #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 254 - regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) | 255 - ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2); 256 - #else 257 - regs.cp0_status |= ST0_EXL; 258 - #endif 259 - 260 - /* Ok, create the new process.. */ 261 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 262 222 } 263 223 264 224 /*
+1 -1
arch/mips/kernel/scall64-n32.S
··· 167 167 PTR sys_getsockopt 168 168 PTR sys_clone /* 6055 */ 169 169 PTR sys_fork 170 - PTR sys32_execve 170 + PTR compat_sys_execve 171 171 PTR sys_exit 172 172 PTR compat_sys_wait4 173 173 PTR sys_kill /* 6060 */
+1 -1
arch/mips/kernel/scall64-o32.S
··· 203 203 PTR sys_creat 204 204 PTR sys_link 205 205 PTR sys_unlink /* 4010 */ 206 - PTR sys32_execve 206 + PTR compat_sys_execve 207 207 PTR sys_chdir 208 208 PTR compat_sys_time 209 209 PTR sys_mknod
-53
arch/mips/kernel/syscall.c
··· 127 127 parent_tidptr, child_tidptr); 128 128 } 129 129 130 - /* 131 - * sys_execve() executes a new program. 132 - */ 133 - asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) 134 - { 135 - int error; 136 - struct filename *filename; 137 - 138 - filename = getname((const char __user *) (long)regs.regs[4]); 139 - error = PTR_ERR(filename); 140 - if (IS_ERR(filename)) 141 - goto out; 142 - error = do_execve(filename->name, 143 - (const char __user *const __user *) (long)regs.regs[5], 144 - (const char __user *const __user *) (long)regs.regs[6], 145 - &regs); 146 - putname(filename); 147 - 148 - out: 149 - return error; 150 - } 151 - 152 130 SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) 153 131 { 154 132 struct thread_info *ti = task_thread_info(current); ··· 290 312 asmlinkage void bad_stack(void) 291 313 { 292 314 do_exit(SIGSEGV); 293 - } 294 - 295 - /* 296 - * Do a system call from kernel instead of calling sys_execve so we 297 - * end up with proper pt_regs. 298 - */ 299 - int kernel_execve(const char *filename, 300 - const char *const argv[], 301 - const char *const envp[]) 302 - { 303 - register unsigned long __a0 asm("$4") = (unsigned long) filename; 304 - register unsigned long __a1 asm("$5") = (unsigned long) argv; 305 - register unsigned long __a2 asm("$6") = (unsigned long) envp; 306 - register unsigned long __a3 asm("$7"); 307 - unsigned long __v0; 308 - 309 - __asm__ volatile (" \n" 310 - " .set noreorder \n" 311 - " li $2, %5 # __NR_execve \n" 312 - " syscall \n" 313 - " move %0, $2 \n" 314 - " .set reorder \n" 315 - : "=&r" (__v0), "=r" (__a3) 316 - : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve) 317 - : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", 318 - "memory"); 319 - 320 - if (__a3 == 0) 321 - return __v0; 322 - 323 - return -__v0; 324 315 }
+1
arch/mn10300/Kconfig
··· 9 9 select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER 10 10 select GENERIC_CLOCKEVENTS 11 11 select GENERIC_KERNEL_THREAD 12 + select GENERIC_KERNEL_EXECVE 12 13 select MODULES_USE_ELF_RELA 13 14 14 15 config AM33_2
-1
arch/mn10300/include/asm/unistd.h
··· 44 44 #define __ARCH_WANT_SYS_RT_SIGACTION 45 45 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 46 46 #define __ARCH_WANT_SYS_EXECVE 47 - #define __ARCH_WANT_KERNEL_EXECVE 48 47 49 48 /* 50 49 * "Conditional" syscalls
+1 -6
arch/mn10300/kernel/entry.S
··· 60 60 mov (REG_D0,fp),d0 61 61 mov (REG_A0,fp),a0 62 62 calls (a0) 63 - jmp sys_exit 64 - 65 - ENTRY(ret_from_kernel_execve) 66 - add -12,d0 /* pt_regs -> frame */ 67 - mov d0,sp 68 - GET_THREAD_INFO a2 69 63 clr d0 64 + mov d0,(REG_D0,fp) 70 65 jmp syscall_exit 71 66 72 67 ###############################################################################
+2
arch/openrisc/Kconfig
··· 22 22 select GENERIC_STRNCPY_FROM_USER 23 23 select GENERIC_STRNLEN_USER 24 24 select MODULES_USE_ELF_RELA 25 + select GENERIC_KERNEL_THREAD 26 + select GENERIC_KERNEL_EXECVE 25 27 26 28 config MMU 27 29 def_bool y
+2
arch/openrisc/include/uapi/asm/unistd.h
··· 20 20 21 21 #define sys_mmap2 sys_mmap_pgoff 22 22 23 + #define __ARCH_WANT_SYS_EXECVE 24 + 23 25 #include <asm-generic/unistd.h> 24 26 25 27 #define __NR_or1k_atomic __NR_arch_specific_syscall
+17 -26
arch/openrisc/kernel/entry.S
··· 894 894 l.jal schedule_tail 895 895 l.nop 896 896 897 + /* Check if we are a kernel thread */ 898 + l.sfeqi r20,0 899 + l.bf 1f 900 + l.nop 901 + 902 + /* ...we are a kernel thread so invoke the requested callback */ 903 + l.jalr r20 904 + l.or r3,r22,r0 905 + 906 + 1: 897 907 /* _syscall_returns expect r11 to contain return value */ 898 908 l.lwz r11,PT_GPR11(r1) 899 909 ··· 924 914 925 915 l.j _syscall_return 926 916 l.nop 927 - 928 - /* Since syscalls don't save call-clobbered registers, the args to 929 - * kernel_thread_helper will need to be passed through callee-saved 930 - * registers and copied to the parameter registers when the thread 931 - * begins running. 932 - * 933 - * See arch/openrisc/kernel/process.c: 934 - * The args are passed as follows: 935 - * arg1 (r3) : passed in r20 936 - * arg2 (r4) : passed in r22 937 - */ 938 - 939 - ENTRY(_kernel_thread_helper) 940 - l.or r3,r20,r0 941 - l.or r4,r22,r0 942 - l.movhi r31,hi(kernel_thread_helper) 943 - l.ori r31,r31,lo(kernel_thread_helper) 944 - l.jr r31 945 - l.nop 946 - 947 917 948 918 /* ========================================================[ switch ] === */ 949 919 ··· 1034 1044 /* Unwind stack to pre-switch state */ 1035 1045 l.addi r1,r1,(INT_FRAME_SIZE) 1036 1046 1037 - /* Return via the link-register back to where we 'came from', where that can be 1038 - * either schedule() or return_from_fork()... */ 1047 + /* Return via the link-register back to where we 'came from', where 1048 + * that may be either schedule(), ret_from_fork(), or 1049 + * ret_from_kernel_thread(). If we are returning to a new thread, 1050 + * we are expected to have set up the arg to schedule_tail already, 1051 + * hence we do so here unconditionally: 1052 + */ 1053 + l.lwz r3,TI_STACK(r3) /* Load 'prev' as schedule_tail arg */ 1039 1054 l.jr r9 1040 1055 l.nop 1041 1056 ··· 1082 1087 l.ori r29,r29,lo(_sys_fork) 1083 1088 l.j _fork_save_extra_regs_and_call 1084 1089 l.addi r3,r1,0 1085 - 1086 - ENTRY(sys_execve) 1087 - l.j _sys_execve 1088 - l.addi r6,r1,0 1089 1090 1090 1091 ENTRY(sys_sigaltstack) 1091 1092 l.j _sys_sigaltstack
+57 -108
arch/openrisc/kernel/process.c
··· 109 109 */ 110 110 extern asmlinkage void ret_from_fork(void); 111 111 112 + /* 113 + * copy_thread 114 + * @clone_flags: flags 115 + * @usp: user stack pointer or fn for kernel thread 116 + * @arg: arg to fn for kernel thread; always NULL for userspace thread 117 + * @p: the newly created task 118 + * @regs: CPU context to copy for userspace thread; always NULL for kthread 119 + * 120 + * At the top of a newly initialized kernel stack are two stacked pt_reg 121 + * structures. The first (topmost) is the userspace context of the thread. 122 + * The second is the kernelspace context of the thread. 123 + * 124 + * A kernel thread will not be returning to userspace, so the topmost pt_regs 125 + * struct can be uninitialized; it _does_ need to exist, though, because 126 + * a kernel thread can become a userspace thread by doing a kernel_execve, in 127 + * which case the topmost context will be initialized and used for 'returning' 128 + * to userspace. 129 + * 130 + * The second pt_reg struct needs to be initialized to 'return' to 131 + * ret_from_fork. A kernel thread will need to set r20 to the address of 132 + * a function to call into (with arg in r22); userspace threads need to set 133 + * r20 to NULL in which case ret_from_fork will just continue a return to 134 + * userspace. 135 + * 136 + * A kernel thread 'fn' may return; this is effectively what happens when 137 + * kernel_execve is called. In that case, the userspace pt_regs must have 138 + * been initialized (which kernel_execve takes care of, see start_thread 139 + * below); ret_from_fork will then continue its execution causing the 140 + * 'kernel thread' to return to userspace as a userspace thread. 141 + */ 142 + 112 143 int 113 144 copy_thread(unsigned long clone_flags, unsigned long usp, 114 - unsigned long unused, struct task_struct *p, struct pt_regs *regs) 145 + unsigned long arg, struct task_struct *p, struct pt_regs *regs) 115 146 { 116 - struct pt_regs *childregs; 147 + struct pt_regs *userregs; 117 148 struct pt_regs *kregs; 118 149 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 119 - struct thread_info *ti; 120 150 unsigned long top_of_kernel_stack; 121 151 122 152 top_of_kernel_stack = sp; 123 153 124 154 p->set_child_tid = p->clear_child_tid = NULL; 125 155 126 - /* Copy registers */ 127 - /* redzone */ 128 - sp -= STACK_FRAME_OVERHEAD; 156 + /* Locate userspace context on stack... */ 157 + sp -= STACK_FRAME_OVERHEAD; /* redzone */ 129 158 sp -= sizeof(struct pt_regs); 130 - childregs = (struct pt_regs *)sp; 159 + userregs = (struct pt_regs *) sp; 131 160 132 - /* Copy parent registers */ 133 - *childregs = *regs; 134 - 135 - if ((childregs->sr & SPR_SR_SM) == 1) { 136 - /* for kernel thread, set `current_thread_info' 137 - * and stackptr in new task 138 - */ 139 - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 140 - childregs->gpr[10] = (unsigned long)task_thread_info(p); 141 - } else { 142 - childregs->sp = usp; 143 - } 144 - 145 - childregs->gpr[11] = 0; /* Result from fork() */ 146 - 147 - /* 148 - * The way this works is that at some point in the future 149 - * some task will call _switch to switch to the new task. 150 - * That will pop off the stack frame created below and start 151 - * the new task running at ret_from_fork. The new task will 152 - * do some house keeping and then return from the fork or clone 153 - * system call, using the stack frame created above. 154 - */ 155 - /* redzone */ 156 - sp -= STACK_FRAME_OVERHEAD; 161 + /* ...and kernel context */ 162 + sp -= STACK_FRAME_OVERHEAD; /* redzone */ 157 163 sp -= sizeof(struct pt_regs); 158 164 kregs = (struct pt_regs *)sp; 159 165 160 - ti = task_thread_info(p); 161 - ti->ksp = sp; 166 + if (unlikely(p->flags & PF_KTHREAD)) { 167 + memset(kregs, 0, sizeof(struct pt_regs)); 168 + kregs->gpr[20] = usp; /* fn, kernel thread */ 169 + kregs->gpr[22] = arg; 170 + } else { 171 + *userregs = *regs; 162 172 163 - /* kregs->sp must store the location of the 'pre-switch' kernel stack 164 - * pointer... for a newly forked process, this is simply the top of 165 - * the kernel stack. 173 + userregs->sp = usp; 174 + userregs->gpr[11] = 0; /* Result from fork() */ 175 + 176 + kregs->gpr[20] = 0; /* Userspace thread */ 177 + } 178 + 179 + /* 180 + * _switch wants the kernel stack page in pt_regs->sp so that it 181 + * can restore it to thread_info->ksp... see _switch for details. 166 182 */ 167 183 kregs->sp = top_of_kernel_stack; 168 - kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */ 169 - kregs->gpr[10] = (unsigned long)task_thread_info(p); 170 184 kregs->gpr[9] = (unsigned long)ret_from_fork; 185 + 186 + task_thread_info(p)->ksp = (unsigned long)kregs; 171 187 172 188 return 0; 173 189 } ··· 193 177 */ 194 178 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) 195 179 { 196 - unsigned long sr = regs->sr & ~SPR_SR_SM; 180 + unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; 197 181 198 182 set_fs(USER_DS); 199 - memset(regs->gpr, 0, sizeof(regs->gpr)); 183 + memset(regs, 0, sizeof(struct pt_regs)); 200 184 201 185 regs->pc = pc; 202 186 regs->sr = sr; 203 187 regs->sp = sp; 204 - 205 - /* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/ 206 188 } 207 189 208 190 /* Fill in the fpu structure for a core dump. */ ··· 251 237 dest[35] = 0; 252 238 } 253 239 254 - extern void _kernel_thread_helper(void); 255 - 256 - void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg) 257 - { 258 - do_exit(fn(arg)); 259 - } 260 - 261 - /* 262 - * Create a kernel thread. 263 - */ 264 - int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) 265 - { 266 - struct pt_regs regs; 267 - 268 - memset(&regs, 0, sizeof(regs)); 269 - 270 - regs.gpr[20] = (unsigned long)fn; 271 - regs.gpr[22] = (unsigned long)arg; 272 - regs.sr = mfspr(SPR_SR); 273 - regs.pc = (unsigned long)_kernel_thread_helper; 274 - 275 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 276 - 0, &regs, 0, NULL, NULL); 277 - } 278 - 279 - /* 280 - * sys_execve() executes a new program. 281 - */ 282 - asmlinkage long _sys_execve(const char __user *name, 283 - const char __user * const __user *argv, 284 - const char __user * const __user *envp, 285 - struct pt_regs *regs) 286 - { 287 - int error; 288 - struct filename *filename; 289 - 290 - filename = getname(name); 291 - error = PTR_ERR(filename); 292 - 293 - if (IS_ERR(filename)) 294 - goto out; 295 - 296 - error = do_execve(filename->name, argv, envp, regs); 297 - putname(filename); 298 - 299 - out: 300 - return error; 301 - } 302 - 303 240 unsigned long get_wchan(struct task_struct *p) 304 241 { 305 242 /* TODO */ 306 243 307 244 return 0; 308 - } 309 - 310 - int kernel_execve(const char *filename, char *const argv[], char *const envp[]) 311 - { 312 - register long __res asm("r11") = __NR_execve; 313 - register long __a asm("r3") = (long)(filename); 314 - register long __b asm("r4") = (long)(argv); 315 - register long __c asm("r5") = (long)(envp); 316 - __asm__ volatile ("l.sys 1" 317 - : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c) 318 - : "0"(__res), "1"(__a), "2"(__b), "3"(__c) 319 - : "r6", "r7", "r8", "r12", "r13", "r15", 320 - "r17", "r19", "r21", "r23", "r25", "r27", 321 - "r29", "r31"); 322 - __asm__ volatile ("l.nop"); 323 - return __res; 324 245 }
+2
arch/parisc/Kconfig
··· 22 22 select GENERIC_STRNCPY_FROM_USER 23 23 select HAVE_MOD_ARCH_SPECIFIC 24 24 select MODULES_USE_ELF_RELA 25 + select GENERIC_KERNEL_THREAD 26 + select GENERIC_KERNEL_EXECVE 25 27 26 28 help 27 29 The PA-RISC microprocessor is designed by Hewlett-Packard and used
+1
arch/parisc/include/asm/unistd.h
··· 163 163 #define __ARCH_WANT_SYS_RT_SIGACTION 164 164 #define __ARCH_WANT_SYS_RT_SIGSUSPEND 165 165 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 166 + #define __ARCH_WANT_SYS_EXECVE 166 167 167 168 #endif /* __ASSEMBLY__ */ 168 169
+20 -197
arch/parisc/kernel/entry.S
··· 708 708 .import do_cpu_irq_mask,code 709 709 710 710 /* 711 - * r26 = function to be called 712 - * r25 = argument to pass in 713 - * r24 = flags for do_fork() 714 - * 715 - * Kernel threads don't ever return, so they don't need 716 - * a true register context. We just save away the arguments 717 - * for copy_thread/ret_ to properly set up the child. 718 - */ 719 - 720 - #define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */ 721 - #define CLONE_UNTRACED 0x00800000 722 - 723 - .import do_fork 724 - ENTRY(__kernel_thread) 725 - STREG %r2, -RP_OFFSET(%r30) 726 - 727 - copy %r30, %r1 728 - ldo PT_SZ_ALGN(%r30),%r30 729 - #ifdef CONFIG_64BIT 730 - /* Yo, function pointers in wide mode are little structs... -PB */ 731 - ldd 24(%r26), %r2 732 - STREG %r2, PT_GR27(%r1) /* Store childs %dp */ 733 - ldd 16(%r26), %r26 734 - 735 - STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */ 736 - copy %r0, %r22 /* user_tid */ 737 - #endif 738 - STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ 739 - STREG %r25, PT_GR25(%r1) 740 - ldil L%CLONE_UNTRACED, %r26 741 - ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */ 742 - or %r26, %r24, %r26 /* will have kernel mappings. */ 743 - ldi 1, %r25 /* stack_start, signals kernel thread */ 744 - stw %r0, -52(%r30) /* user_tid */ 745 - #ifdef CONFIG_64BIT 746 - ldo -16(%r30),%r29 /* Reference param save area */ 747 - #endif 748 - BL do_fork, %r2 749 - copy %r1, %r24 /* pt_regs */ 750 - 751 - /* Parent Returns here */ 752 - 753 - LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2 754 - ldo -PT_SZ_ALGN(%r30), %r30 755 - bv %r0(%r2) 756 - nop 757 - ENDPROC(__kernel_thread) 758 - 759 - /* 760 711 * Child Returns here 761 712 * 762 - * copy_thread moved args from temp save area set up above 763 - * into task save area. 713 + * copy_thread moved args into task save area. 764 714 */ 765 715 766 716 ENTRY(ret_from_kernel_thread) ··· 719 769 BL schedule_tail, %r2 720 770 nop 721 771 722 - LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1 772 + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 723 773 LDREG TASK_PT_GR25(%r1), %r26 724 774 #ifdef CONFIG_64BIT 725 775 LDREG TASK_PT_GR27(%r1), %r27 726 - LDREG TASK_PT_GR22(%r1), %r22 727 776 #endif 728 777 LDREG TASK_PT_GR26(%r1), %r1 729 778 ble 0(%sr7, %r1) 730 779 copy %r31, %r2 731 - 732 - #ifdef CONFIG_64BIT 733 - ldo -16(%r30),%r29 /* Reference param save area */ 734 - loadgp /* Thread could have been in a module */ 735 - #endif 736 - #ifndef CONFIG_64BIT 737 - b sys_exit 738 - #else 739 - load32 sys_exit, %r1 740 - bv %r0(%r1) 741 - #endif 742 - ldi 0, %r26 743 - ENDPROC(ret_from_kernel_thread) 744 - 745 - .import sys_execve, code 746 - ENTRY(__execve) 747 - copy %r2, %r15 748 - copy %r30, %r16 749 - ldo PT_SZ_ALGN(%r30), %r30 750 - STREG %r26, PT_GR26(%r16) 751 - STREG %r25, PT_GR25(%r16) 752 - STREG %r24, PT_GR24(%r16) 753 - #ifdef CONFIG_64BIT 754 - ldo -16(%r30),%r29 /* Reference param save area */ 755 - #endif 756 - BL sys_execve, %r2 757 - copy %r16, %r26 758 - 759 - cmpib,=,n 0,%r28,intr_return /* forward */ 760 - 761 - /* yes, this will trap and die. */ 762 - copy %r15, %r2 763 - copy %r16, %r30 764 - bv %r0(%r2) 780 + b finish_child_return 765 781 nop 766 - ENDPROC(__execve) 782 + ENDPROC(ret_from_kernel_thread) 767 783 768 784 769 785 /* ··· 1692 1776 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 1693 1777 ldo TASK_REGS(%r1),%r1 1694 1778 reg_save %r1 1695 - mfctl %cr27, %r3 1696 - STREG %r3, PT_CR27(%r1) 1697 - 1698 - STREG %r2,-RP_OFFSET(%r30) 1699 - ldo FRAME_SIZE(%r30),%r30 1700 - #ifdef CONFIG_64BIT 1701 - ldo -16(%r30),%r29 /* Reference param save area */ 1702 - #endif 1703 - 1704 - /* These are call-clobbered registers and therefore 1705 - also syscall-clobbered (we hope). */ 1706 - STREG %r2,PT_GR19(%r1) /* save for child */ 1707 - STREG %r30,PT_GR21(%r1) 1779 + mfctl %cr27, %r28 1780 + STREG %r28, PT_CR27(%r1) 1708 1781 1709 1782 LDREG PT_GR30(%r1),%r25 1710 1783 copy %r1,%r24 1711 - BL sys_clone,%r2 1784 + b sys_clone 1712 1785 ldi SIGCHLD,%r26 1713 - 1714 - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1715 - wrapper_exit: 1716 - ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ 1717 - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1718 - ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1719 - 1720 - LDREG PT_CR27(%r1), %r3 1721 - mtctl %r3, %cr27 1722 - reg_restore %r1 1723 - 1724 - /* strace expects syscall # to be preserved in r20 */ 1725 - ldi __NR_fork,%r20 1726 - bv %r0(%r2) 1727 - STREG %r20,PT_GR20(%r1) 1728 1786 ENDPROC(sys_fork_wrapper) 1729 1787 1730 1788 /* Set the return value for the child */ 1731 1789 ENTRY(child_return) 1732 1790 BL schedule_tail, %r2 1733 1791 nop 1792 + finish_child_return: 1793 + LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 1794 + ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1734 1795 1735 - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r1 1736 - LDREG TASK_PT_GR19(%r1),%r2 1737 - b wrapper_exit 1796 + LDREG PT_CR27(%r1), %r3 1797 + mtctl %r3, %cr27 1798 + reg_restore %r1 1799 + b syscall_exit 1738 1800 copy %r0,%r28 1739 1801 ENDPROC(child_return) 1740 1802 ··· 1721 1827 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1722 1828 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1723 1829 reg_save %r1 1724 - mfctl %cr27, %r3 1725 - STREG %r3, PT_CR27(%r1) 1726 - 1727 - STREG %r2,-RP_OFFSET(%r30) 1728 - ldo FRAME_SIZE(%r30),%r30 1729 - #ifdef CONFIG_64BIT 1730 - ldo -16(%r30),%r29 /* Reference param save area */ 1731 - #endif 1732 - 1733 - /* WARNING - Clobbers r19 and r21, userspace must save these! */ 1734 - STREG %r2,PT_GR19(%r1) /* save for child */ 1735 - STREG %r30,PT_GR21(%r1) 1736 - BL sys_clone,%r2 1830 + mfctl %cr27, %r28 1831 + STREG %r28, PT_CR27(%r1) 1832 + b sys_clone 1737 1833 copy %r1,%r24 1738 - 1739 - b wrapper_exit 1740 - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1741 1834 ENDPROC(sys_clone_wrapper) 1742 1835 1743 1836 ··· 1732 1851 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1733 1852 ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1734 1853 reg_save %r1 1735 - mfctl %cr27, %r3 1736 - STREG %r3, PT_CR27(%r1) 1854 + mfctl %cr27, %r28 1855 + STREG %r28, PT_CR27(%r1) 1737 1856 1738 - STREG %r2,-RP_OFFSET(%r30) 1739 - ldo FRAME_SIZE(%r30),%r30 1740 - #ifdef CONFIG_64BIT 1741 - ldo -16(%r30),%r29 /* Reference param save area */ 1742 - #endif 1743 - 1744 - STREG %r2,PT_GR19(%r1) /* save for child */ 1745 - STREG %r30,PT_GR21(%r1) 1746 - 1747 - BL sys_vfork,%r2 1857 + b sys_vfork 1748 1858 copy %r1,%r26 1749 - 1750 - b wrapper_exit 1751 - LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 1752 1859 ENDPROC(sys_vfork_wrapper) 1753 1860 1754 1861 1755 - .macro execve_wrapper execve 1756 - LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 1757 - ldo TASK_REGS(%r1),%r1 /* get pt regs */ 1758 - 1759 - /* 1760 - * Do we need to save/restore r3-r18 here? 1761 - * I don't think so. why would new thread need old 1762 - * threads registers? 1763 - */ 1764 - 1765 - /* %arg0 - %arg3 are already saved for us. */ 1766 - 1767 - STREG %r2,-RP_OFFSET(%r30) 1768 - ldo FRAME_SIZE(%r30),%r30 1769 - #ifdef CONFIG_64BIT 1770 - ldo -16(%r30),%r29 /* Reference param save area */ 1771 - #endif 1772 - BL \execve,%r2 1773 - copy %r1,%arg0 1774 - 1775 - ldo -FRAME_SIZE(%r30),%r30 1776 - LDREG -RP_OFFSET(%r30),%r2 1777 - 1778 - /* If exec succeeded we need to load the args */ 1779 - 1780 - ldo -1024(%r0),%r1 1781 - cmpb,>>= %r28,%r1,error_\execve 1782 - copy %r2,%r19 1783 - 1784 - error_\execve: 1785 - bv %r0(%r19) 1786 - nop 1787 - .endm 1788 - 1789 - .import sys_execve 1790 - ENTRY(sys_execve_wrapper) 1791 - execve_wrapper sys_execve 1792 - ENDPROC(sys_execve_wrapper) 1793 - 1794 - #ifdef CONFIG_64BIT 1795 - .import sys32_execve 1796 - ENTRY(sys32_execve_wrapper) 1797 - execve_wrapper sys32_execve 1798 - ENDPROC(sys32_execve_wrapper) 1799 - #endif 1800 - 1801 1862 ENTRY(sys_rt_sigreturn_wrapper) 1802 1863 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 1803 1864 ldo TASK_REGS(%r26),%r26 /* get pt regs */
+15 -81
arch/parisc/kernel/process.c
··· 52 52 53 53 #include <asm/io.h> 54 54 #include <asm/asm-offsets.h> 55 + #include <asm/assembly.h> 55 56 #include <asm/pdc.h> 56 57 #include <asm/pdc_chassis.h> 57 58 #include <asm/pgalloc.h> ··· 166 165 EXPORT_SYMBOL(pm_power_off); 167 166 168 167 /* 169 - * Create a kernel thread 170 - */ 171 - 172 - extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 173 - pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 174 - { 175 - 176 - /* 177 - * FIXME: Once we are sure we don't need any debug here, 178 - * kernel_thread can become a #define. 179 - */ 180 - 181 - return __kernel_thread(fn, arg, flags); 182 - } 183 - EXPORT_SYMBOL(kernel_thread); 184 - 185 - /* 186 168 * Free current thread data structures etc.. 187 169 */ 188 170 void exit_thread(void) ··· 240 256 241 257 int 242 258 copy_thread(unsigned long clone_flags, unsigned long usp, 243 - unsigned long unused, /* in ia64 this is "user_stack_size" */ 244 - struct task_struct * p, struct pt_regs * pregs) 259 + unsigned long arg, 260 + struct task_struct *p, struct pt_regs *pregs) 245 261 { 246 262 struct pt_regs * cregs = &(p->thread.regs); 247 263 void *stack = task_stack_page(p); ··· 254 270 #ifdef CONFIG_HPUX 255 271 extern void * const hpux_child_return; 256 272 #endif 273 + if (unlikely(p->flags & PF_KTHREAD)) { 274 + memset(cregs, 0, sizeof(struct pt_regs)); 275 + if (!usp) /* idle thread */ 276 + return 0; 257 277 258 - *cregs = *pregs; 259 - 260 - /* Set the return value for the child. Note that this is not 261 - actually restored by the syscall exit path, but we put it 262 - here for consistency in case of signals. */ 263 - cregs->gr[28] = 0; /* child */ 264 - 265 - /* 266 - * We need to differentiate between a user fork and a 267 - * kernel fork. We can't use user_mode, because the 268 - * the syscall path doesn't save iaoq. Right now 269 - * We rely on the fact that kernel_thread passes 270 - * in zero for usp. 271 - */ 272 - if (usp == 1) { 273 278 /* kernel thread */ 274 - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; 275 279 /* Must exit via ret_from_kernel_thread in order 276 280 * to call schedule_tail() 277 281 */ 282 + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; 278 283 cregs->kpc = (unsigned long) &ret_from_kernel_thread; 279 284 /* 280 285 * Copy function and argument to be called from 281 286 * ret_from_kernel_thread. 282 287 */ 283 288 #ifdef CONFIG_64BIT 284 - cregs->gr[27] = pregs->gr[27]; 289 + cregs->gr[27] = ((unsigned long *)usp)[3]; 290 + cregs->gr[26] = ((unsigned long *)usp)[2]; 291 + #else 292 + cregs->gr[26] = usp; 285 293 #endif 286 - cregs->gr[26] = pregs->gr[26]; 287 - cregs->gr[25] = pregs->gr[25]; 294 + cregs->gr[25] = arg; 288 295 } else { 289 296 /* user thread */ 290 - /* 291 - * Note that the fork wrappers are responsible 292 - * for setting gr[21]. 293 - */ 294 - 295 - /* Use same stack depth as parent */ 296 - cregs->ksp = (unsigned long)stack 297 - + (pregs->gr[21] & (THREAD_SIZE - 1)); 298 297 cregs->gr[30] = usp; 298 + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; 299 299 if (personality(p->personality) == PER_HPUX) { 300 300 #ifdef CONFIG_HPUX 301 301 cregs->kpc = (unsigned long) &hpux_child_return; ··· 291 323 } 292 324 /* Setup thread TLS area from the 4th parameter in clone */ 293 325 if (clone_flags & CLONE_SETTLS) 294 - cregs->cr27 = pregs->gr[23]; 295 - 326 + cregs->cr27 = pregs->gr[23]; 296 327 } 297 328 298 329 return 0; ··· 300 333 unsigned long thread_saved_pc(struct task_struct *t) 301 334 { 302 335 return t->thread.regs.kpc; 303 - } 304 - 305 - /* 306 - * sys_execve() executes a new program. 307 - */ 308 - 309 - asmlinkage int sys_execve(struct pt_regs *regs) 310 - { 311 - int error; 312 - struct filename *filename; 313 - 314 - filename = getname((const char __user *) regs->gr[26]); 315 - error = PTR_ERR(filename); 316 - if (IS_ERR(filename)) 317 - goto out; 318 - error = do_execve(filename->name, 319 - (const char __user *const __user *) regs->gr[25], 320 - (const char __user *const __user *) regs->gr[24], 321 - regs); 322 - putname(filename); 323 - out: 324 - 325 - return error; 326 - } 327 - 328 - extern int __execve(const char *filename, 329 - const char *const argv[], 330 - const char *const envp[], struct task_struct *task); 331 - int kernel_execve(const char *filename, 332 - const char *const argv[], 333 - const char *const envp[]) 334 - { 335 - return __execve(filename, argv, envp, current); 336 336 } 337 337 338 338 unsigned long
-22
arch/parisc/kernel/sys_parisc32.c
··· 53 53 #define DBG(x) 54 54 #endif 55 55 56 - /* 57 - * sys32_execve() executes a new program. 58 - */ 59 - 60 - asmlinkage int sys32_execve(struct pt_regs *regs) 61 - { 62 - int error; 63 - struct filename *filename; 64 - 65 - DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); 66 - filename = getname((const char __user *) regs->gr[26]); 67 - error = PTR_ERR(filename); 68 - if (IS_ERR(filename)) 69 - goto out; 70 - error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]), 71 - compat_ptr(regs->gr[24]), regs); 72 - putname(filename); 73 - out: 74 - 75 - return error; 76 - } 77 - 78 56 asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, 79 57 int r22, int r21, int r20) 80 58 {
+1 -1
arch/parisc/kernel/syscall_table.S
··· 66 66 ENTRY_SAME(creat) 67 67 ENTRY_SAME(link) 68 68 ENTRY_SAME(unlink) /* 10 */ 69 - ENTRY_DIFF(execve_wrapper) 69 + ENTRY_COMP(execve) 70 70 ENTRY_SAME(chdir) 71 71 /* See comments in kernel/time.c!!! Maybe we don't need this? */ 72 72 ENTRY_COMP(time)
+1
arch/powerpc/Kconfig
··· 144 144 select GENERIC_KERNEL_THREAD 145 145 select HAVE_MOD_ARCH_SPECIFIC 146 146 select MODULES_USE_ELF_RELA 147 + select GENERIC_KERNEL_EXECVE 147 148 148 149 config EARLY_PRINTK 149 150 bool
-1
arch/powerpc/include/asm/unistd.h
··· 56 56 #define __ARCH_WANT_COMPAT_SYS_SENDFILE 57 57 #endif 58 58 #define __ARCH_WANT_SYS_EXECVE 59 - #define __ARCH_WANT_KERNEL_EXECVE 60 59 61 60 /* 62 61 * "Conditional" syscalls
-5
arch/powerpc/kernel/entry_32.S
··· 444 444 PPC440EP_ERR42 445 445 blrl 446 446 li r3,0 447 - b do_exit # no return 448 - 449 - .globl __ret_from_kernel_execve 450 - __ret_from_kernel_execve: 451 - addi r1,r3,-STACK_FRAME_OVERHEAD 452 447 b ret_from_syscall 453 448 454 449 /* Traced system call support */
+1 -7
arch/powerpc/kernel/entry_64.S
··· 373 373 _GLOBAL(ret_from_kernel_thread) 374 374 bl .schedule_tail 375 375 REST_NVGPRS(r1) 376 - REST_GPR(2,r1) 376 + ld r14, 0(r14) 377 377 mtlr r14 378 378 mr r3,r15 379 379 blrl 380 380 li r3,0 381 - b .do_exit # no return 382 - 383 - _GLOBAL(__ret_from_kernel_execve) 384 - addi r1,r3,-STACK_FRAME_OVERHEAD 385 - li r10,1 386 - std r10,SOFTE(r1) 387 381 b syscall_exit 388 382 389 383 .section ".toc","aw"
+10 -33
arch/powerpc/kernel/process.c
··· 745 745 /* Copy registers */ 746 746 sp -= sizeof(struct pt_regs); 747 747 childregs = (struct pt_regs *) sp; 748 - if (!regs) { 749 - /* for kernel thread, set `current' and stackptr in new task */ 748 + if (unlikely(p->flags & PF_KTHREAD)) { 749 + struct thread_info *ti = (void *)task_stack_page(p); 750 750 memset(childregs, 0, sizeof(struct pt_regs)); 751 751 childregs->gpr[1] = sp + sizeof(struct pt_regs); 752 - #ifdef CONFIG_PPC64 753 - childregs->gpr[14] = *(unsigned long *)usp; 754 - childregs->gpr[2] = ((unsigned long *)usp)[1], 755 - clear_tsk_thread_flag(p, TIF_32BIT); 756 - #else 757 752 childregs->gpr[14] = usp; /* function */ 758 - childregs->gpr[2] = (unsigned long) p; 753 + #ifdef CONFIG_PPC64 754 + clear_tsk_thread_flag(p, TIF_32BIT); 755 + childregs->softe = 1; 759 756 #endif 760 757 childregs->gpr[15] = arg; 761 758 p->thread.regs = NULL; /* no user register state */ 759 + ti->flags |= _TIF_RESTOREALL; 762 760 f = ret_from_kernel_thread; 763 761 } else { 764 762 CHECK_FULL_REGS(regs); 765 763 *childregs = *regs; 766 - childregs->gpr[1] = usp; 764 + if (usp) 765 + childregs->gpr[1] = usp; 767 766 p->thread.regs = childregs; 768 767 childregs->gpr[3] = 0; /* Result from fork() */ 769 768 if (clone_flags & CLONE_SETTLS) { ··· 1026 1027 return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); 1027 1028 } 1028 1029 1029 - #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) 1030 - 1031 1030 int sys_clone(unsigned long clone_flags, unsigned long usp, 1032 1031 int __user *parent_tidp, void __user *child_threadptr, 1033 1032 int __user *child_tidp, int p6, 1034 1033 struct pt_regs *regs) 1035 1034 { 1036 - CHECK_FULL_REGS(regs); 1037 - if (usp == 0) 1038 - usp = regs->gpr[1]; /* stack pointer for child */ 1039 - #ifdef CONFIG_PPC64 1040 - if (is_32bit_task()) { 1041 - parent_tidp = TRUNC_PTR(parent_tidp); 1042 - child_tidp = TRUNC_PTR(child_tidp); 1043 - } 1044 - #endif 1045 1035 return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); 1046 1036 } 1047 1037 ··· 1038 1050 unsigned long p4, unsigned long p5, unsigned long p6, 1039 1051 struct pt_regs *regs) 1040 1052 { 1041 - CHECK_FULL_REGS(regs); 1042 - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); 1053 + return do_fork(SIGCHLD, 0, regs, 0, NULL, NULL); 1043 1054 } 1044 1055 1045 1056 int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, 1046 1057 unsigned long p4, unsigned long p5, unsigned long p6, 1047 1058 struct pt_regs *regs) 1048 1059 { 1049 - CHECK_FULL_REGS(regs); 1050 - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], 1060 + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 1051 1061 regs, 0, NULL, NULL); 1052 - } 1053 - 1054 - void __ret_from_kernel_execve(struct pt_regs *normal) 1055 - __noreturn; 1056 - 1057 - void ret_from_kernel_execve(struct pt_regs *normal) 1058 - { 1059 - set_thread_flag(TIF_RESTOREALL); 1060 - __ret_from_kernel_execve(normal); 1061 1062 } 1062 1063 1063 1064 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
+1
arch/s390/Kconfig
··· 138 138 select KTIME_SCALAR if 32BIT 139 139 select HAVE_ARCH_SECCOMP_FILTER 140 140 select GENERIC_KERNEL_THREAD 141 + select GENERIC_KERNEL_EXECVE 141 142 select HAVE_MOD_ARCH_SPECIFIC 142 143 select MODULES_USE_ELF_RELA 143 144
-1
arch/s390/include/asm/unistd.h
··· 54 54 # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 55 55 # endif 56 56 #define __ARCH_WANT_SYS_EXECVE 57 - #define __ARCH_WANT_KERNEL_EXECVE 58 57 59 58 /* 60 59 * "Conditional" syscalls
+8 -30
arch/s390/kernel/entry.S
··· 330 330 la %r11,STACK_FRAME_OVERHEAD(%r15) 331 331 l %r12,__LC_THREAD_INFO 332 332 l %r13,__LC_SVC_NEW_PSW+4 333 + l %r1,BASED(.Lschedule_tail) 334 + basr %r14,%r1 # call schedule_tail 335 + TRACE_IRQS_ON 336 + ssm __LC_SVC_NEW_PSW # reenable interrupts 333 337 tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? 334 - je 1f 335 - l %r1,BASED(.Lschedule_tail) 336 - basr %r14,%r1 # call schedule_tail 337 - TRACE_IRQS_ON 338 - ssm __LC_SVC_NEW_PSW # reenable interrupts 339 - j sysc_tracenogo 340 - 341 - 1: # it's a kernel thread 342 - st %r15,__PT_R15(%r11) # store stack pointer for new kthread 343 - l %r1,BASED(.Lschedule_tail) 344 - basr %r14,%r1 # call schedule_tail 345 - TRACE_IRQS_ON 346 - ssm __LC_SVC_NEW_PSW # reenable interrupts 347 - lm %r9,%r11,__PT_R9(%r11) # load gprs 338 + jne sysc_tracenogo 339 + # it's a kernel thread 340 + lm %r9,%r10,__PT_R9(%r11) # load gprs 348 341 ENTRY(kernel_thread_starter) 349 342 la %r2,0(%r10) 350 343 basr %r14,%r9 351 - la %r2,0 352 - br %r11 # do_exit 353 - 354 - # 355 - # kernel_execve function needs to deal with pt_regs that is not 356 - # at the usual place 357 - # 358 - ENTRY(ret_from_kernel_execve) 359 - ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 360 - lr %r15,%r2 361 - lr %r11,%r2 362 - ahi %r15,-STACK_FRAME_OVERHEAD 363 - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) 364 - l %r12,__LC_THREAD_INFO 365 - ssm __LC_SVC_NEW_PSW # reenable interrupts 366 - j sysc_return 344 + j sysc_tracenogo 367 345 368 346 /* 369 347 * Program check handler routine
+7 -23
arch/s390/kernel/entry64.S
··· 352 352 ENTRY(ret_from_fork) 353 353 la %r11,STACK_FRAME_OVERHEAD(%r15) 354 354 lg %r12,__LC_THREAD_INFO 355 + brasl %r14,schedule_tail 356 + TRACE_IRQS_ON 357 + ssm __LC_SVC_NEW_PSW # reenable interrupts 355 358 tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? 356 - je 1f 357 - brasl %r14,schedule_tail 358 - TRACE_IRQS_ON 359 - ssm __LC_SVC_NEW_PSW # reenable interrupts 360 - j sysc_tracenogo 361 - 1: # it's a kernel thread 362 - stg %r15,__PT_R15(%r11) # store stack pointer for new kthread 363 - brasl %r14,schedule_tail 364 - TRACE_IRQS_ON 365 - ssm __LC_SVC_NEW_PSW # reenable interrupts 366 - lmg %r9,%r11,__PT_R9(%r11) # load gprs 359 + jne sysc_tracenogo 360 + # it's a kernel thread 361 + lmg %r9,%r10,__PT_R9(%r11) # load gprs 367 362 ENTRY(kernel_thread_starter) 368 363 la %r2,0(%r10) 369 364 basr %r14,%r9 370 - la %r2,0 371 - br %r11 # do_exit 372 - 373 - ENTRY(ret_from_kernel_execve) 374 - ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts 375 - lgr %r15,%r2 376 - lgr %r11,%r2 377 - aghi %r15,-STACK_FRAME_OVERHEAD 378 - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) 379 - lg %r12,__LC_THREAD_INFO 380 - ssm __LC_SVC_NEW_PSW # reenable interrupts 381 - j sysc_return 365 + j sysc_tracenogo 382 366 383 367 /* 384 368 * Program check handler routine
+2
arch/score/Kconfig
··· 13 13 select GENERIC_CLOCKEVENTS 14 14 select HAVE_MOD_ARCH_SPECIFIC 15 15 select MODULES_USE_ELF_REL 16 + select GENERIC_KERNEL_THREAD 17 + select GENERIC_KERNEL_EXECVE 16 18 17 19 choice 18 20 prompt "System type"
-1
arch/score/include/asm/processor.h
··· 13 13 */ 14 14 extern void (*cpu_wait)(void); 15 15 16 - extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 17 16 extern unsigned long thread_saved_pc(struct task_struct *tsk); 18 17 extern void start_thread(struct pt_regs *regs, 19 18 unsigned long pc, unsigned long sp);
-1
arch/score/include/asm/syscalls.h
··· 2 2 #define _ASM_SCORE_SYSCALLS_H 3 3 4 4 asmlinkage long score_clone(struct pt_regs *regs); 5 - asmlinkage long score_execve(struct pt_regs *regs); 6 5 asmlinkage long score_sigaltstack(struct pt_regs *regs); 7 6 asmlinkage long score_rt_sigreturn(struct pt_regs *regs); 8 7
+1
arch/score/include/asm/unistd.h
··· 4 4 #define __ARCH_WANT_SYSCALL_NO_FLAGS 5 5 #define __ARCH_WANT_SYSCALL_OFF_T 6 6 #define __ARCH_WANT_SYSCALL_DEPRECATED 7 + #define __ARCH_WANT_SYS_EXECVE 7 8 8 9 #include <asm-generic/unistd.h>
+7 -5
arch/score/kernel/entry.S
··· 278 278 nop 279 279 #endif 280 280 281 + ENTRY(ret_from_kernel_thread) 282 + bl schedule_tail # r4=struct task_struct *prev 283 + nop 284 + mv r4, r13 285 + brl r12 286 + j syscall_exit 287 + 281 288 ENTRY(ret_from_fork) 282 289 bl schedule_tail # r4=struct task_struct *prev 283 290 ··· 486 479 ldi r9, 1 # set error flag 487 480 sw r9, [r0, PT_R7] 488 481 j syscall_return 489 - 490 - ENTRY(sys_execve) 491 - mv r4, r0 492 - la r8, score_execve 493 - br r8 494 482 495 483 ENTRY(sys_clone) 496 484 mv r4, r0
+14 -41
arch/score/kernel/process.c
··· 60 60 } 61 61 62 62 void ret_from_fork(void); 63 + void ret_from_kernel_thread(void); 63 64 64 65 void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) 65 66 { ··· 87 86 * set up the kernel stack and exception frames for a new process 88 87 */ 89 88 int copy_thread(unsigned long clone_flags, unsigned long usp, 90 - unsigned long unused, 89 + unsigned long arg, 91 90 struct task_struct *p, struct pt_regs *regs) 92 91 { 93 92 struct thread_info *ti = task_thread_info(p); 94 93 struct pt_regs *childregs = task_pt_regs(p); 95 94 96 - p->set_child_tid = NULL; 97 - p->clear_child_tid = NULL; 98 - 99 - *childregs = *regs; 100 - childregs->regs[7] = 0; /* Clear error flag */ 101 - childregs->regs[4] = 0; /* Child gets zero as return value */ 102 - regs->regs[4] = p->pid; 103 - 104 - if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */ 105 - childregs->regs[0] = usp; /* user fork */ 95 + p->thread.reg0 = (unsigned long) childregs; 96 + if (unlikely(!regs)) { 97 + memset(childregs, 0, sizeof(struct pt_regs)); 98 + p->thread->reg12 = usp; 99 + p->thread->reg13 = arg; 100 + p->thread.reg3 = (unsigned long) ret_from_kernel_thread; 106 101 } else { 107 - childregs->regs[28] = (unsigned long) ti; /* kernel fork */ 108 - childregs->regs[0] = (unsigned long) childregs; 102 + *childregs = *regs; 103 + childregs->regs[7] = 0; /* Clear error flag */ 104 + childregs->regs[4] = 0; /* Child gets zero as return value */ 105 + childregs->regs[0] = usp; /* user fork */ 106 + regs->regs[4] = p->pid; /* WTF? */ 107 + p->thread.reg3 = (unsigned long) ret_from_fork; 109 108 } 110 109 111 - p->thread.reg0 = (unsigned long) childregs; 112 - p->thread.reg3 = (unsigned long) ret_from_fork; 113 110 p->thread.cp0_psr = 0; 114 111 115 112 return 0; ··· 117 118 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) 118 119 { 119 120 return 1; 120 - } 121 - 122 - static void __noreturn 123 - kernel_thread_helper(void *unused0, int (*fn)(void *), 124 - void *arg, void *unused1) 125 - { 126 - do_exit(fn(arg)); 127 - } 128 - 129 - /* 130 - * Create a kernel thread. 131 - */ 132 - long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) 133 - { 134 - struct pt_regs regs; 135 - 136 - memset(&regs, 0, sizeof(regs)); 137 - 138 - regs.regs[6] = (unsigned long) arg; 139 - regs.regs[5] = (unsigned long) fn; 140 - regs.cp0_epc = (unsigned long) kernel_thread_helper; 141 - regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \ 142 - ((regs.cp0_psr & 0x3) << 2); 143 - 144 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \ 145 - 0, &regs, 0, NULL, NULL); 146 121 } 147 122 148 123 unsigned long thread_saved_pc(struct task_struct *tsk)
-54
arch/score/kernel/sys_score.c
··· 83 83 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 84 84 regs->regs[0], regs, 0, NULL, NULL); 85 85 } 86 - 87 - /* 88 - * sys_execve() executes a new program. 89 - * This is called indirectly via a small wrapper 90 - */ 91 - asmlinkage long 92 - score_execve(struct pt_regs *regs) 93 - { 94 - int error; 95 - struct filename *filename; 96 - 97 - filename = getname((char __user*)regs->regs[4]); 98 - error = PTR_ERR(filename); 99 - if (IS_ERR(filename)) 100 - return error; 101 - 102 - error = do_execve(filename->name, 103 - (const char __user *const __user *)regs->regs[5], 104 - (const char __user *const __user *)regs->regs[6], 105 - regs); 106 - 107 - putname(filename); 108 - return error; 109 - } 110 - 111 - /* 112 - * Do a system call from kernel instead of calling sys_execve so we 113 - * end up with proper pt_regs. 114 - */ 115 - asmlinkage 116 - int kernel_execve(const char *filename, 117 - const char *const argv[], 118 - const char *const envp[]) 119 - { 120 - register unsigned long __r4 asm("r4") = (unsigned long) filename; 121 - register unsigned long __r5 asm("r5") = (unsigned long) argv; 122 - register unsigned long __r6 asm("r6") = (unsigned long) envp; 123 - register unsigned long __r7 asm("r7"); 124 - 125 - __asm__ __volatile__ (" \n" 126 - "ldi r27, %5 \n" 127 - "syscall \n" 128 - "mv %0, r4 \n" 129 - "mv %1, r7 \n" 130 - : "=&r" (__r4), "=r" (__r7) 131 - : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve) 132 - : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25", 133 - "r26", "r27", "memory"); 134 - 135 - if (__r7 == 0) 136 - return __r4; 137 - 138 - return -__r4; 139 - }
+2
arch/sh/Kconfig
··· 40 40 select GENERIC_STRNLEN_USER 41 41 select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER 42 42 select MODULES_USE_ELF_RELA 43 + select GENERIC_KERNEL_THREAD 44 + select GENERIC_KERNEL_EXECVE 43 45 help 44 46 The SuperH is a RISC processor targeted for use in embedded systems 45 47 and consumer electronics; it was also used in the Sega Dreamcast
-5
arch/sh/include/asm/processor_32.h
··· 126 126 /* Free all resources held by a thread. */ 127 127 extern void release_thread(struct task_struct *); 128 128 129 - /* 130 - * create a kernel thread without removing it from tasklists 131 - */ 132 - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 133 - 134 129 /* Copy and release all segment info associated with a VM */ 135 130 #define copy_segments(p, mm) do { } while(0) 136 131 #define release_segments(mm) do { } while(0)
-5
arch/sh/include/asm/processor_64.h
··· 159 159 160 160 /* Free all resources held by a thread. */ 161 161 extern void release_thread(struct task_struct *); 162 - /* 163 - * create a kernel thread without removing it from tasklists 164 - */ 165 - extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 166 - 167 162 168 163 /* Copy and release all segment info associated with a VM */ 169 164 #define copy_segments(p, mm) do { } while (0)
-4
arch/sh/include/asm/syscalls_32.h
··· 19 19 asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, 20 20 unsigned long r6, unsigned long r7, 21 21 struct pt_regs __regs); 22 - asmlinkage int sys_execve(const char __user *ufilename, 23 - const char __user *const __user *uargv, 24 - const char __user *const __user *uenvp, 25 - unsigned long r7, struct pt_regs __regs); 26 22 asmlinkage int sys_sigsuspend(old_sigset_t mask); 27 23 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, 28 24 struct old_sigaction __user *oact);
-4
arch/sh/include/asm/syscalls_64.h
··· 21 21 unsigned long r4, unsigned long r5, 22 22 unsigned long r6, unsigned long r7, 23 23 struct pt_regs *pregs); 24 - asmlinkage int sys_execve(const char *ufilename, char **uargv, 25 - char **uenvp, unsigned long r5, 26 - unsigned long r6, unsigned long r7, 27 - struct pt_regs *pregs); 28 24 29 25 /* Misc syscall related bits */ 30 26 asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
+1
arch/sh/include/asm/unistd.h
··· 28 28 # define __ARCH_WANT_SYS_SIGPENDING 29 29 # define __ARCH_WANT_SYS_SIGPROCMASK 30 30 # define __ARCH_WANT_SYS_RT_SIGACTION 31 + # define __ARCH_WANT_SYS_EXECVE 31 32 32 33 /* 33 34 * "Conditional" syscalls
+2 -1
arch/sh/kernel/Makefile
··· 16 16 machvec.o nmi_debug.o process.o \ 17 17 process_$(BITS).o ptrace.o ptrace_$(BITS).o \ 18 18 reboot.o return_address.o \ 19 - setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ 19 + setup.o signal_$(BITS).o sys_sh.o \ 20 20 syscalls_$(BITS).o time.o topology.o traps.o \ 21 21 traps_$(BITS).o unwinder.o 22 22 ··· 25 25 obj-$(CONFIG_HAS_IOPORT) += ioport.o 26 26 endif 27 27 28 + obj-$(CONFIG_SUPERH32) += sys_sh32.o 28 29 obj-y += cpu/ 29 30 obj-$(CONFIG_VSYSCALL) += vsyscall/ 30 31 obj-$(CONFIG_SMP) += smp.o
+19
arch/sh/kernel/cpu/sh5/entry.S
··· 1228 1228 pta ret_from_syscall, tr0 1229 1229 blink tr0, ZERO 1230 1230 1231 + .global ret_from_kernel_thread 1232 + ret_from_kernel_thread: 1233 + 1234 + movi schedule_tail,r5 1235 + ori r5, 1, r5 1236 + ptabs r5, tr0 1237 + blink tr0, LINK 1238 + 1239 + ld.q SP, FRAME_R(2), r2 1240 + ld.q SP, FRAME_R(3), r3 1241 + ptabs r3, tr0 1242 + blink tr0, LINK 1243 + 1244 + ld.q SP, FRAME_S(FSPC), r2 1245 + addi r2, 4, r2 /* Move PC, being pre-execution event */ 1246 + st.q SP, FRAME_S(FSPC), r2 1247 + pta ret_from_syscall, tr0 1248 + blink tr0, ZERO 1249 + 1231 1250 syscall_allowed: 1232 1251 /* Use LINK to deflect the exit point, default is syscall_ret */ 1233 1252 pta syscall_ret, tr0
+13
arch/sh/kernel/entry-common.S
··· 297 297 mov r0, r4 298 298 bra syscall_exit 299 299 nop 300 + 301 + .align 2 302 + .globl ret_from_kernel_thread 303 + ret_from_kernel_thread: 304 + mov.l 1f, r8 305 + jsr @r8 306 + mov r0, r4 307 + mov.l @(OFF_R5,r15), r5 ! fn 308 + jsr @r5 309 + mov.l @(OFF_R4,r15), r4 ! arg 310 + bra syscall_exit 311 + nop 312 + 300 313 .align 2 301 314 1: .long schedule_tail 302 315
+19 -68
arch/sh/kernel/process_32.c
··· 68 68 show_code(regs); 69 69 } 70 70 71 - /* 72 - * Create a kernel thread 73 - */ 74 - __noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) 75 - { 76 - do_exit(fn(arg)); 77 - } 78 - 79 - /* Don't use this in BL=1(cli). Or else, CPU resets! */ 80 - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 81 - { 82 - struct pt_regs regs; 83 - int pid; 84 - 85 - memset(&regs, 0, sizeof(regs)); 86 - regs.regs[4] = (unsigned long)arg; 87 - regs.regs[5] = (unsigned long)fn; 88 - 89 - regs.pc = (unsigned long)kernel_thread_helper; 90 - regs.sr = SR_MD; 91 - #if defined(CONFIG_SH_FPU) 92 - regs.sr |= SR_FD; 93 - #endif 94 - 95 - /* Ok, create the new process.. */ 96 - pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, 97 - &regs, 0, NULL, NULL); 98 - 99 - return pid; 100 - } 101 - EXPORT_SYMBOL(kernel_thread); 102 - 103 71 void start_thread(struct pt_regs *regs, unsigned long new_pc, 104 72 unsigned long new_sp) 105 73 { ··· 125 157 EXPORT_SYMBOL(dump_fpu); 126 158 127 159 asmlinkage void ret_from_fork(void); 160 + asmlinkage void ret_from_kernel_thread(void); 128 161 129 162 int copy_thread(unsigned long clone_flags, unsigned long usp, 130 - unsigned long unused, 163 + unsigned long arg, 131 164 struct task_struct *p, struct pt_regs *regs) 132 165 { 133 166 struct thread_info *ti = task_thread_info(p); ··· 146 177 } 147 178 #endif 148 179 149 - childregs = task_pt_regs(p); 150 - *childregs = *regs; 180 + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 151 181 152 - if (user_mode(regs)) { 153 - childregs->regs[15] = usp; 154 - ti->addr_limit = USER_DS; 155 - } else { 156 - childregs->regs[15] = (unsigned long)childregs; 182 + childregs = task_pt_regs(p); 183 + p->thread.sp = (unsigned long) childregs; 184 + if (unlikely(p->flags & PF_KTHREAD)) { 185 + memset(childregs, 0, sizeof(struct pt_regs)); 186 + p->thread.pc = (unsigned long) ret_from_kernel_thread; 187 + childregs->regs[4] = arg; 188 + childregs->regs[5] = usp; 189 + childregs->sr = SR_MD; 190 + #if defined(CONFIG_SH_FPU) 191 + childregs->sr |= SR_FD; 192 + #endif 157 193 ti->addr_limit = KERNEL_DS; 158 194 ti->status &= ~TS_USEDFPU; 159 195 p->fpu_counter = 0; 196 + return 0; 160 197 } 198 + *childregs = *regs; 199 + 200 + childregs->regs[15] = usp; 201 + ti->addr_limit = USER_DS; 161 202 162 203 if (clone_flags & CLONE_SETTLS) 163 204 childregs->gbr = childregs->regs[0]; 164 205 165 206 childregs->regs[0] = 0; /* Set return value for child */ 166 - 167 - p->thread.sp = (unsigned long) childregs; 168 207 p->thread.pc = (unsigned long) ret_from_fork; 169 - 170 - memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 171 - 172 208 return 0; 173 209 } 174 210 ··· 260 286 struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 261 287 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, 262 288 0, NULL, NULL); 263 - } 264 - 265 - /* 266 - * sys_execve() executes a new program. 267 - */ 268 - asmlinkage int sys_execve(const char __user *ufilename, 269 - const char __user *const __user *uargv, 270 - const char __user *const __user *uenvp, 271 - unsigned long r7, struct pt_regs __regs) 272 - { 273 - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 274 - int error; 275 - struct filename *filename; 276 - 277 - filename = getname(ufilename); 278 - error = PTR_ERR(filename); 279 - if (IS_ERR(filename)) 280 - goto out; 281 - 282 - error = do_execve(filename->name, uargv, uenvp, regs); 283 - putname(filename); 284 - out: 285 - return error; 286 289 } 287 290 288 291 unsigned long get_wchan(struct task_struct *p)
+16 -69
arch/sh/kernel/process_64.c
··· 285 285 } 286 286 287 287 /* 288 - * Create a kernel thread 289 - */ 290 - __noreturn void kernel_thread_helper(void *arg, int (*fn)(void *)) 291 - { 292 - do_exit(fn(arg)); 293 - } 294 - 295 - /* 296 - * This is the mechanism for creating a new kernel thread. 297 - * 298 - * NOTE! Only a kernel-only process(ie the swapper or direct descendants 299 - * who haven't done an "execve()") should use this: it will work within 300 - * a system call from a "real" process, but the process memory space will 301 - * not be freed until both the parent and the child have exited. 302 - */ 303 - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 304 - { 305 - struct pt_regs regs; 306 - 307 - memset(&regs, 0, sizeof(regs)); 308 - regs.regs[2] = (unsigned long)arg; 309 - regs.regs[3] = (unsigned long)fn; 310 - 311 - regs.pc = (unsigned long)kernel_thread_helper; 312 - regs.sr = (1 << 30); 313 - 314 - /* Ok, create the new process.. */ 315 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, 316 - &regs, 0, NULL, NULL); 317 - } 318 - EXPORT_SYMBOL(kernel_thread); 319 - 320 - /* 321 288 * Free current thread data structures etc.. 322 289 */ 323 290 void exit_thread(void) ··· 368 401 EXPORT_SYMBOL(dump_fpu); 369 402 370 403 asmlinkage void ret_from_fork(void); 404 + asmlinkage void ret_from_kernel_thread(void); 371 405 372 406 int copy_thread(unsigned long clone_flags, unsigned long usp, 373 - unsigned long unused, 407 + unsigned long arg, 374 408 struct task_struct *p, struct pt_regs *regs) 375 409 { 376 410 struct pt_regs *childregs; 377 411 378 412 #ifdef CONFIG_SH_FPU 379 - if(last_task_used_math == current) { 413 + /* can't happen for a kernel thread */ 414 + if (last_task_used_math == current) { 380 415 enable_fpu(); 381 416 save_fpu(current); 382 417 disable_fpu(); ··· 388 419 #endif 389 420 /* Copy from sh version */ 390 421 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; 422 + p->thread.sp = (unsigned long) childregs; 391 423 424 + if (unlikely(p->flags & PF_KTHREAD)) { 425 + memset(childregs, 0, sizeof(struct pt_regs)); 426 + childregs->regs[2] = (unsigned long)arg; 427 + childregs->regs[3] = (unsigned long)fn; 428 + childregs->sr = (1 << 30); /* not user_mode */ 429 + childregs->sr |= SR_FD; /* Invalidate FPU flag */ 430 + p->thread.pc = (unsigned long) ret_from_kernel_thread; 431 + return 0; 432 + } 392 433 *childregs = *regs; 393 434 394 435 /* ··· 407 428 * 32-bit wide and context switch must take care 408 429 * of NEFF sign extension. 409 430 */ 410 - if (user_mode(regs)) { 411 - childregs->regs[15] = neff_sign_extend(usp); 412 - p->thread.uregs = childregs; 413 - } else { 414 - childregs->regs[15] = 415 - neff_sign_extend((unsigned long)task_stack_page(p) + 416 - THREAD_SIZE); 417 - } 431 + childregs->regs[15] = neff_sign_extend(usp); 432 + p->thread.uregs = childregs; 418 433 419 434 childregs->regs[9] = 0; /* Set return value for child */ 420 435 childregs->sr |= SR_FD; /* Invalidate FPU flag */ 421 436 422 - p->thread.sp = (unsigned long) childregs; 423 437 p->thread.pc = (unsigned long) ret_from_fork; 424 438 425 439 return 0; ··· 452 480 struct pt_regs *pregs) 453 481 { 454 482 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); 455 - } 456 - 457 - /* 458 - * sys_execve() executes a new program. 459 - */ 460 - asmlinkage int sys_execve(const char *ufilename, char **uargv, 461 - char **uenvp, unsigned long r5, 462 - unsigned long r6, unsigned long r7, 463 - struct pt_regs *pregs) 464 - { 465 - int error; 466 - struct filename *filename; 467 - 468 - filename = getname((char __user *)ufilename); 469 - error = PTR_ERR(filename); 470 - if (IS_ERR(filename)) 471 - goto out; 472 - 473 - error = do_execve(filename->name, 474 - (const char __user *const __user *)uargv, 475 - (const char __user *const __user *)uenvp, 476 - pregs); 477 - putname(filename); 478 - out: 479 - return error; 480 483 } 481 484 482 485 #ifdef CONFIG_FRAME_POINTER
-24
arch/sh/kernel/sys_sh32.c
··· 60 60 (u64)len0 << 32 | len1, advice); 61 61 #endif 62 62 } 63 - 64 - #if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) 65 - #define SYSCALL_ARG3 "trapa #0x23" 66 - #else 67 - #define SYSCALL_ARG3 "trapa #0x13" 68 - #endif 69 - 70 - /* 71 - * Do a system call from kernel instead of calling sys_execve so we 72 - * end up with proper pt_regs. 73 - */ 74 - int kernel_execve(const char *filename, 75 - const char *const argv[], 76 - const char *const envp[]) 77 - { 78 - register long __sc0 __asm__ ("r3") = __NR_execve; 79 - register long __sc4 __asm__ ("r4") = (long) filename; 80 - register long __sc5 __asm__ ("r5") = (long) argv; 81 - register long __sc6 __asm__ ("r6") = (long) envp; 82 - __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) 83 - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) 84 - : "memory"); 85 - return __sc0; 86 - }
-50
arch/sh/kernel/sys_sh64.c
··· 1 - /* 2 - * arch/sh/kernel/sys_sh64.c 3 - * 4 - * Copyright (C) 2000, 2001 Paolo Alberelli 5 - * 6 - * This file contains various random system calls that 7 - * have a non-standard calling sequence on the Linux/SH5 8 - * platform. 9 - * 10 - * This file is subject to the terms and conditions of the GNU General Public 11 - * License. See the file "COPYING" in the main directory of this archive 12 - * for more details. 13 - */ 14 - #include <linux/errno.h> 15 - #include <linux/rwsem.h> 16 - #include <linux/sched.h> 17 - #include <linux/mm.h> 18 - #include <linux/fs.h> 19 - #include <linux/smp.h> 20 - #include <linux/sem.h> 21 - #include <linux/msg.h> 22 - #include <linux/shm.h> 23 - #include <linux/stat.h> 24 - #include <linux/mman.h> 25 - #include <linux/file.h> 26 - #include <linux/syscalls.h> 27 - #include <linux/ipc.h> 28 - #include <asm/uaccess.h> 29 - #include <asm/ptrace.h> 30 - #include <asm/unistd.h> 31 - 32 - /* 33 - * Do a system call from kernel instead of calling sys_execve so we 34 - * end up with proper pt_regs. 35 - */ 36 - int kernel_execve(const char *filename, 37 - const char *const argv[], 38 - const char *const envp[]) 39 - { 40 - register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); 41 - register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; 42 - register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; 43 - register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; 44 - __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" 45 - : "=r" (__sc0) 46 - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); 47 - __asm__ __volatile__ ("!dummy %0 %1 %2 %3" 48 - : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); 49 - return __sc0; 50 - }
+2
arch/sparc/Kconfig
··· 41 41 select GENERIC_STRNCPY_FROM_USER 42 42 select GENERIC_STRNLEN_USER 43 43 select MODULES_USE_ELF_RELA 44 + select GENERIC_KERNEL_THREAD 45 + select GENERIC_KERNEL_EXECVE 44 46 45 47 config SPARC32 46 48 def_bool !64BIT
-1
arch/sparc/include/asm/processor_32.h
··· 106 106 107 107 /* Free all resources held by a thread. */ 108 108 #define release_thread(tsk) do { } while(0) 109 - extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 110 109 111 110 extern unsigned long get_wchan(struct task_struct *); 112 111
+9 -2
arch/sparc/include/asm/processor_64.h
··· 94 94 #ifndef __ASSEMBLY__ 95 95 96 96 #include <linux/types.h> 97 + #include <asm/fpumacro.h> 97 98 98 99 /* Return saved PC of a blocked thread. */ 99 100 struct task_struct; ··· 144 143 : \ 145 144 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \ 146 145 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 146 + fprs_write(0); \ 147 + current_thread_info()->xfsr[0] = 0; \ 148 + current_thread_info()->fpsaved[0] = 0; \ 149 + regs->tstate &= ~TSTATE_PEF; \ 147 150 } while (0) 148 151 149 152 #define start_thread32(regs, pc, sp) \ ··· 188 183 : \ 189 184 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \ 190 185 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \ 186 + fprs_write(0); \ 187 + current_thread_info()->xfsr[0] = 0; \ 188 + current_thread_info()->fpsaved[0] = 0; \ 189 + regs->tstate &= ~TSTATE_PEF; \ 191 190 } while (0) 192 191 193 192 /* Free all resources held by a thread. */ 194 193 #define release_thread(tsk) do { } while (0) 195 - 196 - extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 197 194 198 195 extern unsigned long get_wchan(struct task_struct *task); 199 196
+7 -3
arch/sparc/include/asm/ptrace.h
··· 32 32 #define arch_ptrace_stop(exit_code, info) \ 33 33 synchronize_user_stack() 34 34 35 + #define current_pt_regs() \ 36 + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) 37 + 35 38 struct global_reg_snapshot { 36 39 unsigned long tstate; 37 40 unsigned long tpc; ··· 58 55 59 56 extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS]; 60 57 61 - #define force_successful_syscall_return() \ 62 - do { current_thread_info()->syscall_noerror = 1; \ 63 - } while (0) 58 + #define force_successful_syscall_return() set_thread_noerror(1) 64 59 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV)) 65 60 #define instruction_pointer(regs) ((regs)->tpc) 66 61 #define instruction_pointer_set(regs, val) ((regs)->tpc = (val)) ··· 100 99 101 100 #define arch_ptrace_stop(exit_code, info) \ 102 101 synchronize_user_stack() 102 + 103 + #define current_pt_regs() \ 104 + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) 103 105 104 106 #define user_mode(regs) (!((regs)->psr & PSR_PS)) 105 107 #define instruction_pointer(regs) ((regs)->pc)
+1 -1
arch/sparc/include/asm/switch_to_64.h
··· 23 23 /* If you are tempted to conditionalize the following */ \ 24 24 /* so that ASI is only written if it changes, think again. */ \ 25 25 __asm__ __volatile__("wr %%g0, %0, %%asi" \ 26 - : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\ 26 + : : "r" (task_thread_info(next)->current_ds));\ 27 27 trap_block[current_thread_info()->cpu].thread = \ 28 28 task_thread_info(next); \ 29 29 __asm__ __volatile__( \
-2
arch/sparc/include/asm/syscalls.h
··· 8 8 struct pt_regs *regs, 9 9 unsigned long stack_size); 10 10 11 - extern asmlinkage int sparc_execve(struct pt_regs *regs); 12 - 13 11 #endif /* _SPARC64_SYSCALLS_H */
+12 -13
arch/sparc/include/asm/thread_info_64.h
··· 14 14 #define TI_FLAG_FAULT_CODE_SHIFT 56 15 15 #define TI_FLAG_BYTE_WSTATE 1 16 16 #define TI_FLAG_WSTATE_SHIFT 48 17 - #define TI_FLAG_BYTE_CWP 2 18 - #define TI_FLAG_CWP_SHIFT 40 19 - #define TI_FLAG_BYTE_CURRENT_DS 3 20 - #define TI_FLAG_CURRENT_DS_SHIFT 32 21 - #define TI_FLAG_BYTE_FPDEPTH 4 22 - #define TI_FLAG_FPDEPTH_SHIFT 24 17 + #define TI_FLAG_BYTE_NOERROR 2 18 + #define TI_FLAG_BYTE_NOERROR_SHIFT 40 19 + #define TI_FLAG_BYTE_FPDEPTH 3 20 + #define TI_FLAG_FPDEPTH_SHIFT 32 21 + #define TI_FLAG_BYTE_CWP 4 22 + #define TI_FLAG_CWP_SHIFT 24 23 23 #define TI_FLAG_BYTE_WSAVED 5 24 24 #define TI_FLAG_WSAVED_SHIFT 16 25 25 ··· 47 47 struct exec_domain *exec_domain; 48 48 int preempt_count; /* 0 => preemptable, <0 => BUG */ 49 49 __u8 new_child; 50 - __u8 syscall_noerror; 50 + __u8 current_ds; 51 51 __u16 cpu; 52 52 53 53 unsigned long *utraps; ··· 74 74 #define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE) 75 75 #define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE) 76 76 #define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP) 77 - #define TI_CURRENT_DS (TI_FLAGS + TI_FLAG_BYTE_CURRENT_DS) 78 77 #define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH) 79 78 #define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED) 79 + #define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR) 80 80 #define TI_FPSAVED 0x00000010 81 81 #define TI_KSP 0x00000018 82 82 #define TI_FAULT_ADDR 0x00000020 ··· 84 84 #define TI_EXEC_DOMAIN 0x00000030 85 85 #define TI_PRE_COUNT 0x00000038 86 86 #define TI_NEW_CHILD 0x0000003c 87 - #define TI_SYS_NOERROR 0x0000003d 87 + #define TI_CURRENT_DS 0x0000003d 88 88 #define TI_CPU 0x0000003e 89 89 #define TI_UTRAPS 0x00000040 90 90 #define TI_REG_WINDOW 0x00000048 ··· 121 121 #define INIT_THREAD_INFO(tsk) \ 122 122 { \ 123 123 .task = &tsk, \ 124 - .flags = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT, \ 124 + .current_ds = ASI_P, \ 125 125 .exec_domain = &default_exec_domain, \ 126 126 .preempt_count = INIT_PREEMPT_COUNT, \ 127 127 .restart_block = { \ ··· 153 153 #define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val)) 154 154 #define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP]) 155 155 #define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val)) 156 - #define get_thread_current_ds() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS]) 157 - #define set_thread_current_ds(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CURRENT_DS] = (val)) 156 + #define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR]) 157 + #define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val)) 158 158 #define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH]) 159 159 #define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val)) 160 160 #define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED]) 161 161 #define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val)) 162 - 163 162 #endif /* !(__ASSEMBLY__) */ 164 163 165 164 /*
+2 -2
arch/sparc/include/asm/uaccess_64.h
··· 38 38 #define VERIFY_READ 0 39 39 #define VERIFY_WRITE 1 40 40 41 - #define get_fs() ((mm_segment_t) { get_thread_current_ds() }) 41 + #define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) 42 42 #define get_ds() (KERNEL_DS) 43 43 44 44 #define segment_eq(a,b) ((a).seg == (b).seg) 45 45 46 46 #define set_fs(val) \ 47 47 do { \ 48 - set_thread_current_ds((val).seg); \ 48 + current_thread_info()->current_ds =(val).seg; \ 49 49 __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ 50 50 } while(0) 51 51
+1
arch/sparc/include/asm/unistd.h
··· 46 46 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND 47 47 #define __ARCH_WANT_COMPAT_SYS_SENDFILE 48 48 #endif 49 + #define __ARCH_WANT_SYS_EXECVE 49 50 50 51 /* 51 52 * "Conditional" syscalls
+22 -29
arch/sparc/kernel/entry.S
··· 806 806 call c_sys_nis_syscall 807 807 mov %l5, %o7 808 808 809 - .align 4 810 - .globl sys_execve 811 - sys_execve: 812 - mov %o7, %l5 813 - add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg 814 - call sparc_execve 815 - mov %l5, %o7 816 - 817 - .globl sunos_execv 818 809 sunos_execv: 819 - st %g0, [%sp + STACKFRAME_SZ + PT_I2] 820 - 821 - call sparc_execve 822 - add %sp, STACKFRAME_SZ, %o0 823 - 824 - b ret_sys_call 825 - ld [%sp + STACKFRAME_SZ + PT_I0], %o0 810 + .globl sunos_execv 811 + b sys_execve 812 + clr %i2 826 813 827 814 .align 4 828 815 .globl sys_sparc_pipe ··· 946 959 .align 4 947 960 linux_sparc_ni_syscall: 948 961 sethi %hi(sys_ni_syscall), %l7 949 - b syscall_is_too_hard 962 + b do_syscall 950 963 or %l7, %lo(sys_ni_syscall), %l7 951 - 952 - linux_fast_syscall: 953 - andn %l7, 3, %l7 954 - mov %i0, %o0 955 - mov %i1, %o1 956 - mov %i2, %o2 957 - jmpl %l7 + %g0, %g0 958 - mov %i3, %o3 959 964 960 965 linux_syscall_trace: 961 966 add %sp, STACKFRAME_SZ, %o0 ··· 970 991 b ret_sys_call 971 992 ld [%sp + STACKFRAME_SZ + PT_I0], %o0 972 993 994 + .globl ret_from_kernel_thread 995 + ret_from_kernel_thread: 996 + call schedule_tail 997 + ld [%g3 + TI_TASK], %o0 998 + ld [%sp + STACKFRAME_SZ + PT_G1], %l0 999 + call %l0 1000 + ld [%sp + STACKFRAME_SZ + PT_G2], %o0 1001 + rd %psr, %l1 1002 + ld [%sp + STACKFRAME_SZ + PT_PSR], %l0 1003 + andn %l0, PSR_CWP, %l0 1004 + nop 1005 + and %l1, PSR_CWP, %l1 1006 + or %l0, %l1, %l0 1007 + st %l0, [%sp + STACKFRAME_SZ + PT_PSR] 1008 + b ret_sys_call 1009 + mov 0, %o0 1010 + 973 1011 /* Linux native system calls enter here... */ 974 1012 .align 4 975 1013 .globl linux_sparc_syscall ··· 998 1002 bgeu linux_sparc_ni_syscall 999 1003 sll %g1, 2, %l4 1000 1004 ld [%l7 + %l4], %l7 1001 - andcc %l7, 1, %g0 1002 - bne linux_fast_syscall 1003 - /* Just do first insn from SAVE_ALL in the delay slot */ 1004 1005 1005 - syscall_is_too_hard: 1006 + do_syscall: 1006 1007 SAVE_ALL_HEAD 1007 1008 rd %wim, %l3 1008 1009
+6 -2
arch/sparc/kernel/etrap_64.S
··· 92 92 rdpr %wstate, %g2 93 93 wrpr %g0, 0, %canrestore 94 94 sll %g2, 3, %g2 95 + 96 + /* Set TI_SYS_FPDEPTH to 1 and clear TI_SYS_NOERROR. */ 95 97 mov 1, %l5 96 - stb %l5, [%l6 + TI_FPDEPTH] 98 + sth %l5, [%l6 + TI_SYS_NOERROR] 97 99 98 100 wrpr %g3, 0, %otherwin 99 101 wrpr %g2, 0, %wstate ··· 154 152 add %l6, TI_FPSAVED + 1, %l4 155 153 srl %l5, 1, %l3 156 154 add %l5, 2, %l5 157 - stb %l5, [%l6 + TI_FPDEPTH] 155 + 156 + /* Set TI_SYS_FPDEPTH to %l5 and clear TI_SYS_NOERROR. */ 157 + sth %l5, [%l6 + TI_SYS_NOERROR] 158 158 ba,pt %xcc, 2b 159 159 stb %g0, [%l4 + %l3] 160 160 nop
+45 -107
arch/sparc/kernel/process_32.c
··· 316 316 * XXX See comment above sys_vfork in sparc64. todo. 317 317 */ 318 318 extern void ret_from_fork(void); 319 + extern void ret_from_kernel_thread(void); 319 320 320 321 int copy_thread(unsigned long clone_flags, unsigned long sp, 321 - unsigned long unused, 322 + unsigned long arg, 322 323 struct task_struct *p, struct pt_regs *regs) 323 324 { 324 325 struct thread_info *ti = task_thread_info(p); ··· 337 336 } 338 337 339 338 /* 340 - * p->thread_info new_stack childregs 341 - * ! ! ! {if(PSR_PS) } 342 - * V V (stk.fr.) V (pt_regs) { (stk.fr.) } 343 - * +----- - - - - - ------+===========+============={+==========}+ 339 + * p->thread_info new_stack childregs stack bottom 340 + * ! ! ! ! 341 + * V V (stk.fr.) V (pt_regs) V 342 + * +----- - - - - - ------+===========+=============+ 344 343 */ 345 344 new_stack = task_stack_page(p) + THREAD_SIZE; 346 - if (regs->psr & PSR_PS) 347 - new_stack -= STACKFRAME_SZ; 348 345 new_stack -= STACKFRAME_SZ + TRACEREG_SZ; 349 - memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); 350 346 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ); 351 347 352 348 /* ··· 354 356 * Thus, kpsr|=PSR_PIL. 355 357 */ 356 358 ti->ksp = (unsigned long) new_stack; 359 + p->thread.kregs = childregs; 360 + 361 + if (unlikely(p->flags & PF_KTHREAD)) { 362 + extern int nwindows; 363 + unsigned long psr; 364 + memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ); 365 + p->thread.flags |= SPARC_FLAG_KTHREAD; 366 + p->thread.current_ds = KERNEL_DS; 367 + ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8); 368 + childregs->u_regs[UREG_G1] = sp; /* function */ 369 + childregs->u_regs[UREG_G2] = arg; 370 + psr = childregs->psr = get_psr(); 371 + ti->kpsr = psr | PSR_PIL; 372 + ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows); 373 + return 0; 374 + } 375 + memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ); 376 + childregs->u_regs[UREG_FP] = sp; 377 + p->thread.flags &= ~SPARC_FLAG_KTHREAD; 378 + p->thread.current_ds = USER_DS; 357 379 ti->kpc = (((unsigned long) ret_from_fork) - 0x8); 358 380 ti->kpsr = current->thread.fork_kpsr | PSR_PIL; 359 381 ti->kwim = current->thread.fork_kwim; 360 382 361 - if(regs->psr & PSR_PS) { 362 - extern struct pt_regs fake_swapper_regs; 383 + if (sp != regs->u_regs[UREG_FP]) { 384 + struct sparc_stackf __user *childstack; 385 + struct sparc_stackf __user *parentstack; 363 386 364 - p->thread.kregs = &fake_swapper_regs; 365 - new_stack += STACKFRAME_SZ + TRACEREG_SZ; 366 - childregs->u_regs[UREG_FP] = (unsigned long) new_stack; 367 - p->thread.flags |= SPARC_FLAG_KTHREAD; 368 - p->thread.current_ds = KERNEL_DS; 369 - memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ); 370 - childregs->u_regs[UREG_G6] = (unsigned long) ti; 371 - } else { 372 - p->thread.kregs = childregs; 373 - childregs->u_regs[UREG_FP] = sp; 374 - p->thread.flags &= ~SPARC_FLAG_KTHREAD; 375 - p->thread.current_ds = USER_DS; 376 - 377 - if (sp != regs->u_regs[UREG_FP]) { 378 - struct sparc_stackf __user *childstack; 379 - struct sparc_stackf __user *parentstack; 380 - 381 - /* 382 - * This is a clone() call with supplied user stack. 383 - * Set some valid stack frames to give to the child. 384 - */ 385 - childstack = (struct sparc_stackf __user *) 386 - (sp & ~0xfUL); 387 - parentstack = (struct sparc_stackf __user *) 388 - regs->u_regs[UREG_FP]; 387 + /* 388 + * This is a clone() call with supplied user stack. 389 + * Set some valid stack frames to give to the child. 390 + */ 391 + childstack = (struct sparc_stackf __user *) 392 + (sp & ~0xfUL); 393 + parentstack = (struct sparc_stackf __user *) 394 + regs->u_regs[UREG_FP]; 389 395 390 396 #if 0 391 - printk("clone: parent stack:\n"); 392 - show_stackframe(parentstack); 397 + printk("clone: parent stack:\n"); 398 + show_stackframe(parentstack); 393 399 #endif 394 400 395 - childstack = clone_stackframe(childstack, parentstack); 396 - if (!childstack) 397 - return -EFAULT; 401 + childstack = clone_stackframe(childstack, parentstack); 402 + if (!childstack) 403 + return -EFAULT; 398 404 399 405 #if 0 400 - printk("clone: child stack:\n"); 401 - show_stackframe(childstack); 406 + printk("clone: child stack:\n"); 407 + show_stackframe(childstack); 402 408 #endif 403 409 404 - childregs->u_regs[UREG_FP] = (unsigned long)childstack; 405 - } 410 + childregs->u_regs[UREG_FP] = (unsigned long)childstack; 406 411 } 407 412 408 413 #ifdef CONFIG_SMP ··· 475 474 sizeof(struct fpq) * (32 - fpregs->pr_qcnt)); 476 475 return 1; 477 476 } 478 - 479 - /* 480 - * sparc_execve() executes a new program after the asm stub has set 481 - * things up for us. This should basically do what I want it to. 482 - */ 483 - asmlinkage int sparc_execve(struct pt_regs *regs) 484 - { 485 - int error, base = 0; 486 - struct filename *filename; 487 - 488 - /* Check for indirect call. */ 489 - if(regs->u_regs[UREG_G1] == 0) 490 - base = 1; 491 - 492 - filename = getname((char __user *)regs->u_regs[base + UREG_I0]); 493 - error = PTR_ERR(filename); 494 - if(IS_ERR(filename)) 495 - goto out; 496 - error = do_execve(filename->name, 497 - (const char __user *const __user *) 498 - regs->u_regs[base + UREG_I1], 499 - (const char __user *const __user *) 500 - regs->u_regs[base + UREG_I2], 501 - regs); 502 - putname(filename); 503 - out: 504 - return error; 505 - } 506 - 507 - /* 508 - * This is the mechanism for creating a new kernel thread. 509 - * 510 - * NOTE! Only a kernel-only process(ie the swapper or direct descendants 511 - * who haven't done an "execve()") should use this: it will work within 512 - * a system call from a "real" process, but the process memory space will 513 - * not be freed until both the parent and the child have exited. 514 - */ 515 - pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 516 - { 517 - long retval; 518 - 519 - __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */ 520 - "mov %5, %%g3\n\t" /* and arg. */ 521 - "mov %1, %%g1\n\t" 522 - "mov %2, %%o0\n\t" /* Clone flags. */ 523 - "mov 0, %%o1\n\t" /* usp arg == 0 */ 524 - "t 0x10\n\t" /* Linux/Sparc clone(). */ 525 - "cmp %%o1, 0\n\t" 526 - "be 1f\n\t" /* The parent, just return. */ 527 - " nop\n\t" /* Delay slot. */ 528 - "jmpl %%g2, %%o7\n\t" /* Call the function. */ 529 - " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */ 530 - "mov %3, %%g1\n\t" 531 - "t 0x10\n\t" /* Linux/Sparc exit(). */ 532 - /* Notreached by child. */ 533 - "1: mov %%o0, %0\n\t" : 534 - "=r" (retval) : 535 - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), 536 - "i" (__NR_exit), "r" (fn), "r" (arg) : 537 - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); 538 - return retval; 539 - } 540 - EXPORT_SYMBOL(kernel_thread); 541 477 542 478 unsigned long get_wchan(struct task_struct *task) 543 479 {
+31 -114
arch/sparc/kernel/process_64.c
··· 622 622 * Child --> %o0 == parents pid, %o1 == 1 623 623 */ 624 624 int copy_thread(unsigned long clone_flags, unsigned long sp, 625 - unsigned long unused, 625 + unsigned long arg, 626 626 struct task_struct *p, struct pt_regs *regs) 627 627 { 628 628 struct thread_info *t = task_thread_info(p); 629 629 struct sparc_stackf *parent_sf; 630 630 unsigned long child_stack_sz; 631 631 char *child_trap_frame; 632 - int kernel_thread; 633 - 634 - kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; 635 - parent_sf = ((struct sparc_stackf *) regs) - 1; 636 632 637 633 /* Calculate offset to stack_frame & pt_regs */ 638 - child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + 639 - (kernel_thread ? STACKFRAME_SZ : 0)); 634 + child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ); 640 635 child_trap_frame = (task_stack_page(p) + 641 636 (THREAD_SIZE - child_stack_sz)); 642 - memcpy(child_trap_frame, parent_sf, child_stack_sz); 643 637 644 - t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | 645 - (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | 646 - (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); 647 638 t->new_child = 1; 648 639 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; 649 640 t->kregs = (struct pt_regs *) (child_trap_frame + 650 641 sizeof(struct sparc_stackf)); 651 642 t->fpsaved[0] = 0; 652 643 653 - if (kernel_thread) { 654 - struct sparc_stackf *child_sf = (struct sparc_stackf *) 655 - (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); 656 - 657 - /* Zero terminate the stack backtrace. */ 658 - child_sf->fp = NULL; 659 - t->kregs->u_regs[UREG_FP] = 660 - ((unsigned long) child_sf) - STACK_BIAS; 661 - 662 - t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); 663 - t->kregs->u_regs[UREG_G6] = (unsigned long) t; 664 - t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; 665 - } else { 666 - if (t->flags & _TIF_32BIT) { 667 - sp &= 0x00000000ffffffffUL; 668 - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; 669 - } 670 - t->kregs->u_regs[UREG_FP] = sp; 671 - t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT); 672 - if (sp != regs->u_regs[UREG_FP]) { 673 - unsigned long csp; 674 - 675 - csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); 676 - if (!csp) 677 - return -EFAULT; 678 - t->kregs->u_regs[UREG_FP] = csp; 679 - } 680 - if (t->utraps) 681 - t->utraps[0]++; 644 + if (unlikely(p->flags & PF_KTHREAD)) { 645 + memset(child_trap_frame, 0, child_stack_sz); 646 + __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 647 + (current_pt_regs()->tstate + 1) & TSTATE_CWP; 648 + t->current_ds = ASI_P; 649 + t->kregs->u_regs[UREG_G1] = sp; /* function */ 650 + t->kregs->u_regs[UREG_G2] = arg; 651 + return 0; 682 652 } 653 + 654 + parent_sf = ((struct sparc_stackf *) regs) - 1; 655 + memcpy(child_trap_frame, parent_sf, child_stack_sz); 656 + if (t->flags & _TIF_32BIT) { 657 + sp &= 0x00000000ffffffffUL; 658 + regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; 659 + } 660 + t->kregs->u_regs[UREG_FP] = sp; 661 + __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 662 + (regs->tstate + 1) & TSTATE_CWP; 663 + t->current_ds = ASI_AIUS; 664 + if (sp != regs->u_regs[UREG_FP]) { 665 + unsigned long csp; 666 + 667 + csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); 668 + if (!csp) 669 + return -EFAULT; 670 + t->kregs->u_regs[UREG_FP] = csp; 671 + } 672 + if (t->utraps) 673 + t->utraps[0]++; 683 674 684 675 /* Set the return value for the child. */ 685 676 t->kregs->u_regs[UREG_I0] = current->pid; ··· 684 693 685 694 return 0; 686 695 } 687 - 688 - /* 689 - * This is the mechanism for creating a new kernel thread. 690 - * 691 - * NOTE! Only a kernel-only process(ie the swapper or direct descendants 692 - * who haven't done an "execve()") should use this: it will work within 693 - * a system call from a "real" process, but the process memory space will 694 - * not be freed until both the parent and the child have exited. 695 - */ 696 - pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 697 - { 698 - long retval; 699 - 700 - /* If the parent runs before fn(arg) is called by the child, 701 - * the input registers of this function can be clobbered. 702 - * So we stash 'fn' and 'arg' into global registers which 703 - * will not be modified by the parent. 704 - */ 705 - __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */ 706 - "mov %5, %%g3\n\t" /* Save ARG into global */ 707 - "mov %1, %%g1\n\t" /* Clone syscall nr. */ 708 - "mov %2, %%o0\n\t" /* Clone flags. */ 709 - "mov 0, %%o1\n\t" /* usp arg == 0 */ 710 - "t 0x6d\n\t" /* Linux/Sparc clone(). */ 711 - "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ 712 - " mov %%o0, %0\n\t" 713 - "jmpl %%g2, %%o7\n\t" /* Call the function. */ 714 - " mov %%g3, %%o0\n\t" /* Set arg in delay. */ 715 - "mov %3, %%g1\n\t" 716 - "t 0x6d\n\t" /* Linux/Sparc exit(). */ 717 - /* Notreached by child. */ 718 - "1:" : 719 - "=r" (retval) : 720 - "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED), 721 - "i" (__NR_exit), "r" (fn), "r" (arg) : 722 - "g1", "g2", "g3", "o0", "o1", "memory", "cc"); 723 - return retval; 724 - } 725 - EXPORT_SYMBOL(kernel_thread); 726 696 727 697 typedef struct { 728 698 union { ··· 750 798 return 1; 751 799 } 752 800 EXPORT_SYMBOL(dump_fpu); 753 - 754 - /* 755 - * sparc_execve() executes a new program after the asm stub has set 756 - * things up for us. This should basically do what I want it to. 757 - */ 758 - asmlinkage int sparc_execve(struct pt_regs *regs) 759 - { 760 - int error, base = 0; 761 - struct filename *filename; 762 - 763 - /* User register window flush is done by entry.S */ 764 - 765 - /* Check for indirect call. */ 766 - if (regs->u_regs[UREG_G1] == 0) 767 - base = 1; 768 - 769 - filename = getname((char __user *)regs->u_regs[base + UREG_I0]); 770 - error = PTR_ERR(filename); 771 - if (IS_ERR(filename)) 772 - goto out; 773 - error = do_execve(filename->name, 774 - (const char __user *const __user *) 775 - regs->u_regs[base + UREG_I1], 776 - (const char __user *const __user *) 777 - regs->u_regs[base + UREG_I2], regs); 778 - putname(filename); 779 - if (!error) { 780 - fprs_write(0); 781 - current_thread_info()->xfsr[0] = 0; 782 - current_thread_info()->fpsaved[0] = 0; 783 - regs->tstate &= ~TSTATE_PEF; 784 - } 785 - out: 786 - return error; 787 - } 788 801 789 802 unsigned long get_wchan(struct task_struct *task) 790 803 {
-36
arch/sparc/kernel/sys_sparc32.c
··· 396 396 return ret; 397 397 } 398 398 399 - /* 400 - * sparc32_execve() executes a new program after the asm stub has set 401 - * things up for us. This should basically do what I want it to. 402 - */ 403 - asmlinkage long sparc32_execve(struct pt_regs *regs) 404 - { 405 - int error, base = 0; 406 - struct filename *filename; 407 - 408 - /* User register window flush is done by entry.S */ 409 - 410 - /* Check for indirect call. */ 411 - if ((u32)regs->u_regs[UREG_G1] == 0) 412 - base = 1; 413 - 414 - filename = getname(compat_ptr(regs->u_regs[base + UREG_I0])); 415 - error = PTR_ERR(filename); 416 - if (IS_ERR(filename)) 417 - goto out; 418 - 419 - error = compat_do_execve(filename->name, 420 - compat_ptr(regs->u_regs[base + UREG_I1]), 421 - compat_ptr(regs->u_regs[base + UREG_I2]), regs); 422 - 423 - putname(filename); 424 - 425 - if (!error) { 426 - fprs_write(0); 427 - current_thread_info()->xfsr[0] = 0; 428 - current_thread_info()->fpsaved[0] = 0; 429 - regs->tstate &= ~TSTATE_PEF; 430 - } 431 - out: 432 - return error; 433 - } 434 - 435 399 #ifdef CONFIG_MODULES 436 400 437 401 asmlinkage long sys32_init_module(void __user *umod, u32 len,
-24
arch/sparc/kernel/sys_sparc_32.c
··· 258 258 up_read(&uts_sem); 259 259 return err; 260 260 } 261 - 262 - /* 263 - * Do a system call from kernel instead of calling sys_execve so we 264 - * end up with proper pt_regs. 265 - */ 266 - int kernel_execve(const char *filename, 267 - const char *const argv[], 268 - const char *const envp[]) 269 - { 270 - long __res; 271 - register long __g1 __asm__ ("g1") = __NR_execve; 272 - register long __o0 __asm__ ("o0") = (long)(filename); 273 - register long __o1 __asm__ ("o1") = (long)(argv); 274 - register long __o2 __asm__ ("o2") = (long)(envp); 275 - asm volatile ("t 0x10\n\t" 276 - "bcc 1f\n\t" 277 - "mov %%o0, %0\n\t" 278 - "sub %%g0, %%o0, %0\n\t" 279 - "1:\n\t" 280 - : "=r" (__res), "=&r" (__o0) 281 - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) 282 - : "cc"); 283 - return __res; 284 - }
-22
arch/sparc/kernel/sys_sparc_64.c
··· 730 730 return ret; 731 731 } 732 732 733 - /* 734 - * Do a system call from kernel instead of calling sys_execve so we 735 - * end up with proper pt_regs. 736 - */ 737 - int kernel_execve(const char *filename, 738 - const char *const argv[], 739 - const char *const envp[]) 740 - { 741 - long __res; 742 - register long __g1 __asm__ ("g1") = __NR_execve; 743 - register long __o0 __asm__ ("o0") = (long)(filename); 744 - register long __o1 __asm__ ("o1") = (long)(argv); 745 - register long __o2 __asm__ ("o2") = (long)(envp); 746 - asm volatile ("t 0x6d\n\t" 747 - "sub %%g0, %%o0, %0\n\t" 748 - "movcc %%xcc, %%o0, %0\n\t" 749 - : "=r" (__res), "=&r" (__o0) 750 - : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) 751 - : "cc"); 752 - return __res; 753 - } 754 - 755 733 asmlinkage long sys_kern_features(void) 756 734 { 757 735 return KERN_FEATURE_MIXED_MODE_STACK;
+15 -15
arch/sparc/kernel/syscalls.S
··· 1 1 /* SunOS's execv() call only specifies the argv argument, the 2 2 * environment settings are the same as the calling processes. 3 3 */ 4 - sys_execve: 5 - sethi %hi(sparc_execve), %g1 6 - ba,pt %xcc, execve_merge 7 - or %g1, %lo(sparc_execve), %g1 4 + sys64_execve: 5 + set sys_execve, %g1 6 + jmpl %g1, %g0 7 + flushw 8 8 9 9 #ifdef CONFIG_COMPAT 10 10 sunos_execv: 11 - stx %g0, [%sp + PTREGS_OFF + PT_V9_I2] 11 + mov %g0, %o2 12 12 sys32_execve: 13 - sethi %hi(sparc32_execve), %g1 14 - or %g1, %lo(sparc32_execve), %g1 15 - #endif 16 - 17 - execve_merge: 18 - flushw 13 + set compat_sys_execve, %g1 19 14 jmpl %g1, %g0 20 - add %sp, PTREGS_OFF, %o0 15 + flushw 16 + #endif 21 17 22 18 .align 32 23 19 sys_sparc_pipe: ··· 108 112 ret_from_syscall: 109 113 /* Clear current_thread_info()->new_child. */ 110 114 stb %g0, [%g6 + TI_NEW_CHILD] 111 - ldx [%g6 + TI_FLAGS], %l0 112 115 call schedule_tail 113 116 mov %g7, %o0 117 + ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 118 + brnz,pt %o0, ret_sys_call 119 + ldx [%g6 + TI_FLAGS], %l0 120 + ldx [%sp + PTREGS_OFF + PT_V9_G1], %l1 121 + call %l1 122 + ldx [%sp + PTREGS_OFF + PT_V9_G2], %o0 114 123 ba,pt %xcc, ret_sys_call 115 - ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0 124 + mov 0, %o0 116 125 117 126 .globl sparc_exit 118 127 .type sparc_exit,#function ··· 223 222 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc 224 223 225 224 2: 226 - stb %g0, [%g6 + TI_SYS_NOERROR] 227 225 /* System call success, clear Carry condition code. */ 228 226 andn %g3, %g2, %g3 229 227 3:
+1 -1
arch/sparc/kernel/systbls_64.S
··· 107 107 /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall 108 108 .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid 109 109 /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl 110 - .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve 110 + .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys64_execve 111 111 /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize 112 112 .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall 113 113 /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect
+2 -2
arch/sparc/kernel/traps_64.c
··· 2688 2688 TI_PRE_COUNT != offsetof(struct thread_info, 2689 2689 preempt_count) || 2690 2690 TI_NEW_CHILD != offsetof(struct thread_info, new_child) || 2691 - TI_SYS_NOERROR != offsetof(struct thread_info, 2692 - syscall_noerror) || 2691 + TI_CURRENT_DS != offsetof(struct thread_info, 2692 + current_ds) || 2693 2693 TI_RESTART_BLOCK != offsetof(struct thread_info, 2694 2694 restart_block) || 2695 2695 TI_KUNA_REGS != offsetof(struct thread_info,
+1 -1
arch/sparc/mm/init_64.c
··· 624 624 void prom_world(int enter) 625 625 { 626 626 if (!enter) 627 - set_fs((mm_segment_t) { get_thread_current_ds() }); 627 + set_fs(get_fs()); 628 628 629 629 __asm__ __volatile__("flushw"); 630 630 }
+2
arch/tile/Kconfig
··· 21 21 select ARCH_HAVE_NMI_SAFE_CMPXCHG 22 22 select GENERIC_CLOCKEVENTS 23 23 select MODULES_USE_ELF_RELA 24 + select GENERIC_KERNEL_THREAD 25 + select GENERIC_KERNEL_EXECVE 24 26 25 27 # FIXME: investigate whether we need/want these options. 26 28 # select HAVE_IOREMAP_PROT
+3 -12
arch/tile/include/asm/compat.h
··· 275 275 struct compat_sigaction; 276 276 struct compat_siginfo; 277 277 struct compat_sigaltstack; 278 - long compat_sys_execve(const char __user *path, 279 - compat_uptr_t __user *argv, 280 - compat_uptr_t __user *envp, struct pt_regs *); 281 278 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, 282 279 struct compat_sigaction __user *oact, 283 280 size_t sigsetsize); 284 281 long compat_sys_rt_sigqueueinfo(int pid, int sig, 285 282 struct compat_siginfo __user *uinfo); 286 - long compat_sys_rt_sigreturn(struct pt_regs *); 283 + long compat_sys_rt_sigreturn(void); 287 284 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, 288 - struct compat_sigaltstack __user *uoss_ptr, 289 - struct pt_regs *); 285 + struct compat_sigaltstack __user *uoss_ptr); 290 286 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high); 291 287 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high); 292 288 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, ··· 299 303 long compat_sys_sched_rr_get_interval(compat_pid_t pid, 300 304 struct compat_timespec __user *interval); 301 305 302 - /* These are the intvec_64.S trampolines. */ 303 - long _compat_sys_execve(const char __user *path, 304 - const compat_uptr_t __user *argv, 305 - const compat_uptr_t __user *envp); 306 - long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, 307 - struct compat_sigaltstack __user *uoss_ptr); 306 + /* Assembly trampoline to avoid clobbering r0. */ 308 307 long _compat_sys_rt_sigreturn(void); 309 308 310 309 #endif /* _ASM_TILE_COMPAT_H */
+1
arch/tile/include/asm/elf.h
··· 148 148 #define compat_start_thread(regs, ip, usp) do { \ 149 149 regs->pc = ptr_to_compat_reg((void *)(ip)); \ 150 150 regs->sp = ptr_to_compat_reg((void *)(usp)); \ 151 + single_step_execve(); \ 151 152 } while (0) 152 153 153 154 /*
+4
arch/tile/include/asm/processor.h
··· 211 211 { 212 212 regs->pc = pc; 213 213 regs->sp = usp; 214 + single_step_execve(); 214 215 } 215 216 216 217 /* Free all resources held by a thread. */ ··· 240 239 #define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA) 241 240 #define task_pt_regs(task) \ 242 241 ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) 242 + #define current_pt_regs() \ 243 + ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ 244 + (KSTK_PTREGS_GAP - 1)) - 1) 243 245 #define task_sp(task) (task_pt_regs(task)->sp) 244 246 #define task_pc(task) (task_pt_regs(task)->pc) 245 247 /* Aliases for pc and sp (used in fs/proc/array.c) */
+4 -1
arch/tile/include/asm/switch_to.h
··· 68 68 /* Support function for forking a new task. */ 69 69 void ret_from_fork(void); 70 70 71 - /* Called from ret_from_fork() when a new process starts up. */ 71 + /* Support function for forking a new kernel thread. */ 72 + void ret_from_kernel_thread(void *fn, void *arg); 73 + 74 + /* Called from ret_from_xxx() when a new process starts up. */ 72 75 struct task_struct *sim_notify_fork(struct task_struct *prev); 73 76 74 77 #endif /* !__ASSEMBLY__ */
+14 -6
arch/tile/include/asm/syscalls.h
··· 51 51 52 52 #ifndef __tilegx__ 53 53 /* mm/fault.c */ 54 - long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *); 55 - long _sys_cmpxchg_badaddr(unsigned long address); 54 + long sys_cmpxchg_badaddr(unsigned long address); 56 55 #endif 57 56 58 57 #ifdef CONFIG_COMPAT ··· 62 63 long sys_ftruncate64(unsigned int fd, loff_t length); 63 64 #endif 64 65 66 + /* Provide versions of standard syscalls that use current_pt_regs(). */ 67 + long sys_clone(unsigned long clone_flags, unsigned long newsp, 68 + void __user *parent_tid, void __user *child_tid); 69 + long sys_execve(const char __user *filename, 70 + const char __user *const __user *argv, 71 + const char __user *const __user *envp); 72 + long sys_rt_sigreturn(void); 73 + long sys_sigaltstack(const stack_t __user *, stack_t __user *); 74 + #define sys_clone sys_clone 75 + #define sys_execve sys_execve 76 + #define sys_rt_sigreturn sys_rt_sigreturn 77 + #define sys_sigaltstack sys_sigaltstack 78 + 65 79 /* These are the intvec*.S trampolines. */ 66 - long _sys_sigaltstack(const stack_t __user *, stack_t __user *); 67 80 long _sys_rt_sigreturn(void); 68 81 long _sys_clone(unsigned long clone_flags, unsigned long newsp, 69 82 void __user *parent_tid, void __user *child_tid); 70 - long _sys_execve(const char __user *filename, 71 - const char __user *const __user *argv, 72 - const char __user *const __user *envp); 73 83 74 84 #include <asm-generic/syscalls.h> 75 85
+1
arch/tile/include/asm/unistd.h
··· 16 16 #define __ARCH_WANT_SYS_LLSEEK 17 17 #endif 18 18 #define __ARCH_WANT_SYS_NEWFSTATAT 19 + #define __ARCH_WANT_SYS_EXECVE 19 20 #include <uapi/asm/unistd.h>
+2 -3
arch/tile/kernel/compat.c
··· 102 102 #define compat_sys_fadvise64_64 sys32_fadvise64_64 103 103 #define compat_sys_readahead sys32_readahead 104 104 105 - /* Call the trampolines to manage pt_regs where necessary. */ 106 - #define compat_sys_execve _compat_sys_execve 107 - #define compat_sys_sigaltstack _compat_sys_sigaltstack 105 + /* Call the assembly trampolines where necessary. */ 108 106 #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn 107 + #undef sys_clone 109 108 #define sys_clone _sys_clone 110 109 111 110 /*
+5 -5
arch/tile/kernel/compat_signal.c
··· 197 197 } 198 198 199 199 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, 200 - struct compat_sigaltstack __user *uoss_ptr, 201 - struct pt_regs *regs) 200 + struct compat_sigaltstack __user *uoss_ptr) 202 201 { 203 202 stack_t uss, uoss; 204 203 int ret; ··· 218 219 set_fs(KERNEL_DS); 219 220 ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL, 220 221 (stack_t __user __force *)&uoss, 221 - (unsigned long)compat_ptr(regs->sp)); 222 + (unsigned long)compat_ptr(current_pt_regs()->sp)); 222 223 set_fs(seg); 223 224 if (ret >= 0 && uoss_ptr) { 224 225 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) || ··· 231 232 } 232 233 233 234 /* The assembly shim for this function arranges to ignore the return value. */ 234 - long compat_sys_rt_sigreturn(struct pt_regs *regs) 235 + long compat_sys_rt_sigreturn(void) 235 236 { 237 + struct pt_regs *regs = current_pt_regs(); 236 238 struct compat_rt_sigframe __user *frame = 237 239 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); 238 240 sigset_t set; ··· 248 248 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 249 249 goto badframe; 250 250 251 - if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) 251 + if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT) 252 252 goto badframe; 253 253 254 254 return 0;
-11
arch/tile/kernel/entry.S
··· 28 28 STD_ENDPROC(current_text_addr) 29 29 30 30 /* 31 - * Implement execve(). The i386 code has a note that forking from kernel 32 - * space results in no copy on write until the execve, so we should be 33 - * careful not to write to the stack here. 34 - */ 35 - STD_ENTRY(kernel_execve) 36 - moveli TREG_SYSCALL_NR_NAME, __NR_execve 37 - swint1 38 - jrp lr 39 - STD_ENDPROC(kernel_execve) 40 - 41 - /* 42 31 * We don't run this function directly, but instead copy it to a page 43 32 * we map into every user process. See vdso_setup(). 44 33 *
+16 -13
arch/tile/kernel/intvec_32.S
··· 1291 1291 } 1292 1292 STD_ENDPROC(ret_from_fork) 1293 1293 1294 + STD_ENTRY(ret_from_kernel_thread) 1295 + jal sim_notify_fork 1296 + jal schedule_tail 1297 + FEEDBACK_REENTER(ret_from_fork) 1298 + { 1299 + move r0, r31 1300 + jalr r30 1301 + } 1302 + FEEDBACK_REENTER(ret_from_kernel_thread) 1303 + { 1304 + movei r30, 0 /* not an NMI */ 1305 + j .Lresume_userspace /* jump into middle of interrupt_return */ 1306 + } 1307 + STD_ENDPROC(ret_from_kernel_thread) 1308 + 1294 1309 /* 1295 1310 * Code for ill interrupt. 1296 1311 */ ··· 1452 1437 panic "Unhandled interrupt %#x: PC %#lx" 1453 1438 STD_ENDPROC(bad_intr) 1454 1439 1455 - /* Put address of pt_regs in reg and jump. */ 1456 - #define PTREGS_SYSCALL(x, reg) \ 1457 - STD_ENTRY(_##x); \ 1458 - { \ 1459 - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ 1460 - j x \ 1461 - }; \ 1462 - STD_ENDPROC(_##x) 1463 - 1464 1440 /* 1465 1441 * Special-case sigreturn to not write r0 to the stack on return. 1466 1442 * This is technically more efficient, but it also avoids difficulties ··· 1467 1461 }; \ 1468 1462 STD_ENDPROC(_##x) 1469 1463 1470 - PTREGS_SYSCALL(sys_execve, r3) 1471 - PTREGS_SYSCALL(sys_sigaltstack, r2) 1472 1464 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) 1473 - PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) 1474 1465 1475 - /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ 1466 + /* Save additional callee-saves to pt_regs and jump to standard function. */ 1476 1467 STD_ENTRY(_sys_clone) 1477 1468 push_extra_callee_saves r4 1478 1469 j sys_clone
+16 -14
arch/tile/kernel/intvec_64.S
··· 1150 1150 } 1151 1151 STD_ENDPROC(ret_from_fork) 1152 1152 1153 + STD_ENTRY(ret_from_kernel_thread) 1154 + jal sim_notify_fork 1155 + jal schedule_tail 1156 + FEEDBACK_REENTER(ret_from_fork) 1157 + { 1158 + move r0, r31 1159 + jalr r30 1160 + } 1161 + FEEDBACK_REENTER(ret_from_kernel_thread) 1162 + { 1163 + movei r30, 0 /* not an NMI */ 1164 + j .Lresume_userspace /* jump into middle of interrupt_return */ 1165 + } 1166 + STD_ENDPROC(ret_from_kernel_thread) 1167 + 1153 1168 /* Various stub interrupt handlers and syscall handlers */ 1154 1169 1155 1170 STD_ENTRY_LOCAL(_kernel_double_fault) ··· 1181 1166 panic "Unhandled interrupt %#x: PC %#lx" 1182 1167 STD_ENDPROC(bad_intr) 1183 1168 1184 - /* Put address of pt_regs in reg and jump. */ 1185 - #define PTREGS_SYSCALL(x, reg) \ 1186 - STD_ENTRY(_##x); \ 1187 - { \ 1188 - PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ 1189 - j x \ 1190 - }; \ 1191 - STD_ENDPROC(_##x) 1192 - 1193 1169 /* 1194 1170 * Special-case sigreturn to not write r0 to the stack on return. 1195 1171 * This is technically more efficient, but it also avoids difficulties ··· 1196 1190 }; \ 1197 1191 STD_ENDPROC(_##x) 1198 1192 1199 - PTREGS_SYSCALL(sys_execve, r3) 1200 - PTREGS_SYSCALL(sys_sigaltstack, r2) 1201 1193 PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) 1202 1194 #ifdef CONFIG_COMPAT 1203 - PTREGS_SYSCALL(compat_sys_execve, r3) 1204 - PTREGS_SYSCALL(compat_sys_sigaltstack, r2) 1205 1195 PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) 1206 1196 #endif 1207 1197 1208 - /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ 1198 + /* Save additional callee-saves to pt_regs and jump to standard function. */ 1209 1199 STD_ENTRY(_sys_clone) 1210 1200 push_extra_callee_saves r4 1211 1201 j sys_clone
+51 -123
arch/tile/kernel/process.c
··· 157 157 static void save_arch_state(struct thread_struct *t); 158 158 159 159 int copy_thread(unsigned long clone_flags, unsigned long sp, 160 - unsigned long stack_size, 161 - struct task_struct *p, struct pt_regs *regs) 160 + unsigned long arg, 161 + struct task_struct *p, struct pt_regs *unused) 162 162 { 163 - struct pt_regs *childregs; 163 + struct pt_regs *childregs = task_pt_regs(p); 164 164 unsigned long ksp; 165 + unsigned long *callee_regs; 165 166 166 167 /* 167 - * When creating a new kernel thread we pass sp as zero. 168 - * Assign it to a reasonable value now that we have the stack. 168 + * Set up the stack and stack pointer appropriately for the 169 + * new child to find itself woken up in __switch_to(). 170 + * The callee-saved registers must be on the stack to be read; 171 + * the new task will then jump to assembly support to handle 172 + * calling schedule_tail(), etc., and (for userspace tasks) 173 + * returning to the context set up in the pt_regs. 169 174 */ 170 - if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) 171 - sp = KSTK_TOP(p); 175 + ksp = (unsigned long) childregs; 176 + ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ 177 + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; 178 + ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); 179 + callee_regs = (unsigned long *)ksp; 180 + ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ 181 + ((long *)ksp)[0] = ((long *)ksp)[1] = 0; 182 + p->thread.ksp = ksp; 183 + 184 + /* Record the pid of the task that created this one. */ 185 + p->thread.creator_pid = current->pid; 186 + 187 + if (unlikely(p->flags & PF_KTHREAD)) { 188 + /* kernel thread */ 189 + memset(childregs, 0, sizeof(struct pt_regs)); 190 + memset(&callee_regs[2], 0, 191 + (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long)); 192 + callee_regs[0] = sp; /* r30 = function */ 193 + callee_regs[1] = arg; /* r31 = arg */ 194 + childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0); 195 + p->thread.pc = (unsigned long) ret_from_kernel_thread; 196 + return 0; 197 + } 198 + 199 + /* 200 + * Start new thread in ret_from_fork so it schedules properly 201 + * and then return from interrupt like the parent. 202 + */ 203 + p->thread.pc = (unsigned long) ret_from_fork; 172 204 173 205 /* 174 206 * Do not clone step state from the parent; each thread ··· 209 177 task_thread_info(p)->step_state = NULL; 210 178 211 179 /* 212 - * Start new thread in ret_from_fork so it schedules properly 213 - * and then return from interrupt like the parent. 214 - */ 215 - p->thread.pc = (unsigned long) ret_from_fork; 216 - 217 - /* Save user stack top pointer so we can ID the stack vm area later. */ 218 - p->thread.usp0 = sp; 219 - 220 - /* Record the pid of the process that created this one. */ 221 - p->thread.creator_pid = current->pid; 222 - 223 - /* 224 180 * Copy the registers onto the kernel stack so the 225 181 * return-from-interrupt code will reload it into registers. 226 182 */ 227 - childregs = task_pt_regs(p); 228 - *childregs = *regs; 183 + *childregs = *current_pt_regs(); 229 184 childregs->regs[0] = 0; /* return value is zero */ 230 - childregs->sp = sp; /* override with new user stack pointer */ 185 + if (sp) 186 + childregs->sp = sp; /* override with new user stack pointer */ 187 + memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG], 188 + CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); 189 + 190 + /* Save user stack top pointer so we can ID the stack vm area later. */ 191 + p->thread.usp0 = childregs->sp; 231 192 232 193 /* 233 194 * If CLONE_SETTLS is set, set "tp" in the new task to "r4", 234 195 * which is passed in as arg #5 to sys_clone(). 235 196 */ 236 197 if (clone_flags & CLONE_SETTLS) 237 - childregs->tp = regs->regs[4]; 198 + childregs->tp = childregs->regs[4]; 238 199 239 - /* 240 - * Copy the callee-saved registers from the passed pt_regs struct 241 - * into the context-switch callee-saved registers area. 242 - * This way when we start the interrupt-return sequence, the 243 - * callee-save registers will be correctly in registers, which 244 - * is how we assume the compiler leaves them as we start doing 245 - * the normal return-from-interrupt path after calling C code. 246 - * Zero out the C ABI save area to mark the top of the stack. 247 - */ 248 - ksp = (unsigned long) childregs; 249 - ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */ 250 - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; 251 - ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long); 252 - memcpy((void *)ksp, &regs->regs[CALLEE_SAVED_FIRST_REG], 253 - CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long)); 254 - ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */ 255 - ((long *)ksp)[0] = ((long *)ksp)[1] = 0; 256 - p->thread.ksp = ksp; 257 200 258 201 #if CHIP_HAS_TILE_DMA() 259 202 /* ··· 585 578 } 586 579 587 580 /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ 588 - SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, 589 - void __user *, parent_tidptr, void __user *, child_tidptr, 590 - struct pt_regs *, regs) 581 + SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp, 582 + void __user *, parent_tidptr, void __user *, child_tidptr) 591 583 { 592 - if (!newsp) 593 - newsp = regs->sp; 594 - return do_fork(clone_flags, newsp, regs, 0, 584 + return do_fork(clone_flags, newsp, current_pt_regs(), 0, 595 585 parent_tidptr, child_tidptr); 596 586 } 597 - 598 - /* 599 - * sys_execve() executes a new program. 600 - */ 601 - SYSCALL_DEFINE4(execve, const char __user *, path, 602 - const char __user *const __user *, argv, 603 - const char __user *const __user *, envp, 604 - struct pt_regs *, regs) 605 - { 606 - long error; 607 - struct filename *filename; 608 - 609 - filename = getname(path); 610 - error = PTR_ERR(filename); 611 - if (IS_ERR(filename)) 612 - goto out; 613 - error = do_execve(filename->name, argv, envp, regs); 614 - putname(filename); 615 - if (error == 0) 616 - single_step_execve(); 617 - out: 618 - return error; 619 - } 620 - 621 - #ifdef CONFIG_COMPAT 622 - long compat_sys_execve(const char __user *path, 623 - compat_uptr_t __user *argv, 624 - compat_uptr_t __user *envp, 625 - struct pt_regs *regs) 626 - { 627 - long error; 628 - struct filename *filename; 629 - 630 - filename = getname(path); 631 - error = PTR_ERR(filename); 632 - if (IS_ERR(filename)) 633 - goto out; 634 - error = compat_do_execve(filename->name, argv, envp, regs); 635 - putname(filename); 636 - if (error == 0) 637 - single_step_execve(); 638 - out: 639 - return error; 640 - } 641 - #endif 642 587 643 588 unsigned long get_wchan(struct task_struct *p) 644 589 { ··· 608 649 609 650 return 0; 610 651 } 611 - 612 - /* 613 - * We pass in lr as zero (cleared in kernel_thread) and the caller 614 - * part of the backtrace ABI on the stack also zeroed (in copy_thread) 615 - * so that backtraces will stop with this function. 616 - * Note that we don't use r0, since copy_thread() clears it. 617 - */ 618 - static void start_kernel_thread(int dummy, int (*fn)(int), int arg) 619 - { 620 - do_exit(fn(arg)); 621 - } 622 - 623 - /* 624 - * Create a kernel thread 625 - */ 626 - int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) 627 - { 628 - struct pt_regs regs; 629 - 630 - memset(&regs, 0, sizeof(regs)); 631 - regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */ 632 - regs.pc = (long) start_kernel_thread; 633 - regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */ 634 - regs.regs[1] = (long) fn; /* function pointer */ 635 - regs.regs[2] = (long) arg; /* parameter register */ 636 - 637 - /* Ok, create the new process.. */ 638 - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 639 - 0, NULL, NULL); 640 - } 641 - EXPORT_SYMBOL(kernel_thread); 642 652 643 653 /* Flush thread state. */ 644 654 void flush_thread(void)
+5 -4
arch/tile/kernel/signal.c
··· 37 37 38 38 #define DEBUG_SIG 0 39 39 40 - SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, 41 - stack_t __user *, uoss, struct pt_regs *, regs) 40 + SYSCALL_DEFINE2(sigaltstack, const stack_t __user *, uss, 41 + stack_t __user *, uoss) 42 42 { 43 - return do_sigaltstack(uss, uoss, regs->sp); 43 + return do_sigaltstack(uss, uoss, current_pt_regs()->sp); 44 44 } 45 45 46 46 ··· 83 83 } 84 84 85 85 /* The assembly shim for this function arranges to ignore the return value. */ 86 - SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) 86 + SYSCALL_DEFINE0(rt_sigreturn) 87 87 { 88 + struct pt_regs *regs = current_pt_regs(); 88 89 struct rt_sigframe __user *frame = 89 90 (struct rt_sigframe __user *)(regs->sp); 90 91 sigset_t set;
+3 -6
arch/tile/kernel/sys.c
··· 106 106 #define sys_readahead sys32_readahead 107 107 #endif 108 108 109 - /* Call the trampolines to manage pt_regs where necessary. */ 110 - #define sys_execve _sys_execve 111 - #define sys_sigaltstack _sys_sigaltstack 109 + /* Call the assembly trampolines where necessary. */ 110 + #undef sys_rt_sigreturn 112 111 #define sys_rt_sigreturn _sys_rt_sigreturn 112 + #undef sys_clone 113 113 #define sys_clone _sys_clone 114 - #ifndef __tilegx__ 115 - #define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr 116 - #endif 117 114 118 115 /* 119 116 * Note that we can't include <linux/unistd.h> here since the header
+3 -2
arch/tile/mm/fault.c
··· 70 70 * Synthesize the fault a PL0 process would get by doing a word-load of 71 71 * an unaligned address or a high kernel address. 72 72 */ 73 - SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address, 74 - struct pt_regs *, regs) 73 + SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address) 75 74 { 75 + struct pt_regs *regs = current_pt_regs(); 76 + 76 77 if (address >= PAGE_OFFSET) 77 78 force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR, 78 79 address, INT_DTLB_MISS, current, regs);
-2
include/linux/compat.h
··· 286 286 287 287 int compat_do_execve(const char *filename, const compat_uptr_t __user *argv, 288 288 const compat_uptr_t __user *envp, struct pt_regs *regs); 289 - #ifdef __ARCH_WANT_SYS_EXECVE 290 289 asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, 291 290 const compat_uptr_t __user *envp); 292 - #endif 293 291 294 292 asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, 295 293 compat_ulong_t __user *outp, compat_ulong_t __user *exp,