diff options
Diffstat (limited to 'arch/x86/kernel/process_64.c')
-rw-r--r-- | arch/x86/kernel/process_64.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ad535b683170..41a26a82470a 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/user.h> | 27 | #include <linux/user.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/utsname.h> | ||
30 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/ptrace.h> | 31 | #include <linux/ptrace.h> |
@@ -38,7 +37,6 @@ | |||
38 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
39 | #include <linux/io.h> | 38 | #include <linux/io.h> |
40 | #include <linux/ftrace.h> | 39 | #include <linux/ftrace.h> |
41 | #include <linux/dmi.h> | ||
42 | 40 | ||
43 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
44 | #include <asm/system.h> | 42 | #include <asm/system.h> |
@@ -52,14 +50,13 @@ | |||
52 | #include <asm/idle.h> | 50 | #include <asm/idle.h> |
53 | #include <asm/syscalls.h> | 51 | #include <asm/syscalls.h> |
54 | #include <asm/ds.h> | 52 | #include <asm/ds.h> |
53 | #include <asm/debugreg.h> | ||
55 | 54 | ||
56 | asmlinkage extern void ret_from_fork(void); | 55 | asmlinkage extern void ret_from_fork(void); |
57 | 56 | ||
58 | DEFINE_PER_CPU(unsigned long, old_rsp); | 57 | DEFINE_PER_CPU(unsigned long, old_rsp); |
59 | static DEFINE_PER_CPU(unsigned char, is_idle); | 58 | static DEFINE_PER_CPU(unsigned char, is_idle); |
60 | 59 | ||
61 | unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; | ||
62 | |||
63 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); | 60 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
64 | 61 | ||
65 | void idle_notifier_register(struct notifier_block *n) | 62 | void idle_notifier_register(struct notifier_block *n) |
@@ -162,31 +159,21 @@ void __show_regs(struct pt_regs *regs, int all) | |||
162 | unsigned long d0, d1, d2, d3, d6, d7; | 159 | unsigned long d0, d1, d2, d3, d6, d7; |
163 | unsigned int fsindex, gsindex; | 160 | unsigned int fsindex, gsindex; |
164 | unsigned int ds, cs, es; | 161 | unsigned int ds, cs, es; |
165 | const char *board; | 162 | |
166 | 163 | show_regs_common(); | |
167 | printk("\n"); | 164 | printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); |
168 | print_modules(); | ||
169 | board = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
170 | if (!board) | ||
171 | board = ""; | ||
172 | printk(KERN_INFO "Pid: %d, comm: %.20s %s %s %.*s %s\n", | ||
173 | current->pid, current->comm, print_tainted(), | ||
174 | init_utsname()->release, | ||
175 | (int)strcspn(init_utsname()->version, " "), | ||
176 | init_utsname()->version, board); | ||
177 | printk(KERN_INFO "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip); | ||
178 | printk_address(regs->ip, 1); | 165 | printk_address(regs->ip, 1); |
179 | printk(KERN_INFO "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, | 166 | printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, |
180 | regs->sp, regs->flags); | 167 | regs->sp, regs->flags); |
181 | printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", | 168 | printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n", |
182 | regs->ax, regs->bx, regs->cx); | 169 | regs->ax, regs->bx, regs->cx); |
183 | printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", | 170 | printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n", |
184 | regs->dx, regs->si, regs->di); | 171 | regs->dx, regs->si, regs->di); |
185 | printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", | 172 | printk(KERN_DEFAULT "RBP: %016lx R08: %016lx R09: %016lx\n", |
186 | regs->bp, regs->r8, regs->r9); | 173 | regs->bp, regs->r8, regs->r9); |
187 | printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", | 174 | printk(KERN_DEFAULT "R10: %016lx R11: %016lx R12: %016lx\n", |
188 | regs->r10, regs->r11, regs->r12); | 175 | regs->r10, regs->r11, regs->r12); |
189 | printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", | 176 | printk(KERN_DEFAULT "R13: %016lx R14: %016lx R15: %016lx\n", |
190 | regs->r13, regs->r14, regs->r15); | 177 | regs->r13, regs->r14, regs->r15); |
191 | 178 | ||
192 | asm("movl %%ds,%0" : "=r" (ds)); | 179 | asm("movl %%ds,%0" : "=r" (ds)); |
@@ -207,27 +194,26 @@ void __show_regs(struct pt_regs *regs, int all) | |||
207 | cr3 = read_cr3(); | 194 | cr3 = read_cr3(); |
208 | cr4 = read_cr4(); | 195 | cr4 = read_cr4(); |
209 | 196 | ||
210 | printk(KERN_INFO "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", | 197 | printk(KERN_DEFAULT "FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", |
211 | fs, fsindex, gs, gsindex, shadowgs); | 198 | fs, fsindex, gs, gsindex, shadowgs); |
212 | printk(KERN_INFO "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, | 199 | printk(KERN_DEFAULT "CS: %04x DS: %04x ES: %04x CR0: %016lx\n", cs, ds, |
213 | es, cr0); | 200 | es, cr0); |
214 | printk(KERN_INFO "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, | 201 | printk(KERN_DEFAULT "CR2: %016lx CR3: %016lx CR4: %016lx\n", cr2, cr3, |
215 | cr4); | 202 | cr4); |
216 | 203 | ||
217 | get_debugreg(d0, 0); | 204 | get_debugreg(d0, 0); |
218 | get_debugreg(d1, 1); | 205 | get_debugreg(d1, 1); |
219 | get_debugreg(d2, 2); | 206 | get_debugreg(d2, 2); |
220 | printk(KERN_INFO "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); | 207 | printk(KERN_DEFAULT "DR0: %016lx DR1: %016lx DR2: %016lx\n", d0, d1, d2); |
221 | get_debugreg(d3, 3); | 208 | get_debugreg(d3, 3); |
222 | get_debugreg(d6, 6); | 209 | get_debugreg(d6, 6); |
223 | get_debugreg(d7, 7); | 210 | get_debugreg(d7, 7); |
224 | printk(KERN_INFO "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); | 211 | printk(KERN_DEFAULT "DR3: %016lx DR6: %016lx DR7: %016lx\n", d3, d6, d7); |
225 | } | 212 | } |
226 | 213 | ||
227 | void show_regs(struct pt_regs *regs) | 214 | void show_regs(struct pt_regs *regs) |
228 | { | 215 | { |
229 | printk(KERN_INFO "CPU %d:", smp_processor_id()); | 216 | show_registers(regs); |
230 | __show_regs(regs, 1); | ||
231 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); | 217 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); |
232 | } | 218 | } |
233 | 219 | ||
@@ -285,8 +271,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
285 | *childregs = *regs; | 271 | *childregs = *regs; |
286 | 272 | ||
287 | childregs->ax = 0; | 273 | childregs->ax = 0; |
288 | childregs->sp = sp; | 274 | if (user_mode(regs)) |
289 | if (sp == ~0UL) | 275 | childregs->sp = sp; |
276 | else | ||
290 | childregs->sp = (unsigned long)childregs; | 277 | childregs->sp = (unsigned long)childregs; |
291 | 278 | ||
292 | p->thread.sp = (unsigned long) childregs; | 279 | p->thread.sp = (unsigned long) childregs; |
@@ -297,12 +284,16 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
297 | 284 | ||
298 | p->thread.fs = me->thread.fs; | 285 | p->thread.fs = me->thread.fs; |
299 | p->thread.gs = me->thread.gs; | 286 | p->thread.gs = me->thread.gs; |
287 | p->thread.io_bitmap_ptr = NULL; | ||
300 | 288 | ||
301 | savesegment(gs, p->thread.gsindex); | 289 | savesegment(gs, p->thread.gsindex); |
302 | savesegment(fs, p->thread.fsindex); | 290 | savesegment(fs, p->thread.fsindex); |
303 | savesegment(es, p->thread.es); | 291 | savesegment(es, p->thread.es); |
304 | savesegment(ds, p->thread.ds); | 292 | savesegment(ds, p->thread.ds); |
305 | 293 | ||
294 | err = -ENOMEM; | ||
295 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
296 | |||
306 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { | 297 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { |
307 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 298 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
308 | if (!p->thread.io_bitmap_ptr) { | 299 | if (!p->thread.io_bitmap_ptr) { |
@@ -341,29 +332,46 @@ out: | |||
341 | kfree(p->thread.io_bitmap_ptr); | 332 | kfree(p->thread.io_bitmap_ptr); |
342 | p->thread.io_bitmap_max = 0; | 333 | p->thread.io_bitmap_max = 0; |
343 | } | 334 | } |
335 | |||
344 | return err; | 336 | return err; |
345 | } | 337 | } |
346 | 338 | ||
347 | void | 339 | static void |
348 | start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | 340 | start_thread_common(struct pt_regs *regs, unsigned long new_ip, |
341 | unsigned long new_sp, | ||
342 | unsigned int _cs, unsigned int _ss, unsigned int _ds) | ||
349 | { | 343 | { |
350 | loadsegment(fs, 0); | 344 | loadsegment(fs, 0); |
351 | loadsegment(es, 0); | 345 | loadsegment(es, _ds); |
352 | loadsegment(ds, 0); | 346 | loadsegment(ds, _ds); |
353 | load_gs_index(0); | 347 | load_gs_index(0); |
354 | regs->ip = new_ip; | 348 | regs->ip = new_ip; |
355 | regs->sp = new_sp; | 349 | regs->sp = new_sp; |
356 | percpu_write(old_rsp, new_sp); | 350 | percpu_write(old_rsp, new_sp); |
357 | regs->cs = __USER_CS; | 351 | regs->cs = _cs; |
358 | regs->ss = __USER_DS; | 352 | regs->ss = _ss; |
359 | regs->flags = 0x200; | 353 | regs->flags = X86_EFLAGS_IF; |
360 | set_fs(USER_DS); | 354 | set_fs(USER_DS); |
361 | /* | 355 | /* |
362 | * Free the old FP and other extended state | 356 | * Free the old FP and other extended state |
363 | */ | 357 | */ |
364 | free_thread_xstate(current); | 358 | free_thread_xstate(current); |
365 | } | 359 | } |
366 | EXPORT_SYMBOL_GPL(start_thread); | 360 | |
361 | void | ||
362 | start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | ||
363 | { | ||
364 | start_thread_common(regs, new_ip, new_sp, | ||
365 | __USER_CS, __USER_DS, 0); | ||
366 | } | ||
367 | |||
368 | #ifdef CONFIG_IA32_EMULATION | ||
369 | void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp) | ||
370 | { | ||
371 | start_thread_common(regs, new_ip, new_sp, | ||
372 | __USER32_CS, __USER32_DS, __USER32_DS); | ||
373 | } | ||
374 | #endif | ||
367 | 375 | ||
368 | /* | 376 | /* |
369 | * switch_to(x,y) should switch tasks from x to y. | 377 | * switch_to(x,y) should switch tasks from x to y. |
@@ -495,26 +503,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
495 | */ | 503 | */ |
496 | if (preload_fpu) | 504 | if (preload_fpu) |
497 | __math_state_restore(); | 505 | __math_state_restore(); |
498 | return prev_p; | ||
499 | } | ||
500 | 506 | ||
501 | /* | 507 | return prev_p; |
502 | * sys_execve() executes a new program. | ||
503 | */ | ||
504 | asmlinkage | ||
505 | long sys_execve(char __user *name, char __user * __user *argv, | ||
506 | char __user * __user *envp, struct pt_regs *regs) | ||
507 | { | ||
508 | long error; | ||
509 | char *filename; | ||
510 | |||
511 | filename = getname(name); | ||
512 | error = PTR_ERR(filename); | ||
513 | if (IS_ERR(filename)) | ||
514 | return error; | ||
515 | error = do_execve(filename, argv, envp, regs); | ||
516 | putname(filename); | ||
517 | return error; | ||
518 | } | 508 | } |
519 | 509 | ||
520 | void set_personality_64bit(void) | 510 | void set_personality_64bit(void) |
@@ -531,13 +521,15 @@ void set_personality_64bit(void) | |||
531 | current->personality &= ~READ_IMPLIES_EXEC; | 521 | current->personality &= ~READ_IMPLIES_EXEC; |
532 | } | 522 | } |
533 | 523 | ||
534 | asmlinkage long | 524 | void set_personality_ia32(void) |
535 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
536 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
537 | { | 525 | { |
538 | if (!newsp) | 526 | /* inherit personality from parent */ |
539 | newsp = regs->sp; | 527 | |
540 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | 528 | /* Make sure to be in 32bit mode */ |
529 | set_thread_flag(TIF_IA32); | ||
530 | |||
531 | /* Prepare the first "return" to user space */ | ||
532 | current_thread_info()->status |= TS_COMPAT; | ||
541 | } | 533 | } |
542 | 534 | ||
543 | unsigned long get_wchan(struct task_struct *p) | 535 | unsigned long get_wchan(struct task_struct *p) |
@@ -664,3 +656,8 @@ long sys_arch_prctl(int code, unsigned long addr) | |||
664 | return do_arch_prctl(current, code, addr); | 656 | return do_arch_prctl(current, code, addr); |
665 | } | 657 | } |
666 | 658 | ||
659 | unsigned long KSTK_ESP(struct task_struct *task) | ||
660 | { | ||
661 | return (test_tsk_thread_flag(task, TIF_IA32)) ? | ||
662 | (task_pt_regs(task)->sp) : ((task)->thread.usersp); | ||
663 | } | ||