public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] x86: Merge kernel_thread()
@ 2009-12-09 17:34 Brian Gerst
  2009-12-09 17:34 ` [PATCH 1/5] x86, 64-bit: Move kernel_thread to C Brian Gerst
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

[PATCH 1/5] x86, 64-bit: Move kernel_thread to C
[PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread()
[PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper
[PATCH 4/5] x86: Sync 32/64-bit kernel_thread
[PATCH 5/5] x86: Merge kernel_thread()

 arch/x86/kernel/entry_32.S       |    8 +----
 arch/x86/kernel/entry_64.S       |   49 ++-----------------------------------
 arch/x86/kernel/process.c        |   35 +++++++++++++++++++++++++++
 arch/x86/kernel/process_32.c     |   33 -------------------------
 arch/x86/kernel/process_64.c     |    7 ++---
 arch/x86/kernel/x8664_ksyms_64.c |    2 -
 6 files changed, 43 insertions(+), 91 deletions(-)


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/5] x86, 64-bit: Move kernel_thread to C
  2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
@ 2009-12-09 17:34 ` Brian Gerst
  2009-12-11  0:45   ` [tip:x86/asm] " tip-bot for Brian Gerst
  2009-12-09 17:34 ` [PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread() Brian Gerst
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

Prepare for merging with 32-bit.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
 arch/x86/kernel/entry_64.S       |   49 ++-----------------------------------
 arch/x86/kernel/process_64.c     |   31 ++++++++++++++++++++++-
 arch/x86/kernel/x8664_ksyms_64.c |    2 -
 3 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 63bca79..73d9b2c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -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.
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index c95c8f4..866b4b4 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -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)
@@ -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(&regs, 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, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
 void release_thread(struct task_struct *dead_task)
 {
 	if (dead_task->mm) {
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index a102976..9fafaf8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -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);
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread()
  2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
  2009-12-09 17:34 ` [PATCH 1/5] x86, 64-bit: Move kernel_thread to C Brian Gerst
@ 2009-12-09 17:34 ` Brian Gerst
  2009-12-11  0:45   ` [tip:x86/asm] " tip-bot for Brian Gerst
  2009-12-09 17:34 ` [PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper Brian Gerst
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

Use user_mode() instead of a magic value for sp to determine when returning
to kernel mode.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
 arch/x86/kernel/process_64.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 866b4b4..1d8b03d 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -254,7 +254,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.flags = X86_EFLAGS_IF;
 
 	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, ~0UL, &regs, 0, NULL, NULL);
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 EXPORT_SYMBOL(kernel_thread);
 
@@ -312,8 +312,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	*childregs = *regs;
 
 	childregs->ax = 0;
-	childregs->sp = sp;
-	if (sp == ~0UL)
+	if (user_mode(regs))
+		childregs->sp = sp;
+	else
 		childregs->sp = (unsigned long)childregs;
 
 	p->thread.sp = (unsigned long) childregs;
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper
  2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
  2009-12-09 17:34 ` [PATCH 1/5] x86, 64-bit: Move kernel_thread to C Brian Gerst
  2009-12-09 17:34 ` [PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread() Brian Gerst
@ 2009-12-09 17:34 ` Brian Gerst
  2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst
  2009-12-09 17:34 ` [PATCH 4/5] x86: Sync 32/64-bit kernel_thread Brian Gerst
  2009-12-09 17:34 ` [PATCH 5/5] x86: Merge kernel_thread() Brian Gerst
  4 siblings, 1 reply; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

The arg should be in %eax, but that is clobbered by the return value
of clone.  The function pointer can be in any register.  Also, don't
push args onto the stack, since regparm(3) is the normal calling
convention now.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
 arch/x86/kernel/entry_32.S   |    8 ++------
 arch/x86/kernel/process_32.c |    8 ++++----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 50b9c22..0507b02 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1008,12 +1008,8 @@ END(spurious_interrupt_bug)
 ENTRY(kernel_thread_helper)
 	pushl $0		# fake return address for unwinder
 	CFI_STARTPROC
-	movl %edx,%eax
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
-	call *%ebx
-	push %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	movl %edi,%eax
+	call *%esi
 	call do_exit
 	ud2			# padding for call trace
 	CFI_ENDPROC
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 075580b..ee0d4bc 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -193,8 +193,8 @@ void show_regs(struct pt_regs *regs)
 }
 
 /*
- * This gets run with %bx containing the
- * function to call, and %dx containing
+ * This gets run with %si containing the
+ * function to call, and %di containing
  * the "args".
  */
 extern void kernel_thread_helper(void);
@@ -208,8 +208,8 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 
 	memset(&regs, 0, sizeof(regs));
 
-	regs.bx = (unsigned long) fn;
-	regs.dx = (unsigned long) arg;
+	regs.si = (unsigned long) fn;
+	regs.di = (unsigned long) arg;
 
 	regs.ds = __USER_DS;
 	regs.es = __USER_DS;
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/5] x86: Sync 32/64-bit kernel_thread
  2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
                   ` (2 preceding siblings ...)
  2009-12-09 17:34 ` [PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper Brian Gerst
@ 2009-12-09 17:34 ` Brian Gerst
  2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst
  2009-12-09 17:34 ` [PATCH 5/5] x86: Merge kernel_thread() Brian Gerst
  4 siblings, 1 reply; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
 arch/x86/kernel/process_32.c |    5 ++++-
 arch/x86/kernel/process_64.c |   11 +++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index ee0d4bc..e45aa22 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -211,14 +211,17 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	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;
+#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_SF | X86_EFLAGS_PF | 0x2;
+	regs.flags = X86_EFLAGS_IF | 0x2;
 
 	/* Ok, create the new process.. */
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 1d8b03d..54c9939 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -248,10 +248,17 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	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;
+#endif
+
 	regs.orig_ax = -1;
 	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS;
-	regs.flags = X86_EFLAGS_IF;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | 0x2;
 
 	/* Ok, create the new process.. */
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/5] x86: Merge kernel_thread()
  2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
                   ` (3 preceding siblings ...)
  2009-12-09 17:34 ` [PATCH 4/5] x86: Sync 32/64-bit kernel_thread Brian Gerst
@ 2009-12-09 17:34 ` Brian Gerst
  2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst
  4 siblings, 1 reply; 11+ messages in thread
From: Brian Gerst @ 2009-12-09 17:34 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: x86, linux-kernel

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
 arch/x86/kernel/process.c    |   35 +++++++++++++++++++++++++++++++++++
 arch/x86/kernel/process_32.c |   36 ------------------------------------
 arch/x86/kernel/process_64.c |   36 ------------------------------------
 3 files changed, 35 insertions(+), 72 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 5e2ba63..ac9ac64 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -234,6 +234,41 @@ int sys_vfork(struct pt_regs *regs)
 		       NULL, NULL);
 }
 
+/*
+ * 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;
+#endif
+
+	regs.orig_ax = -1;
+	regs.ip = (unsigned long) kernel_thread_helper;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | 0x2;
+
+	/* Ok, create the new process.. */
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Idle related variables and functions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index e45aa22..af2bf74 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -192,42 +192,6 @@ void show_regs(struct pt_regs *regs)
 	show_trace(NULL, regs, &regs->sp, 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(&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;
-#endif
-
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | 0x2;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void release_thread(struct task_struct *dead_task)
 {
 	BUG_ON(dead_task->mm);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 54c9939..09d3a7b 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -229,42 +229,6 @@ 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(&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;
-#endif
-
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | 0x2;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void release_thread(struct task_struct *dead_task)
 {
 	if (dead_task->mm) {
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip:x86/asm] x86, 64-bit: Move kernel_thread to C
  2009-12-09 17:34 ` [PATCH 1/5] x86, 64-bit: Move kernel_thread to C Brian Gerst
@ 2009-12-11  0:45   ` tip-bot for Brian Gerst
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Brian Gerst @ 2009-12-11  0:45 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, brgerst, tglx

Commit-ID:  3bd95dfb182969dc6d2a317c150e0df7107608d3
Gitweb:     http://git.kernel.org/tip/3bd95dfb182969dc6d2a317c150e0df7107608d3
Author:     Brian Gerst <brgerst@gmail.com>
AuthorDate: Wed, 9 Dec 2009 12:34:40 -0500
Committer:  H. Peter Anvin <hpa@zytor.com>
CommitDate: Thu, 10 Dec 2009 15:55:26 -0800

x86, 64-bit: Move kernel_thread to C

Prepare for merging with 32-bit.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
LKML-Reference: <1260380084-3707-2-git-send-email-brgerst@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
 arch/x86/kernel/entry_64.S       |   49 ++-----------------------------------
 arch/x86/kernel/process_64.c     |   31 ++++++++++++++++++++++-
 arch/x86/kernel/x8664_ksyms_64.c |    2 -
 3 files changed, 32 insertions(+), 50 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 63bca79..73d9b2c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -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.
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 83019f9..92484c2 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -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)
@@ -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(&regs, 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, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
 void release_thread(struct task_struct *dead_task)
 {
 	if (dead_task->mm) {
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index a102976..9fafaf8 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -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);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip:x86/asm] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread()
  2009-12-09 17:34 ` [PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread() Brian Gerst
@ 2009-12-11  0:45   ` tip-bot for Brian Gerst
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Brian Gerst @ 2009-12-11  0:45 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, brgerst, tglx

Commit-ID:  fa4b8f84383ae197e643a46c36bf58ab8dffc95c
Gitweb:     http://git.kernel.org/tip/fa4b8f84383ae197e643a46c36bf58ab8dffc95c
Author:     Brian Gerst <brgerst@gmail.com>
AuthorDate: Wed, 9 Dec 2009 12:34:41 -0500
Committer:  H. Peter Anvin <hpa@zytor.com>
CommitDate: Thu, 10 Dec 2009 15:55:30 -0800

x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread()

Use user_mode() instead of a magic value for sp to determine when returning
to kernel mode.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
LKML-Reference: <1260380084-3707-3-git-send-email-brgerst@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
 arch/x86/kernel/process_64.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 92484c2..00ac66f 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -254,7 +254,7 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	regs.flags = X86_EFLAGS_IF;
 
 	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, ~0UL, &regs, 0, NULL, NULL);
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 EXPORT_SYMBOL(kernel_thread);
 
@@ -312,8 +312,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	*childregs = *regs;
 
 	childregs->ax = 0;
-	childregs->sp = sp;
-	if (sp == ~0UL)
+	if (user_mode(regs))
+		childregs->sp = sp;
+	else
 		childregs->sp = (unsigned long)childregs;
 
 	p->thread.sp = (unsigned long) childregs;

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip:x86/asm] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper
  2009-12-09 17:34 ` [PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper Brian Gerst
@ 2009-12-11  0:46   ` tip-bot for Brian Gerst
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Brian Gerst @ 2009-12-11  0:46 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, brgerst, tglx

Commit-ID:  e840227c141116171c89ab1abb5cc9fee6fdb488
Gitweb:     http://git.kernel.org/tip/e840227c141116171c89ab1abb5cc9fee6fdb488
Author:     Brian Gerst <brgerst@gmail.com>
AuthorDate: Wed, 9 Dec 2009 12:34:42 -0500
Committer:  H. Peter Anvin <hpa@zytor.com>
CommitDate: Thu, 10 Dec 2009 15:55:36 -0800

x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper

The arg should be in %eax, but that is clobbered by the return value
of clone.  The function pointer can be in any register.  Also, don't
push args onto the stack, since regparm(3) is the normal calling
convention now.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
LKML-Reference: <1260380084-3707-4-git-send-email-brgerst@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
 arch/x86/kernel/entry_32.S   |    8 ++------
 arch/x86/kernel/process_32.c |    8 ++++----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index cb12b9b..44a8e0d 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1047,12 +1047,8 @@ END(spurious_interrupt_bug)
 ENTRY(kernel_thread_helper)
 	pushl $0		# fake return address for unwinder
 	CFI_STARTPROC
-	movl %edx,%eax
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
-	call *%ebx
-	push %eax
-	CFI_ADJUST_CFA_OFFSET 4
+	movl %edi,%eax
+	call *%esi
 	call do_exit
 	ud2			# padding for call trace
 	CFI_ENDPROC
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 506d5a7..bd874d2 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -193,8 +193,8 @@ void show_regs(struct pt_regs *regs)
 }
 
 /*
- * This gets run with %bx containing the
- * function to call, and %dx containing
+ * This gets run with %si containing the
+ * function to call, and %di containing
  * the "args".
  */
 extern void kernel_thread_helper(void);
@@ -208,8 +208,8 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 
 	memset(&regs, 0, sizeof(regs));
 
-	regs.bx = (unsigned long) fn;
-	regs.dx = (unsigned long) arg;
+	regs.si = (unsigned long) fn;
+	regs.di = (unsigned long) arg;
 
 	regs.ds = __USER_DS;
 	regs.es = __USER_DS;

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip:x86/asm] x86: Sync 32/64-bit kernel_thread
  2009-12-09 17:34 ` [PATCH 4/5] x86: Sync 32/64-bit kernel_thread Brian Gerst
@ 2009-12-11  0:46   ` tip-bot for Brian Gerst
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Brian Gerst @ 2009-12-11  0:46 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, brgerst, tglx

Commit-ID:  f443ff4201dd25cd4dec183f9919ecba90c8edc2
Gitweb:     http://git.kernel.org/tip/f443ff4201dd25cd4dec183f9919ecba90c8edc2
Author:     Brian Gerst <brgerst@gmail.com>
AuthorDate: Wed, 9 Dec 2009 12:34:43 -0500
Committer:  H. Peter Anvin <hpa@zytor.com>
CommitDate: Thu, 10 Dec 2009 15:55:39 -0800

x86: Sync 32/64-bit kernel_thread

Signed-off-by: Brian Gerst <brgerst@gmail.com>
LKML-Reference: <1260380084-3707-5-git-send-email-brgerst@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
 arch/x86/kernel/process_32.c |    5 ++++-
 arch/x86/kernel/process_64.c |   11 +++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index bd874d2..f2e8b05 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -211,14 +211,17 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	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;
+#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_SF | X86_EFLAGS_PF | 0x2;
+	regs.flags = X86_EFLAGS_IF | 0x2;
 
 	/* Ok, create the new process.. */
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 00ac66f..d49a909 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -248,10 +248,17 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 	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;
+#endif
+
 	regs.orig_ax = -1;
 	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS;
-	regs.flags = X86_EFLAGS_IF;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | 0x2;
 
 	/* Ok, create the new process.. */
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip:x86/asm] x86: Merge kernel_thread()
  2009-12-09 17:34 ` [PATCH 5/5] x86: Merge kernel_thread() Brian Gerst
@ 2009-12-11  0:46   ` tip-bot for Brian Gerst
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Brian Gerst @ 2009-12-11  0:46 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, brgerst, tglx

Commit-ID:  df59e7bf439918f523ac29e996ec1eebbed60440
Gitweb:     http://git.kernel.org/tip/df59e7bf439918f523ac29e996ec1eebbed60440
Author:     Brian Gerst <brgerst@gmail.com>
AuthorDate: Wed, 9 Dec 2009 12:34:44 -0500
Committer:  H. Peter Anvin <hpa@zytor.com>
CommitDate: Thu, 10 Dec 2009 16:41:31 -0800

x86: Merge kernel_thread()

Signed-off-by: Brian Gerst <brgerst@gmail.com>
LKML-Reference: <1260380084-3707-6-git-send-email-brgerst@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
 arch/x86/kernel/process.c    |   35 +++++++++++++++++++++++++++++++++++
 arch/x86/kernel/process_32.c |   36 ------------------------------------
 arch/x86/kernel/process_64.c |   36 ------------------------------------
 3 files changed, 35 insertions(+), 72 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index f3c1a6b..8705cce 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -243,6 +243,41 @@ 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;
+#endif
+
+	regs.orig_ax = -1;
+	regs.ip = (unsigned long) kernel_thread_helper;
+	regs.cs = __KERNEL_CS | get_kernel_rpl();
+	regs.flags = X86_EFLAGS_IF | 0x2;
+
+	/* 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.
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index f2e8b05..ccf2342 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -192,42 +192,6 @@ void show_regs(struct pt_regs *regs)
 	show_trace(NULL, regs, &regs->sp, 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(&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;
-#endif
-
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | 0x2;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void release_thread(struct task_struct *dead_task)
 {
 	BUG_ON(dead_task->mm);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index d49a909..1a362c5 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -229,42 +229,6 @@ 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(&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;
-#endif
-
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | 0x2;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void release_thread(struct task_struct *dead_task)
 {
 	if (dead_task->mm) {

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-12-11  0:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-09 17:34 [PATCH 0/5] x86: Merge kernel_thread() Brian Gerst
2009-12-09 17:34 ` [PATCH 1/5] x86, 64-bit: Move kernel_thread to C Brian Gerst
2009-12-11  0:45   ` [tip:x86/asm] " tip-bot for Brian Gerst
2009-12-09 17:34 ` [PATCH 2/5] x86, 64-bit: Use user_mode() to determine new stack pointer in copy_thread() Brian Gerst
2009-12-11  0:45   ` [tip:x86/asm] " tip-bot for Brian Gerst
2009-12-09 17:34 ` [PATCH 3/5] x86, 32-bit: Use same regs as 64-bit for kernel_thread_helper Brian Gerst
2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst
2009-12-09 17:34 ` [PATCH 4/5] x86: Sync 32/64-bit kernel_thread Brian Gerst
2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst
2009-12-09 17:34 ` [PATCH 5/5] x86: Merge kernel_thread() Brian Gerst
2009-12-11  0:46   ` [tip:x86/asm] " tip-bot for Brian Gerst

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox