From 287ad220cd8b5a9d29f71c78f6e4051093f051fc Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Sun, 14 Oct 2012 16:19:52 +0200 Subject: openrisc: pass correct arg to schedule_tail schedule_tail() requires that the 'prev' task be passed as an argument to it. This arg is set in _switch, just before 'returning' to one of the ret_* functions where schedule_tail is invoked. Signed-off-by: Jonas Bonn --- arch/openrisc/kernel/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/openrisc/kernel/process.c') diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index c35f3ab1a8d3..ad26d5af2649 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -165,7 +165,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, * the kernel stack. */ kregs->sp = top_of_kernel_stack; - kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */ kregs->gpr[10] = (unsigned long)task_thread_info(p); kregs->gpr[9] = (unsigned long)ret_from_fork; -- cgit From cbf23cf1b96819599f6a1b9658d1bf3a97c6ff15 Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Oct 2012 18:07:44 +0200 Subject: openrisc: use generic kernel_thread/kernel_execve Signed-off-by: Jonas Bonn --- arch/openrisc/Kconfig | 2 + arch/openrisc/kernel/entry.S | 30 +++------ arch/openrisc/kernel/process.c | 138 +++++++++++++++++------------------------ 3 files changed, 68 insertions(+), 102 deletions(-) (limited to 'arch/openrisc/kernel/process.c') diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 05f2ba41ff1a..e7f1a2993f78 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -22,6 +22,8 @@ config OPENRISC select GENERIC_STRNCPY_FROM_USER select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA + select GENERIC_KERNEL_THREAD + select GENERIC_KERNEL_EXECVE config MMU def_bool y diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index 374e63e7c9f6..dce86aef8aba 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -894,6 +894,16 @@ ENTRY(ret_from_fork) l.jal schedule_tail l.nop + /* Check if we are a kernel thread */ + l.sfeqi r20,0 + l.bf 1f + l.nop + + /* ...we are a kernel thread so invoke the requested callback */ + l.jalr r20 + l.or r3,r22,r0 + +1: /* _syscall_returns expect r11 to contain return value */ l.lwz r11,PT_GPR11(r1) @@ -915,26 +925,6 @@ ENTRY(ret_from_fork) l.j _syscall_return l.nop -/* Since syscalls don't save call-clobbered registers, the args to - * kernel_thread_helper will need to be passed through callee-saved - * registers and copied to the parameter registers when the thread - * begins running. - * - * See arch/openrisc/kernel/process.c: - * The args are passed as follows: - * arg1 (r3) : passed in r20 - * arg2 (r4) : passed in r22 - */ - -ENTRY(_kernel_thread_helper) - l.or r3,r20,r0 - l.or r4,r22,r0 - l.movhi r31,hi(kernel_thread_helper) - l.ori r31,r31,lo(kernel_thread_helper) - l.jr r31 - l.nop - - /* ========================================================[ switch ] === */ /* diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index ad26d5af2649..a0f467e438fc 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -109,65 +109,82 @@ void release_thread(struct task_struct *dead_task) */ extern asmlinkage void ret_from_fork(void); +/* + * copy_thread + * @clone_flags: flags + * @usp: user stack pointer or fn for kernel thread + * @arg: arg to fn for kernel thread; always NULL for userspace thread + * @p: the newly created task + * @regs: CPU context to copy for userspace thread; always NULL for kthread + * + * At the top of a newly initialized kernel stack are two stacked pt_reg + * structures. The first (topmost) is the userspace context of the thread. + * The second is the kernelspace context of the thread. + * + * A kernel thread will not be returning to userspace, so the topmost pt_regs + * struct can be uninitialized; it _does_ need to exist, though, because + * a kernel thread can become a userspace thread by doing a kernel_execve, in + * which case the topmost context will be initialized and used for 'returning' + * to userspace. + * + * The second pt_reg struct needs to be initialized to 'return' to + * ret_from_fork. A kernel thread will need to set r20 to the address of + * a function to call into (with arg in r22); userspace threads need to set + * r20 to NULL in which case ret_from_fork will just continue a return to + * userspace. + * + * A kernel thread 'fn' may return; this is effectively what happens when + * kernel_execve is called. In that case, the userspace pt_regs must have + * been initialized (which kernel_execve takes care of, see start_thread + * below); ret_from_fork will then continue its execution causing the + * 'kernel thread' to return to userspace as a userspace thread. + */ + int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long unused, struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p, struct pt_regs *regs) { - struct pt_regs *childregs; + struct pt_regs *userregs; struct pt_regs *kregs; unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - struct thread_info *ti; unsigned long top_of_kernel_stack; top_of_kernel_stack = sp; p->set_child_tid = p->clear_child_tid = NULL; - /* Copy registers */ - /* redzone */ - sp -= STACK_FRAME_OVERHEAD; + /* Locate userspace context on stack... */ + sp -= STACK_FRAME_OVERHEAD; /* redzone */ sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *)sp; + userregs = (struct pt_regs *) sp; - /* Copy parent registers */ - *childregs = *regs; + /* ...and kernel context */ + sp -= STACK_FRAME_OVERHEAD; /* redzone */ + sp -= sizeof(struct pt_regs); + kregs = (struct pt_regs *)sp; - if ((childregs->sr & SPR_SR_SM) == 1) { - /* for kernel thread, set `current_thread_info' - * and stackptr in new task - */ - childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; - childregs->gpr[10] = (unsigned long)task_thread_info(p); + if (unlikely(p->flags & PF_KTHREAD)) { + memset(kregs, 0, sizeof(struct pt_regs)); + kregs->gpr[20] = usp; /* fn, kernel thread */ + kregs->gpr[22] = arg; } else { - childregs->sp = usp; - } - - childregs->gpr[11] = 0; /* Result from fork() */ + *userregs = *regs; - /* - * The way this works is that at some point in the future - * some task will call _switch to switch to the new task. - * That will pop off the stack frame created below and start - * the new task running at ret_from_fork. The new task will - * do some house keeping and then return from the fork or clone - * system call, using the stack frame created above. - */ - /* redzone */ - sp -= STACK_FRAME_OVERHEAD; - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *)sp; + userregs->sp = usp; + userregs->gpr[11] = 0; /* Result from fork() */ - ti = task_thread_info(p); - ti->ksp = sp; + kregs->gpr[20] = 0; /* Userspace thread */ + } - /* kregs->sp must store the location of the 'pre-switch' kernel stack - * pointer... for a newly forked process, this is simply the top of - * the kernel stack. + /* + * _switch wants the kernel stack page in pt_regs->sp so that it + * can restore it to thread_info->ksp... see _switch for details. */ kregs->sp = top_of_kernel_stack; - kregs->gpr[10] = (unsigned long)task_thread_info(p); kregs->gpr[9] = (unsigned long)ret_from_fork; + task_thread_info(p)->ksp = (unsigned long)kregs; + return 0; } @@ -176,16 +193,14 @@ copy_thread(unsigned long clone_flags, unsigned long usp, */ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) { - unsigned long sr = regs->sr & ~SPR_SR_SM; + unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); + memset(regs, 0, sizeof(struct pt_regs)); regs->pc = pc; regs->sr = sr; regs->sp = sp; - -/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/ } /* Fill in the fpu structure for a core dump. */ @@ -236,31 +251,6 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) dest[35] = 0; } -extern void _kernel_thread_helper(void); - -void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg) -{ - do_exit(fn(arg)); -} - -/* - * Create a kernel thread. - */ -int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.gpr[20] = (unsigned long)fn; - regs.gpr[22] = (unsigned long)arg; - regs.sr = mfspr(SPR_SR); - regs.pc = (unsigned long)_kernel_thread_helper; - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, - 0, ®s, 0, NULL, NULL); -} - /* * sys_execve() executes a new program. */ @@ -291,19 +281,3 @@ unsigned long get_wchan(struct task_struct *p) return 0; } - -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register long __res asm("r11") = __NR_execve; - register long __a asm("r3") = (long)(filename); - register long __b asm("r4") = (long)(argv); - register long __c asm("r5") = (long)(envp); - __asm__ volatile ("l.sys 1" - : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c) - : "0"(__res), "1"(__a), "2"(__b), "3"(__c) - : "r6", "r7", "r8", "r12", "r13", "r15", - "r17", "r19", "r21", "r23", "r25", "r27", - "r29", "r31"); - __asm__ volatile ("l.nop"); - return __res; -} -- cgit From a91a2bb1dbd87987645bdb56f49e6a50501b692a Mon Sep 17 00:00:00 2001 From: Jonas Bonn Date: Fri, 19 Oct 2012 18:25:36 +0200 Subject: openrisc: use generic sys_execve Signed-off-by: Jonas Bonn --- arch/openrisc/include/uapi/asm/unistd.h | 2 ++ arch/openrisc/kernel/entry.S | 4 ---- arch/openrisc/kernel/process.c | 24 ------------------------ 3 files changed, 2 insertions(+), 28 deletions(-) (limited to 'arch/openrisc/kernel/process.c') diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 437bdbb61b14..5db7bc0fa5a7 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -20,6 +20,8 @@ #define sys_mmap2 sys_mmap_pgoff +#define __ARCH_WANT_SYS_EXECVE + #include #define __NR_or1k_atomic __NR_arch_specific_syscall diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index dce86aef8aba..c60a09df323f 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -1083,10 +1083,6 @@ ENTRY(sys_fork) l.j _fork_save_extra_regs_and_call l.addi r3,r1,0 -ENTRY(sys_execve) - l.j _sys_execve - l.addi r6,r1,0 - ENTRY(sys_sigaltstack) l.j _sys_sigaltstack l.addi r5,r1,0 diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index a0f467e438fc..e0874b8e09e4 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -251,30 +251,6 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) dest[35] = 0; } -/* - * sys_execve() executes a new program. - */ -asmlinkage long _sys_execve(const char __user *name, - const char __user * const __user *argv, - const char __user * const __user *envp, - struct pt_regs *regs) -{ - int error; - struct filename *filename; - - filename = getname(name); - error = PTR_ERR(filename); - - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename->name, argv, envp, regs); - putname(filename); - -out: - return error; -} - unsigned long get_wchan(struct task_struct *p) { /* TODO */ -- cgit From 39d91a9eafec7524482e70af76ccbe803dce5b8e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 26 Oct 2012 19:37:49 -0400 Subject: openrisc: switch to use of generic fork and clone Signed-off-by: Al Viro --- arch/openrisc/include/asm/syscalls.h | 7 ++++ arch/openrisc/include/uapi/asm/unistd.h | 2 ++ arch/openrisc/kernel/Makefile | 2 +- arch/openrisc/kernel/entry.S | 12 +++---- arch/openrisc/kernel/process.c | 5 +-- arch/openrisc/kernel/sys_or32.c | 57 --------------------------------- 6 files changed, 19 insertions(+), 66 deletions(-) delete mode 100644 arch/openrisc/kernel/sys_or32.c (limited to 'arch/openrisc/kernel/process.c') diff --git a/arch/openrisc/include/asm/syscalls.h b/arch/openrisc/include/asm/syscalls.h index 84a978af44d7..8ee816812a9e 100644 --- a/arch/openrisc/include/asm/syscalls.h +++ b/arch/openrisc/include/asm/syscalls.h @@ -24,4 +24,11 @@ asmlinkage long sys_or1k_atomic(unsigned long type, unsigned long *v1, #include +asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp, + void __user *parent_tid, void __user *child_tid, int tls); +asmlinkage long __sys_fork(void); + +#define sys_clone __sys_clone +#define sys_fork __sys_fork + #endif /* __ASM_OPENRISC_SYSCALLS_H */ diff --git a/arch/openrisc/include/uapi/asm/unistd.h b/arch/openrisc/include/uapi/asm/unistd.h index 5db7bc0fa5a7..5082b8066325 100644 --- a/arch/openrisc/include/uapi/asm/unistd.h +++ b/arch/openrisc/include/uapi/asm/unistd.h @@ -21,6 +21,8 @@ #define sys_mmap2 sys_mmap_pgoff #define __ARCH_WANT_SYS_EXECVE +#define __ARCH_WANT_SYS_FORK +#define __ARCH_WANT_SYS_CLONE #include diff --git a/arch/openrisc/kernel/Makefile b/arch/openrisc/kernel/Makefile index e1ee0fa2bbda..35f92ce51c24 100644 --- a/arch/openrisc/kernel/Makefile +++ b/arch/openrisc/kernel/Makefile @@ -5,7 +5,7 @@ extra-y := head.o vmlinux.lds obj-y := setup.o idle.o or32_ksyms.o process.o dma.o \ - traps.o time.o irq.o entry.o ptrace.o signal.o sys_or32.o \ + traps.o time.o irq.o entry.o ptrace.o signal.o \ sys_call_table.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S index c60a09df323f..5e5b30601bbf 100644 --- a/arch/openrisc/kernel/entry.S +++ b/arch/openrisc/kernel/entry.S @@ -1071,15 +1071,15 @@ _fork_save_extra_regs_and_call: l.jr r29 l.sw PT_GPR28(r1),r28 -ENTRY(sys_clone) - l.movhi r29,hi(_sys_clone) - l.ori r29,r29,lo(_sys_clone) +ENTRY(__sys_clone) + l.movhi r29,hi(sys_clone) + l.ori r29,r29,lo(sys_clone) l.j _fork_save_extra_regs_and_call l.addi r7,r1,0 -ENTRY(sys_fork) - l.movhi r29,hi(_sys_fork) - l.ori r29,r29,lo(_sys_fork) +ENTRY(__sys_fork) + l.movhi r29,hi(sys_fork) + l.ori r29,r29,lo(sys_fork) l.j _fork_save_extra_regs_and_call l.addi r3,r1,0 diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index e0874b8e09e4..6b853668369b 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -168,9 +168,10 @@ copy_thread(unsigned long clone_flags, unsigned long usp, kregs->gpr[20] = usp; /* fn, kernel thread */ kregs->gpr[22] = arg; } else { - *userregs = *regs; + *userregs = *current_pt_regs(); - userregs->sp = usp; + if (usp) + userregs->sp = usp; userregs->gpr[11] = 0; /* Result from fork() */ kregs->gpr[20] = 0; /* Userspace thread */ diff --git a/arch/openrisc/kernel/sys_or32.c b/arch/openrisc/kernel/sys_or32.c deleted file mode 100644 index 57060084c0cc..000000000000 --- a/arch/openrisc/kernel/sys_or32.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * OpenRISC sys_or32.c - * - * Linux architectural port borrowing liberally from similar works of - * others. All original copyrights apply as per the original source - * declaration. - * - * Modifications for the OpenRISC architecture: - * Copyright (C) 2003 Matjaz Breskvar - * Copyright (C) 2010-2011 Jonas Bonn - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * This file contains various random system calls that - * have a non-standard calling sequence on some platforms. - * Since we don't have to do any backwards compatibility, our - * versions are done in the most "normal" way possible. - */ - -#include -#include -#include - -#include - -/* These are secondary entry points as the primary entry points are defined in - * entry.S where we add the 'regs' parameter value - */ - -asmlinkage long _sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tid, int __user *child_tid, - struct pt_regs *regs) -{ - long ret; - - /* FIXME: Is alignment necessary? */ - /* newsp = ALIGN(newsp, 4); */ - - if (!newsp) - newsp = regs->sp; - - ret = do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); - - return ret; -} - -asmlinkage int _sys_fork(struct pt_regs *regs) -{ -#ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); -#else - return -EINVAL; -#endif -} -- cgit From afa86fc426ff7e7f5477f15da9c405d08d5cf790 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 22 Oct 2012 22:51:14 -0400 Subject: flagday: don't pass regs to copy_thread() Signed-off-by: Al Viro --- arch/alpha/kernel/process.c | 2 +- arch/arm/kernel/process.c | 2 +- arch/arm64/kernel/process.c | 3 +-- arch/avr32/kernel/process.c | 2 +- arch/blackfin/kernel/process.c | 6 +++--- arch/c6x/kernel/process.c | 2 +- arch/cris/arch-v10/kernel/process.c | 3 +-- arch/cris/arch-v32/kernel/process.c | 3 +-- arch/frv/kernel/process.c | 2 +- arch/h8300/kernel/process.c | 2 +- arch/hexagon/kernel/process.c | 3 +-- arch/ia64/kernel/process.c | 3 ++- arch/m32r/kernel/process.c | 2 +- arch/m68k/kernel/process.c | 3 +-- arch/microblaze/kernel/process.c | 3 +-- arch/mips/kernel/process.c | 4 ++-- arch/mn10300/kernel/process.c | 2 +- arch/openrisc/kernel/process.c | 2 +- arch/parisc/kernel/process.c | 5 ++--- arch/powerpc/kernel/process.c | 4 ++-- arch/s390/kernel/process.c | 3 +-- arch/score/kernel/process.c | 4 ++-- arch/sh/kernel/process_32.c | 3 +-- arch/sh/kernel/process_64.c | 5 ++--- arch/sparc/kernel/process_32.c | 5 ++--- arch/sparc/kernel/process_64.c | 4 ++-- arch/tile/kernel/process.c | 5 ++--- arch/um/kernel/process.c | 3 +-- arch/unicore32/kernel/process.c | 2 +- arch/x86/kernel/process_32.c | 3 +-- arch/x86/kernel/process_64.c | 3 +-- arch/xtensa/kernel/process.c | 3 +-- include/linux/sched.h | 2 +- kernel/fork.c | 2 +- 34 files changed, 45 insertions(+), 60 deletions(-) (limited to 'arch/openrisc/kernel/process.c') diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index e9705bcc96f9..b5d0d0923699 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -241,7 +241,7 @@ release_thread(struct task_struct *dead_task) int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, - struct task_struct *p, struct pt_regs *wontuse) + struct task_struct *p) { extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 4ab80bbb6d95..9800338c5d1b 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -376,7 +376,7 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, struct pt_regs *unused) + unsigned long stk_sz, struct task_struct *p) { struct thread_info *thread = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 5a1335caf6f1..cb0956bc96ed 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -234,8 +234,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) asmlinkage void ret_from_fork(void) asm("ret_from_fork"); int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, - struct pt_regs *unused) + unsigned long stk_sz, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); unsigned long tls = p->thread.tp_value; diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 03d7aa4a4bc9..fd78f58ea79a 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c @@ -299,7 +299,7 @@ asmlinkage void syscall_return(void); int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index e5ae8fcab438..582276efaaa4 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c @@ -141,14 +141,14 @@ asmlinkage int bfin_clone(unsigned long clone_flags, unsigned long newsp) int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long topstk, - struct task_struct *p, struct pt_regs *regs) + struct task_struct *p) { struct pt_regs *childregs; unsigned long *v; childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1; v = ((unsigned long *)childregs) - 2; - if (unlikely(!regs)) { + if (unlikely(p->flags & PF_KTHREAD)) { memset(childregs, 0, sizeof(struct pt_regs)); v[0] = usp; v[1] = topstk; @@ -157,7 +157,7 @@ copy_thread(unsigned long clone_flags, __asm__ __volatile__("%0 = syscfg;":"=da"(childregs->syscfg):); p->thread.usp = 0; } else { - *childregs = *regs; + *childregs = *current_pt_regs(); childregs->r0 = 0; p->thread.usp = usp ? : rdusp(); v[0] = v[1] = 0; diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c index a3f91895e8b4..6434df476f77 100644 --- a/arch/c6x/kernel/process.c +++ b/arch/c6x/kernel/process.c @@ -139,7 +139,7 @@ void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp) */ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long ustk_size, - struct task_struct *p, struct pt_regs *unused) + struct task_struct *p) { struct pt_regs *childregs; diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index 520547c8b196..b1018750cffb 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c @@ -94,8 +94,7 @@ asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 331e70252df0..2b23ef0e4452 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c @@ -109,8 +109,7 @@ extern asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 0039bf77b192..23916b2a12a2 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -144,7 +144,7 @@ inline unsigned long user_stack(const struct pt_regs *regs) */ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + struct task_struct *p) { struct pt_regs *childregs; diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index b0fb4054aee5..b609f63f1590 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -129,7 +129,7 @@ void flush_thread(void) int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long topstk, - struct task_struct * p, struct pt_regs *unused) + struct task_struct * p) { struct pt_regs * childregs; diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index 36dce17ed25c..06ae9ffcabd5 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c @@ -87,8 +87,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) * Copy architecture-specific thread state */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, - struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct hexagon_switch_stack *ss; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 25543a295ad9..31360cbbd5f8 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -393,12 +393,13 @@ ia64_load_extra (struct task_struct *task) int copy_thread(unsigned long clone_flags, unsigned long user_stack_base, unsigned long user_stack_size, - struct task_struct *p, struct pt_regs *regs) + struct task_struct *p) { extern char ia64_ret_from_clone; struct switch_stack *child_stack, *stack; unsigned long rbs, child_rbs, rbs_size; struct pt_regs *child_ptregs; + struct pt_regs *regs = current_pt_regs(); int retval = 0; child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index c37e9a9a8f27..765d0f57c787 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -192,7 +192,7 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) } int copy_thread(unsigned long clone_flags, unsigned long spu, - unsigned long arg, struct task_struct *tsk, struct pt_regs *unused) + unsigned long arg, struct task_struct *tsk) { struct pt_regs *childregs = task_pt_regs(tsk); extern void ret_from_fork(void); diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index aa9b11000273..9a3df4df73cc 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -154,8 +154,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct * p, struct pt_regs * unused) + unsigned long arg, struct task_struct *p) { struct fork_frame { struct switch_stack sw; diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index a5fed8db7263..40823fd1db0b 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -120,8 +120,7 @@ void flush_thread(void) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); struct thread_info *ti = task_thread_info(p); diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index d13720ac656f..38097652d62d 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -114,10 +114,10 @@ void flush_thread(void) } int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); - struct pt_regs *childregs; + struct pt_regs *childregs, *regs = current_pt_regs(); unsigned long childksp; p->set_child_tid = p->clear_child_tid = NULL; diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 5e0ef396458d..eb09f5a552ff 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -206,7 +206,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) */ int copy_thread(unsigned long clone_flags, unsigned long c_usp, unsigned long ustk_size, - struct task_struct *p, struct pt_regs *unused) + struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct pt_regs *c_regs; diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 6b853668369b..00c233bf0d06 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -142,7 +142,7 @@ extern asmlinkage void ret_from_fork(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct pt_regs *userregs; struct pt_regs *kregs; diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 9753ecf49a06..d13507246c5d 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -204,10 +204,9 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r) int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { - struct pt_regs * cregs = &(p->thread.regs); + struct pt_regs *cregs = &(p->thread.regs); void *stack = task_stack_page(p); /* We have to use void * instead of a function pointer, because diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index a31437567631..81430674e71c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -733,8 +733,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p, - struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); @@ -759,6 +758,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, ti->flags |= _TIF_RESTOREALL; f = ret_from_kernel_thread; } else { + struct pt_regs *regs = current_pt_regs(); CHECK_FULL_REGS(regs); *childregs = *regs; if (usp) diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index e37677796a09..536d64579d9a 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -117,8 +117,7 @@ void release_thread(struct task_struct *dead_task) } int copy_thread(unsigned long clone_flags, unsigned long new_stackp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct thread_info *ti; struct fake_frame diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index f96379a5aee0..79568466b578 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -87,11 +87,11 @@ void flush_thread(void) {} * set up the kernel stack and exception frames for a new process */ int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *regs = current_pt_regs(); p->thread.reg0 = (unsigned long) childregs; if (unlikely(p->flags & PF_KTHREAD)) { diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 1786d16b6c64..73eb66fc6253 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -128,8 +128,7 @@ asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); struct pt_regs *childregs; diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index d5c86a8a3849..e611c85144b1 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -371,10 +371,9 @@ asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { - struct pt_regs *childregs; + struct pt_regs *childregs, *regs = current_pt_regs(); #ifdef CONFIG_SH_FPU /* can't happen for a kernel thread */ diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index bf4c6addce7b..ecde946ef834 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -319,11 +319,10 @@ extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct thread_info *ti = task_thread_info(p); - struct pt_regs *childregs; + struct pt_regs *childregs, *regs = current_pt_regs(); char *new_stack; #ifndef CONFIG_SMP diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index dff54f46728d..58ef19e7e82f 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -622,10 +622,10 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, * Child --> %o0 == parents pid, %o1 == 1 */ int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { struct thread_info *t = task_thread_info(p); + struct pt_regs *regs = current_pt_regs(); struct sparc_stackf *parent_sf; unsigned long child_stack_sz; char *child_trap_frame; diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 267936b51b59..0e5661e7d00d 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c @@ -157,10 +157,9 @@ void arch_release_thread_info(struct thread_info *info) static void save_arch_state(struct thread_struct *t); int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { - struct pt_regs *childregs = task_pt_regs(p); + struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs(); unsigned long ksp; unsigned long *callee_regs; diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index c502c804e8bb..b462b13c5bae 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -161,8 +161,7 @@ void fork_handler(void) } int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, struct task_struct * p, - struct pt_regs *regs) + unsigned long arg, struct task_struct * p) { void (*handler)(void); int kthread = current->flags & PF_KTHREAD; diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c index 79e44e8ae31c..62bad9fed03e 100644 --- a/arch/unicore32/kernel/process.c +++ b/arch/unicore32/kernel/process.c @@ -262,7 +262,7 @@ asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, struct pt_regs *unused) + unsigned long stk_sz, struct task_struct *p) { struct thread_info *thread = task_thread_info(p); struct pt_regs *childregs = task_pt_regs(p); diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 16efa974532b..b5a8905785e6 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -128,8 +128,7 @@ void release_thread(struct task_struct *dead_task) } int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long arg, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); struct task_struct *tsk; diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 74aac76c6e34..6e68a6194965 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -146,8 +146,7 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) } int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, - struct task_struct *p, struct pt_regs *regs) + unsigned long arg, struct task_struct *p) { int err; struct pt_regs *childregs; diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 0036c14739f8..1accf28da5f5 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -199,8 +199,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) */ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, - unsigned long thread_fn_arg, - struct task_struct *p, struct pt_regs *unused) + unsigned long thread_fn_arg, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); diff --git a/include/linux/sched.h b/include/linux/sched.h index c57249782e48..78a2ae3470df 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2271,7 +2271,7 @@ extern void mm_release(struct task_struct *, struct mm_struct *); extern struct mm_struct *dup_mm(struct task_struct *tsk); extern int copy_thread(unsigned long, unsigned long, unsigned long, - struct task_struct *, struct pt_regs *); + struct task_struct *); extern void flush_thread(void); extern void exit_thread(void); diff --git a/kernel/fork.c b/kernel/fork.c index 27a337549dab..d96a562b1311 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1320,7 +1320,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, retval = copy_io(clone_flags, p); if (retval) goto bad_fork_cleanup_namespaces; - retval = copy_thread(clone_flags, stack_start, stack_size, p, regs); + retval = copy_thread(clone_flags, stack_start, stack_size, p); if (retval) goto bad_fork_cleanup_io; -- cgit