diff options
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 |
