|
@@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
|
|
}
|
|
}
|
|
|
|
|
|
int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|
int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|
- unsigned long unused,
|
|
|
|
|
|
+ unsigned long arg,
|
|
struct task_struct *p, struct pt_regs *regs)
|
|
struct task_struct *p, struct pt_regs *regs)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
struct pt_regs *childregs;
|
|
struct pt_regs *childregs;
|
|
struct task_struct *me = current;
|
|
struct task_struct *me = current;
|
|
|
|
|
|
- childregs = ((struct pt_regs *)
|
|
|
|
- (THREAD_SIZE + task_stack_page(p))) - 1;
|
|
|
|
- *childregs = *regs;
|
|
|
|
-
|
|
|
|
- childregs->ax = 0;
|
|
|
|
- if (user_mode(regs))
|
|
|
|
- childregs->sp = sp;
|
|
|
|
- else
|
|
|
|
- childregs->sp = (unsigned long)childregs;
|
|
|
|
-
|
|
|
|
|
|
+ p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE;
|
|
|
|
+ childregs = task_pt_regs(p);
|
|
p->thread.sp = (unsigned long) childregs;
|
|
p->thread.sp = (unsigned long) childregs;
|
|
- p->thread.sp0 = (unsigned long) (childregs+1);
|
|
|
|
p->thread.usersp = me->thread.usersp;
|
|
p->thread.usersp = me->thread.usersp;
|
|
-
|
|
|
|
set_tsk_thread_flag(p, TIF_FORK);
|
|
set_tsk_thread_flag(p, TIF_FORK);
|
|
-
|
|
|
|
p->fpu_counter = 0;
|
|
p->fpu_counter = 0;
|
|
p->thread.io_bitmap_ptr = NULL;
|
|
p->thread.io_bitmap_ptr = NULL;
|
|
|
|
|
|
@@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|
p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
|
|
p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
|
|
savesegment(es, p->thread.es);
|
|
savesegment(es, p->thread.es);
|
|
savesegment(ds, p->thread.ds);
|
|
savesegment(ds, p->thread.ds);
|
|
|
|
+ memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
|
|
|
|
+
|
|
|
|
+ if (unlikely(!regs)) {
|
|
|
|
+ /* kernel thread */
|
|
|
|
+ memset(childregs, 0, sizeof(struct pt_regs));
|
|
|
|
+ childregs->sp = (unsigned long)childregs;
|
|
|
|
+ childregs->ss = __KERNEL_DS;
|
|
|
|
+ childregs->bx = sp; /* function */
|
|
|
|
+ childregs->bp = arg;
|
|
|
|
+ childregs->orig_ax = -1;
|
|
|
|
+ childregs->cs = __KERNEL_CS | get_kernel_rpl();
|
|
|
|
+ childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ *childregs = *regs;
|
|
|
|
+
|
|
|
|
+ childregs->ax = 0;
|
|
|
|
+ childregs->sp = sp;
|
|
|
|
|
|
err = -ENOMEM;
|
|
err = -ENOMEM;
|
|
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
|
|
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
|