aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/process_32.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-09-10 16:44:54 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-30 22:53:31 -0400
commit7076aada1040de4ed79a5977dbabdb5e5ea5e249 (patch)
treedfcf480d21cd714a1cc42f38417c427d06526f5a /arch/x86/kernel/process_32.c
parent44f4b56b54d2ab5d06c1726f2cde8ca15c8fac47 (diff)
x86: split ret_from_fork
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r--arch/x86/kernel/process_32.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 75fcad146def..c9939875d267 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -57,6 +57,7 @@
57#include <asm/switch_to.h> 57#include <asm/switch_to.h>
58 58
59asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 59asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
60asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
60 61
61/* 62/*
62 * Return saved PC of a blocked thread. 63 * Return saved PC of a blocked thread.
@@ -127,23 +128,39 @@ void release_thread(struct task_struct *dead_task)
127} 128}
128 129
129int copy_thread(unsigned long clone_flags, unsigned long sp, 130int copy_thread(unsigned long clone_flags, unsigned long sp,
130 unsigned long unused, 131 unsigned long arg,
131 struct task_struct *p, struct pt_regs *regs) 132 struct task_struct *p, struct pt_regs *regs)
132{ 133{
133 struct pt_regs *childregs; 134 struct pt_regs *childregs = task_pt_regs(p);
134 struct task_struct *tsk; 135 struct task_struct *tsk;
135 int err; 136 int err;
136 137
137 childregs = task_pt_regs(p); 138 p->thread.sp = (unsigned long) childregs;
139 p->thread.sp0 = (unsigned long) (childregs+1);
140
141 if (unlikely(!regs)) {
142 /* kernel thread */
143 memset(childregs, 0, sizeof(struct pt_regs));
144 p->thread.ip = (unsigned long) ret_from_kernel_thread;
145 task_user_gs(p) = __KERNEL_STACK_CANARY;
146 childregs->ds = __USER_DS;
147 childregs->es = __USER_DS;
148 childregs->fs = __KERNEL_PERCPU;
149 childregs->bx = sp; /* function */
150 childregs->bp = arg;
151 childregs->orig_ax = -1;
152 childregs->cs = __KERNEL_CS | get_kernel_rpl();
153 childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
154 p->fpu_counter = 0;
155 p->thread.io_bitmap_ptr = NULL;
156 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
157 return 0;
158 }
138 *childregs = *regs; 159 *childregs = *regs;
139 childregs->ax = 0; 160 childregs->ax = 0;
140 childregs->sp = sp; 161 childregs->sp = sp;
141 162
142 p->thread.sp = (unsigned long) childregs;
143 p->thread.sp0 = (unsigned long) (childregs+1);
144
145 p->thread.ip = (unsigned long) ret_from_fork; 163 p->thread.ip = (unsigned long) ret_from_fork;
146
147 task_user_gs(p) = get_user_gs(regs); 164 task_user_gs(p) = get_user_gs(regs);
148 165
149 p->fpu_counter = 0; 166 p->fpu_counter = 0;