Loading arch/x86/kernel/entry_64.S +3 −46 Original line number Diff line number Diff line Loading @@ -1166,63 +1166,20 @@ bad_gs: jmp 2b .previous /* * Create a kernel thread. * * C extern interface: * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) * * asm input arguments: * rdi: fn, rsi: arg, rdx: flags */ ENTRY(kernel_thread) CFI_STARTPROC FAKE_STACK_FRAME $child_rip SAVE_ALL # rdi: flags, rsi: usp, rdx: will be &pt_regs movq %rdx,%rdi orq kernel_thread_flags(%rip),%rdi movq $-1, %rsi movq %rsp, %rdx xorl %r8d,%r8d xorl %r9d,%r9d # clone now call do_fork movq %rax,RAX(%rsp) xorl %edi,%edi /* * It isn't worth to check for reschedule here, * so internally to the x86_64 port you can rely on kernel_thread() * not to reschedule the child before returning, this avoids the need * of hacks for example to fork off the per-CPU idle tasks. * [Hopefully no generic code relies on the reschedule -AK] */ RESTORE_ALL UNFAKE_STACK_FRAME ret CFI_ENDPROC END(kernel_thread) ENTRY(child_rip) ENTRY(kernel_thread_helper) pushq $0 # fake return address CFI_STARTPROC /* * Here we are in the child and the registers are set as they were * at kernel_thread() invocation in the parent. */ movq %rdi, %rax movq %rsi, %rdi call *%rax call *%rsi # exit mov %eax, %edi call do_exit ud2 # padding for call trace CFI_ENDPROC END(child_rip) END(kernel_thread_helper) /* * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. Loading arch/x86/kernel/process_64.c +29 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,6 @@ asmlinkage extern void ret_from_fork(void); DEFINE_PER_CPU(unsigned long, old_rsp); static DEFINE_PER_CPU(unsigned char, is_idle); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; static ATOMIC_NOTIFIER_HEAD(idle_notifier); void idle_notifier_register(struct notifier_block *n) Loading Loading @@ -231,6 +229,35 @@ void show_regs(struct pt_regs *regs) show_trace(NULL, regs, (void *)(regs + 1), regs->bp); } /* * This gets run with %si containing the * function to call, and %di containing * the "args". */ extern void kernel_thread_helper(void); /* * 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.si = (unsigned long) fn; regs.di = (unsigned long) arg; regs.orig_ax = -1; regs.ip = (unsigned long) kernel_thread_helper; regs.cs = __KERNEL_CS; regs.flags = X86_EFLAGS_IF; /* Ok, create the new process.. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, ~0UL, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); void release_thread(struct task_struct *dead_task) { if (dead_task->mm) { Loading arch/x86/kernel/x8664_ksyms_64.c +0 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,6 @@ EXPORT_SYMBOL(mcount); #endif EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); Loading Loading
arch/x86/kernel/entry_64.S +3 −46 Original line number Diff line number Diff line Loading @@ -1166,63 +1166,20 @@ bad_gs: jmp 2b .previous /* * Create a kernel thread. * * C extern interface: * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) * * asm input arguments: * rdi: fn, rsi: arg, rdx: flags */ ENTRY(kernel_thread) CFI_STARTPROC FAKE_STACK_FRAME $child_rip SAVE_ALL # rdi: flags, rsi: usp, rdx: will be &pt_regs movq %rdx,%rdi orq kernel_thread_flags(%rip),%rdi movq $-1, %rsi movq %rsp, %rdx xorl %r8d,%r8d xorl %r9d,%r9d # clone now call do_fork movq %rax,RAX(%rsp) xorl %edi,%edi /* * It isn't worth to check for reschedule here, * so internally to the x86_64 port you can rely on kernel_thread() * not to reschedule the child before returning, this avoids the need * of hacks for example to fork off the per-CPU idle tasks. * [Hopefully no generic code relies on the reschedule -AK] */ RESTORE_ALL UNFAKE_STACK_FRAME ret CFI_ENDPROC END(kernel_thread) ENTRY(child_rip) ENTRY(kernel_thread_helper) pushq $0 # fake return address CFI_STARTPROC /* * Here we are in the child and the registers are set as they were * at kernel_thread() invocation in the parent. */ movq %rdi, %rax movq %rsi, %rdi call *%rax call *%rsi # exit mov %eax, %edi call do_exit ud2 # padding for call trace CFI_ENDPROC END(child_rip) END(kernel_thread_helper) /* * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. Loading
arch/x86/kernel/process_64.c +29 −2 Original line number Diff line number Diff line Loading @@ -59,8 +59,6 @@ asmlinkage extern void ret_from_fork(void); DEFINE_PER_CPU(unsigned long, old_rsp); static DEFINE_PER_CPU(unsigned char, is_idle); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; static ATOMIC_NOTIFIER_HEAD(idle_notifier); void idle_notifier_register(struct notifier_block *n) Loading Loading @@ -231,6 +229,35 @@ void show_regs(struct pt_regs *regs) show_trace(NULL, regs, (void *)(regs + 1), regs->bp); } /* * This gets run with %si containing the * function to call, and %di containing * the "args". */ extern void kernel_thread_helper(void); /* * 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.si = (unsigned long) fn; regs.di = (unsigned long) arg; regs.orig_ax = -1; regs.ip = (unsigned long) kernel_thread_helper; regs.cs = __KERNEL_CS; regs.flags = X86_EFLAGS_IF; /* Ok, create the new process.. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, ~0UL, ®s, 0, NULL, NULL); } EXPORT_SYMBOL(kernel_thread); void release_thread(struct task_struct *dead_task) { if (dead_task->mm) { Loading
arch/x86/kernel/x8664_ksyms_64.c +0 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,6 @@ EXPORT_SYMBOL(mcount); #endif EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); Loading