diff options
Diffstat (limited to 'arch/x86/kernel/process_64.c')
-rw-r--r-- | arch/x86/kernel/process_64.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 8a6d20ce1978..16c6365e2b86 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
149 | unsigned long unused, | 149 | unsigned long arg, |
150 | struct task_struct *p, struct pt_regs *regs) | 150 | struct task_struct *p, struct pt_regs *regs) |
151 | { | 151 | { |
152 | int err; | 152 | int err; |
153 | struct pt_regs *childregs; | 153 | struct pt_regs *childregs; |
154 | struct task_struct *me = current; | 154 | struct task_struct *me = current; |
155 | 155 | ||
156 | childregs = ((struct pt_regs *) | 156 | p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE; |
157 | (THREAD_SIZE + task_stack_page(p))) - 1; | 157 | childregs = task_pt_regs(p); |
158 | *childregs = *regs; | ||
159 | |||
160 | childregs->ax = 0; | ||
161 | if (user_mode(regs)) | ||
162 | childregs->sp = sp; | ||
163 | else | ||
164 | childregs->sp = (unsigned long)childregs; | ||
165 | |||
166 | p->thread.sp = (unsigned long) childregs; | 158 | p->thread.sp = (unsigned long) childregs; |
167 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
168 | p->thread.usersp = me->thread.usersp; | 159 | p->thread.usersp = me->thread.usersp; |
169 | |||
170 | set_tsk_thread_flag(p, TIF_FORK); | 160 | set_tsk_thread_flag(p, TIF_FORK); |
171 | |||
172 | p->fpu_counter = 0; | 161 | p->fpu_counter = 0; |
173 | p->thread.io_bitmap_ptr = NULL; | 162 | p->thread.io_bitmap_ptr = NULL; |
174 | 163 | ||
@@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
178 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; | 167 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; |
179 | savesegment(es, p->thread.es); | 168 | savesegment(es, p->thread.es); |
180 | savesegment(ds, p->thread.ds); | 169 | savesegment(ds, p->thread.ds); |
170 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
171 | |||
172 | if (unlikely(!regs)) { | ||
173 | /* kernel thread */ | ||
174 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
175 | childregs->sp = (unsigned long)childregs; | ||
176 | childregs->ss = __KERNEL_DS; | ||
177 | childregs->bx = sp; /* function */ | ||
178 | childregs->bp = arg; | ||
179 | childregs->orig_ax = -1; | ||
180 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | ||
181 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
182 | return 0; | ||
183 | } | ||
184 | *childregs = *regs; | ||
185 | |||
186 | childregs->ax = 0; | ||
187 | childregs->sp = sp; | ||
181 | 188 | ||
182 | err = -ENOMEM; | 189 | err = -ENOMEM; |
183 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 190 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |