diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
commit | 6be325719b3e54624397e413efd4b33a997e55a3 (patch) | |
tree | 57f321a56794cab2222e179b16731e0d76a4a68a /arch/x86/kernel/process.c | |
parent | 26d92f9276a56d55511a427fb70bd70886af647a (diff) | |
parent | 92dcffb916d309aa01778bf8963a6932e4014d07 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'arch/x86/kernel/process.c')
-rw-r--r-- | arch/x86/kernel/process.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 5e2ba634ea15..02c3ee013ccd 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/clockchips.h> | 10 | #include <linux/clockchips.h> |
11 | #include <linux/random.h> | 11 | #include <linux/random.h> |
12 | #include <linux/user-return-notifier.h> | 12 | #include <linux/user-return-notifier.h> |
13 | #include <linux/dmi.h> | ||
14 | #include <linux/utsname.h> | ||
13 | #include <trace/events/power.h> | 15 | #include <trace/events/power.h> |
14 | #include <linux/hw_breakpoint.h> | 16 | #include <linux/hw_breakpoint.h> |
15 | #include <asm/system.h> | 17 | #include <asm/system.h> |
@@ -90,6 +92,25 @@ void exit_thread(void) | |||
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
95 | void show_regs_common(void) | ||
96 | { | ||
97 | const char *board, *product; | ||
98 | |||
99 | board = dmi_get_system_info(DMI_BOARD_NAME); | ||
100 | if (!board) | ||
101 | board = ""; | ||
102 | product = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
103 | if (!product) | ||
104 | product = ""; | ||
105 | |||
106 | printk(KERN_CONT "\n"); | ||
107 | printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n", | ||
108 | current->pid, current->comm, print_tainted(), | ||
109 | init_utsname()->release, | ||
110 | (int)strcspn(init_utsname()->version, " "), | ||
111 | init_utsname()->version, board, product); | ||
112 | } | ||
113 | |||
93 | void flush_thread(void) | 114 | void flush_thread(void) |
94 | { | 115 | { |
95 | struct task_struct *tsk = current; | 116 | struct task_struct *tsk = current; |
@@ -234,6 +255,78 @@ int sys_vfork(struct pt_regs *regs) | |||
234 | NULL, NULL); | 255 | NULL, NULL); |
235 | } | 256 | } |
236 | 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 | #else | ||
292 | regs.ss = __KERNEL_DS; | ||
293 | #endif | ||
294 | |||
295 | regs.orig_ax = -1; | ||
296 | regs.ip = (unsigned long) kernel_thread_helper; | ||
297 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
298 | regs.flags = X86_EFLAGS_IF | 0x2; | ||
299 | |||
300 | /* Ok, create the new process.. */ | ||
301 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
302 | } | ||
303 | EXPORT_SYMBOL(kernel_thread); | ||
304 | |||
305 | /* | ||
306 | * sys_execve() executes a new program. | ||
307 | */ | ||
308 | long sys_execve(char __user *name, char __user * __user *argv, | ||
309 | char __user * __user *envp, struct pt_regs *regs) | ||
310 | { | ||
311 | long error; | ||
312 | char *filename; | ||
313 | |||
314 | filename = getname(name); | ||
315 | error = PTR_ERR(filename); | ||
316 | if (IS_ERR(filename)) | ||
317 | return error; | ||
318 | error = do_execve(filename, argv, envp, regs); | ||
319 | |||
320 | #ifdef CONFIG_X86_32 | ||
321 | if (error == 0) { | ||
322 | /* Make sure we don't return using sysenter.. */ | ||
323 | set_thread_flag(TIF_IRET); | ||
324 | } | ||
325 | #endif | ||
326 | |||
327 | putname(filename); | ||
328 | return error; | ||
329 | } | ||
237 | 330 | ||
238 | /* | 331 | /* |
239 | * Idle related variables and functions | 332 | * Idle related variables and functions |