diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-12-15 14:33:22 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-15 14:33:28 -0500 |
commit | ab1eebe77dd08b26585860d534e07810d1cd274d (patch) | |
tree | 92b1ff0952cbdeef34922c43ff7eaac2162e77c4 /arch/x86/kernel/process.c | |
parent | 186a25026c44d1bfa97671110ff14dcd0c99678e (diff) | |
parent | df59e7bf439918f523ac29e996ec1eebbed60440 (diff) |
Merge branch 'x86/asm' into x86/urgent
Merge reason: it's stable so lets push it upstream.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/process.c')
-rw-r--r-- | arch/x86/kernel/process.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 7a7bd4e3ec49..98c2cdeb599e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -255,6 +255,76 @@ int sys_vfork(struct pt_regs *regs) | |||
255 | NULL, NULL); | 255 | NULL, NULL); |
256 | } | 256 | } |
257 | 257 | ||
258 | long | ||
259 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
260 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
261 | { | ||
262 | if (!newsp) | ||
263 | newsp = regs->sp; | ||
264 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * This gets run with %si containing the | ||
269 | * function to call, and %di containing | ||
270 | * the "args". | ||
271 | */ | ||
272 | extern void kernel_thread_helper(void); | ||
273 | |||
274 | /* | ||
275 | * Create a kernel thread | ||
276 | */ | ||
277 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
278 | { | ||
279 | struct pt_regs regs; | ||
280 | |||
281 | memset(®s, 0, sizeof(regs)); | ||
282 | |||
283 | regs.si = (unsigned long) fn; | ||
284 | regs.di = (unsigned long) arg; | ||
285 | |||
286 | #ifdef CONFIG_X86_32 | ||
287 | regs.ds = __USER_DS; | ||
288 | regs.es = __USER_DS; | ||
289 | regs.fs = __KERNEL_PERCPU; | ||
290 | regs.gs = __KERNEL_STACK_CANARY; | ||
291 | #endif | ||
292 | |||
293 | regs.orig_ax = -1; | ||
294 | regs.ip = (unsigned long) kernel_thread_helper; | ||
295 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
296 | regs.flags = X86_EFLAGS_IF | 0x2; | ||
297 | |||
298 | /* Ok, create the new process.. */ | ||
299 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
300 | } | ||
301 | EXPORT_SYMBOL(kernel_thread); | ||
302 | |||
303 | /* | ||
304 | * sys_execve() executes a new program. | ||
305 | */ | ||
306 | long sys_execve(char __user *name, char __user * __user *argv, | ||
307 | char __user * __user *envp, struct pt_regs *regs) | ||
308 | { | ||
309 | long error; | ||
310 | char *filename; | ||
311 | |||
312 | filename = getname(name); | ||
313 | error = PTR_ERR(filename); | ||
314 | if (IS_ERR(filename)) | ||
315 | return error; | ||
316 | error = do_execve(filename, argv, envp, regs); | ||
317 | |||
318 | #ifdef CONFIG_X86_32 | ||
319 | if (error == 0) { | ||
320 | /* Make sure we don't return using sysenter.. */ | ||
321 | set_thread_flag(TIF_IRET); | ||
322 | } | ||
323 | #endif | ||
324 | |||
325 | putname(filename); | ||
326 | return error; | ||
327 | } | ||
258 | 328 | ||
259 | /* | 329 | /* |
260 | * Idle related variables and functions | 330 | * Idle related variables and functions |