aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/entry_64.S
diff options
context:
space:
mode:
authorBrian Gerst <brgerst@gmail.com>2009-12-09 12:34:40 -0500
committerH. Peter Anvin <hpa@zytor.com>2009-12-10 18:55:26 -0500
commit3bd95dfb182969dc6d2a317c150e0df7107608d3 (patch)
tree8624969693d1bb51f06f85c35b7ac84ef41b9aeb /arch/x86/kernel/entry_64.S
parentfc380ceed7fe469728ea4acdbda4495ea943ee1c (diff)
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>
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r--arch/x86/kernel/entry_64.S49
1 files changed, 3 insertions, 46 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 63bca794c8f..73d9b2c0e21 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1166,63 +1166,20 @@ bad_gs:
1166 jmp 2b 1166 jmp 2b
1167 .previous 1167 .previous
1168 1168
1169/* 1169ENTRY(kernel_thread_helper)
1170 * Create a kernel thread.
1171 *
1172 * C extern interface:
1173 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
1174 *
1175 * asm input arguments:
1176 * rdi: fn, rsi: arg, rdx: flags
1177 */
1178ENTRY(kernel_thread)
1179 CFI_STARTPROC
1180 FAKE_STACK_FRAME $child_rip
1181 SAVE_ALL
1182
1183 # rdi: flags, rsi: usp, rdx: will be &pt_regs
1184 movq %rdx,%rdi
1185 orq kernel_thread_flags(%rip),%rdi
1186 movq $-1, %rsi
1187 movq %rsp, %rdx
1188
1189 xorl %r8d,%r8d
1190 xorl %r9d,%r9d
1191
1192 # clone now
1193 call do_fork
1194 movq %rax,RAX(%rsp)
1195 xorl %edi,%edi
1196
1197 /*
1198 * It isn't worth to check for reschedule here,
1199 * so internally to the x86_64 port you can rely on kernel_thread()
1200 * not to reschedule the child before returning, this avoids the need
1201 * of hacks for example to fork off the per-CPU idle tasks.
1202 * [Hopefully no generic code relies on the reschedule -AK]
1203 */
1204 RESTORE_ALL
1205 UNFAKE_STACK_FRAME
1206 ret
1207 CFI_ENDPROC
1208END(kernel_thread)
1209
1210ENTRY(child_rip)
1211 pushq $0 # fake return address 1170 pushq $0 # fake return address
1212 CFI_STARTPROC 1171 CFI_STARTPROC
1213 /* 1172 /*
1214 * Here we are in the child and the registers are set as they were 1173 * Here we are in the child and the registers are set as they were
1215 * at kernel_thread() invocation in the parent. 1174 * at kernel_thread() invocation in the parent.
1216 */ 1175 */
1217 movq %rdi, %rax 1176 call *%rsi
1218 movq %rsi, %rdi
1219 call *%rax
1220 # exit 1177 # exit
1221 mov %eax, %edi 1178 mov %eax, %edi
1222 call do_exit 1179 call do_exit
1223 ud2 # padding for call trace 1180 ud2 # padding for call trace
1224 CFI_ENDPROC 1181 CFI_ENDPROC
1225END(child_rip) 1182END(kernel_thread_helper)
1226 1183
1227/* 1184/*
1228 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. 1185 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.