···589589} mm_segment_t;590590591591592592-/*593593- * create a kernel thread without removing it from tasklists594594- */595595-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);596596-597592/* Free all resources held by a thread. */598593extern void release_thread(struct task_struct *);599594
+10-5
arch/x86/kernel/entry_32.S
···994994 */995995 .popsection996996997997-ENTRY(kernel_thread_helper)998998- pushl $0 # fake return address for unwinder997997+ENTRY(ret_from_kernel_thread)999998 CFI_STARTPROC10001000- movl %edi,%eax10011001- call *%esi999999+ pushl_cfi %eax10001000+ call schedule_tail10011001+ GET_THREAD_INFO(%ebp)10021002+ popl_cfi %eax10031003+ pushl_cfi $0x0202 # Reset kernel eflags10041004+ popfl_cfi10051005+ movl PT_EBP(%esp),%eax10061006+ call *PT_EBX(%esp)10021007 call do_exit10031008 ud2 # padding for call trace10041009 CFI_ENDPROC10051005-ENDPROC(kernel_thread_helper)10101010+ENDPROC(ret_from_kernel_thread)1006101110071012#ifdef CONFIG_XEN10081013/* Xen doesn't set %esp to be precisely what the normal sysenter
+11-16
arch/x86/kernel/entry_64.S
···450450 RESTORE_REST451451452452 testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread?453453- jz retint_restore_args453453+ jz 1f454454455455 testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET456456 jnz int_ret_from_sys_call457457458458 RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET459459 jmp ret_from_sys_call # go to the SYSRET fastpath460460+461461+1:462462+ subq $REST_SKIP, %rsp # move the stack pointer back463463+ CFI_ADJUST_CFA_OFFSET REST_SKIP464464+ movq %rbp, %rdi465465+ call *%rbx466466+ # exit467467+ mov %eax, %edi468468+ call do_exit469469+ ud2 # padding for call trace460470461471 CFI_ENDPROC462472END(ret_from_fork)···12151205 movl %eax,%gs12161206 jmp 2b12171207 .previous12181218-12191219-ENTRY(kernel_thread_helper)12201220- pushq $0 # fake return address12211221- CFI_STARTPROC12221222- /*12231223- * Here we are in the child and the registers are set as they were12241224- * at kernel_thread() invocation in the parent.12251225- */12261226- call *%rsi12271227- # exit12281228- mov %eax, %edi12291229- call do_exit12301230- ud2 # padding for call trace12311231- CFI_ENDPROC12321232-END(kernel_thread_helper)1233120812341209/*12351210 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
-38
arch/x86/kernel/process.c
···299299}300300301301/*302302- * This gets run with %si containing the303303- * function to call, and %di containing304304- * the "args".305305- */306306-extern void kernel_thread_helper(void);307307-308308-/*309309- * Create a kernel thread310310- */311311-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)312312-{313313- struct pt_regs regs;314314-315315- memset(®s, 0, sizeof(regs));316316-317317- regs.si = (unsigned long) fn;318318- regs.di = (unsigned long) arg;319319-320320-#ifdef CONFIG_X86_32321321- regs.ds = __USER_DS;322322- regs.es = __USER_DS;323323- regs.fs = __KERNEL_PERCPU;324324- regs.gs = __KERNEL_STACK_CANARY;325325-#else326326- regs.ss = __KERNEL_DS;327327-#endif328328-329329- regs.orig_ax = -1;330330- regs.ip = (unsigned long) kernel_thread_helper;331331- regs.cs = __KERNEL_CS | get_kernel_rpl();332332- regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;333333-334334- /* Ok, create the new process.. */335335- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);336336-}337337-EXPORT_SYMBOL(kernel_thread);338338-339339-/*340302 * sys_execve() executes a new program.341303 */342304long sys_execve(const char __user *name,