Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7076aada authored by Al Viro's avatar Al Viro
Browse files

x86: split ret_from_fork



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 44f4b56b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ config X86
	select KTIME_SCALAR if X86_32
	select GENERIC_STRNCPY_FROM_USER
	select GENERIC_STRNLEN_USER
	select GENERIC_KERNEL_THREAD

config INSTRUCTION_DECODER
	def_bool (KPROBES || PERF_EVENTS || UPROBES)
+0 −5
Original line number Diff line number Diff line
@@ -589,11 +589,6 @@ typedef struct {
} mm_segment_t;


/*
 * create a kernel thread without removing it from tasklists
 */
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);

+10 −5
Original line number Diff line number Diff line
@@ -994,15 +994,20 @@ END(spurious_interrupt_bug)
 */
	.popsection

ENTRY(kernel_thread_helper)
	pushl $0		# fake return address for unwinder
ENTRY(ret_from_kernel_thread)
	CFI_STARTPROC
	movl %edi,%eax
	call *%esi
	pushl_cfi %eax
	call schedule_tail
	GET_THREAD_INFO(%ebp)
	popl_cfi %eax
	pushl_cfi $0x0202		# Reset kernel eflags
	popfl_cfi
	movl PT_EBP(%esp),%eax
	call *PT_EBX(%esp)
	call do_exit
	ud2			# padding for call trace
	CFI_ENDPROC
ENDPROC(kernel_thread_helper)
ENDPROC(ret_from_kernel_thread)

#ifdef CONFIG_XEN
/* Xen doesn't set %esp to be precisely what the normal sysenter
+11 −16
Original line number Diff line number Diff line
@@ -450,7 +450,7 @@ ENTRY(ret_from_fork)
	RESTORE_REST

	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
	jz   retint_restore_args
	jz   1f

	testl $_TIF_IA32, TI_flags(%rcx)	# 32-bit compat task needs IRET
	jnz  int_ret_from_sys_call
@@ -458,6 +458,16 @@ ENTRY(ret_from_fork)
	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
	jmp ret_from_sys_call			# go to the SYSRET fastpath

1:
	subq $REST_SKIP, %rsp	# move the stack pointer back
	CFI_ADJUST_CFA_OFFSET	REST_SKIP
	movq %rbp, %rdi
	call *%rbx
	# exit
	mov %eax, %edi
	call do_exit
	ud2			# padding for call trace

	CFI_ENDPROC
END(ret_from_fork)

@@ -1206,21 +1216,6 @@ bad_gs:
	jmp  2b
	.previous

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.
	 */
	call *%rsi
	# exit
	mov %eax, %edi
	call do_exit
	ud2			# padding for call trace
	CFI_ENDPROC
END(kernel_thread_helper)

/*
 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
 *
+0 −38
Original line number Diff line number Diff line
@@ -298,44 +298,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
}

/*
 * 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(&regs, 0, sizeof(regs));

	regs.si = (unsigned long) fn;
	regs.di = (unsigned long) arg;

#ifdef CONFIG_X86_32
	regs.ds = __USER_DS;
	regs.es = __USER_DS;
	regs.fs = __KERNEL_PERCPU;
	regs.gs = __KERNEL_STACK_CANARY;
#else
	regs.ss = __KERNEL_DS;
#endif

	regs.orig_ax = -1;
	regs.ip = (unsigned long) kernel_thread_helper;
	regs.cs = __KERNEL_CS | get_kernel_rpl();
	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;

	/* Ok, create the new process.. */
	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);

/*
 * sys_execve() executes a new program.
 */
Loading