diff options
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 110 |
1 files changed, 71 insertions, 39 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index bb6745d13b8f..458006ae19f3 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -80,25 +80,25 @@ void idle_notifier_unregister(struct notifier_block *n) | |||
80 | } | 80 | } |
81 | EXPORT_SYMBOL(idle_notifier_unregister); | 81 | EXPORT_SYMBOL(idle_notifier_unregister); |
82 | 82 | ||
83 | enum idle_state { CPU_IDLE, CPU_NOT_IDLE }; | ||
84 | static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE; | ||
85 | |||
86 | void enter_idle(void) | 83 | void enter_idle(void) |
87 | { | 84 | { |
88 | __get_cpu_var(idle_state) = CPU_IDLE; | 85 | write_pda(isidle, 1); |
89 | atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); | 86 | atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); |
90 | } | 87 | } |
91 | 88 | ||
92 | static void __exit_idle(void) | 89 | static void __exit_idle(void) |
93 | { | 90 | { |
94 | __get_cpu_var(idle_state) = CPU_NOT_IDLE; | 91 | if (read_pda(isidle) == 0) |
92 | return; | ||
93 | write_pda(isidle, 0); | ||
95 | atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); | 94 | atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); |
96 | } | 95 | } |
97 | 96 | ||
98 | /* Called from interrupts to signify idle end */ | 97 | /* Called from interrupts to signify idle end */ |
99 | void exit_idle(void) | 98 | void exit_idle(void) |
100 | { | 99 | { |
101 | if (current->pid | read_pda(irqcount)) | 100 | /* idle loop has pid 0 */ |
101 | if (current->pid) | ||
102 | return; | 102 | return; |
103 | __exit_idle(); | 103 | __exit_idle(); |
104 | } | 104 | } |
@@ -220,6 +220,9 @@ void cpu_idle (void) | |||
220 | play_dead(); | 220 | play_dead(); |
221 | enter_idle(); | 221 | enter_idle(); |
222 | idle(); | 222 | idle(); |
223 | /* In many cases the interrupt that ended idle | ||
224 | has already called exit_idle. But some idle | ||
225 | loops can be woken up without interrupt. */ | ||
223 | __exit_idle(); | 226 | __exit_idle(); |
224 | } | 227 | } |
225 | 228 | ||
@@ -350,6 +353,7 @@ void exit_thread(void) | |||
350 | 353 | ||
351 | kfree(t->io_bitmap_ptr); | 354 | kfree(t->io_bitmap_ptr); |
352 | t->io_bitmap_ptr = NULL; | 355 | t->io_bitmap_ptr = NULL; |
356 | clear_thread_flag(TIF_IO_BITMAP); | ||
353 | /* | 357 | /* |
354 | * Careful, clear this in the TSS too: | 358 | * Careful, clear this in the TSS too: |
355 | */ | 359 | */ |
@@ -369,6 +373,7 @@ void flush_thread(void) | |||
369 | if (t->flags & _TIF_IA32) | 373 | if (t->flags & _TIF_IA32) |
370 | current_thread_info()->status |= TS_COMPAT; | 374 | current_thread_info()->status |= TS_COMPAT; |
371 | } | 375 | } |
376 | t->flags &= ~_TIF_DEBUG; | ||
372 | 377 | ||
373 | tsk->thread.debugreg0 = 0; | 378 | tsk->thread.debugreg0 = 0; |
374 | tsk->thread.debugreg1 = 0; | 379 | tsk->thread.debugreg1 = 0; |
@@ -461,7 +466,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
461 | asm("mov %%es,%0" : "=m" (p->thread.es)); | 466 | asm("mov %%es,%0" : "=m" (p->thread.es)); |
462 | asm("mov %%ds,%0" : "=m" (p->thread.ds)); | 467 | asm("mov %%ds,%0" : "=m" (p->thread.ds)); |
463 | 468 | ||
464 | if (unlikely(me->thread.io_bitmap_ptr != NULL)) { | 469 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { |
465 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 470 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
466 | if (!p->thread.io_bitmap_ptr) { | 471 | if (!p->thread.io_bitmap_ptr) { |
467 | p->thread.io_bitmap_max = 0; | 472 | p->thread.io_bitmap_max = 0; |
@@ -469,6 +474,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
469 | } | 474 | } |
470 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, | 475 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, |
471 | IO_BITMAP_BYTES); | 476 | IO_BITMAP_BYTES); |
477 | set_tsk_thread_flag(p, TIF_IO_BITMAP); | ||
472 | } | 478 | } |
473 | 479 | ||
474 | /* | 480 | /* |
@@ -498,6 +504,40 @@ out: | |||
498 | */ | 504 | */ |
499 | #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r) | 505 | #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r) |
500 | 506 | ||
507 | static inline void __switch_to_xtra(struct task_struct *prev_p, | ||
508 | struct task_struct *next_p, | ||
509 | struct tss_struct *tss) | ||
510 | { | ||
511 | struct thread_struct *prev, *next; | ||
512 | |||
513 | prev = &prev_p->thread, | ||
514 | next = &next_p->thread; | ||
515 | |||
516 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
517 | loaddebug(next, 0); | ||
518 | loaddebug(next, 1); | ||
519 | loaddebug(next, 2); | ||
520 | loaddebug(next, 3); | ||
521 | /* no 4 and 5 */ | ||
522 | loaddebug(next, 6); | ||
523 | loaddebug(next, 7); | ||
524 | } | ||
525 | |||
526 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
527 | /* | ||
528 | * Copy the relevant range of the IO bitmap. | ||
529 | * Normally this is 128 bytes or less: | ||
530 | */ | ||
531 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
532 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
533 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { | ||
534 | /* | ||
535 | * Clear any possible leftover bits: | ||
536 | */ | ||
537 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
538 | } | ||
539 | } | ||
540 | |||
501 | /* | 541 | /* |
502 | * switch_to(x,y) should switch tasks from x to y. | 542 | * switch_to(x,y) should switch tasks from x to y. |
503 | * | 543 | * |
@@ -515,6 +555,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
515 | int cpu = smp_processor_id(); | 555 | int cpu = smp_processor_id(); |
516 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 556 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
517 | 557 | ||
558 | /* we're going to use this soon, after a few expensive things */ | ||
559 | if (next_p->fpu_counter>5) | ||
560 | prefetch(&next->i387.fxsave); | ||
561 | |||
518 | /* | 562 | /* |
519 | * Reload esp0, LDT and the page table pointer: | 563 | * Reload esp0, LDT and the page table pointer: |
520 | */ | 564 | */ |
@@ -583,41 +627,29 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
583 | And the AMD workaround requires it to be after DS reload. */ | 627 | And the AMD workaround requires it to be after DS reload. */ |
584 | unlazy_fpu(prev_p); | 628 | unlazy_fpu(prev_p); |
585 | write_pda(kernelstack, | 629 | write_pda(kernelstack, |
586 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); | 630 | (unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); |
587 | 631 | #ifdef CONFIG_CC_STACKPROTECTOR | |
632 | write_pda(stack_canary, next_p->stack_canary); | ||
588 | /* | 633 | /* |
589 | * Now maybe reload the debug registers | 634 | * Build time only check to make sure the stack_canary is at |
635 | * offset 40 in the pda; this is a gcc ABI requirement | ||
590 | */ | 636 | */ |
591 | if (unlikely(next->debugreg7)) { | 637 | BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); |
592 | loaddebug(next, 0); | 638 | #endif |
593 | loaddebug(next, 1); | ||
594 | loaddebug(next, 2); | ||
595 | loaddebug(next, 3); | ||
596 | /* no 4 and 5 */ | ||
597 | loaddebug(next, 6); | ||
598 | loaddebug(next, 7); | ||
599 | } | ||
600 | |||
601 | 639 | ||
602 | /* | 640 | /* |
603 | * Handle the IO bitmap | 641 | * Now maybe reload the debug registers and handle I/O bitmaps |
604 | */ | 642 | */ |
605 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { | 643 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) |
606 | if (next->io_bitmap_ptr) | 644 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) |
607 | /* | 645 | __switch_to_xtra(prev_p, next_p, tss); |
608 | * Copy the relevant range of the IO bitmap. | ||
609 | * Normally this is 128 bytes or less: | ||
610 | */ | ||
611 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
612 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
613 | else { | ||
614 | /* | ||
615 | * Clear any possible leftover bits: | ||
616 | */ | ||
617 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
618 | } | ||
619 | } | ||
620 | 646 | ||
647 | /* If the task has used fpu the last 5 timeslices, just do a full | ||
648 | * restore of the math state immediately to avoid the trap; the | ||
649 | * chances of needing FPU soon are obviously high now | ||
650 | */ | ||
651 | if (next_p->fpu_counter>5) | ||
652 | math_state_restore(); | ||
621 | return prev_p; | 653 | return prev_p; |
622 | } | 654 | } |
623 | 655 | ||
@@ -834,7 +866,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
834 | 866 | ||
835 | unsigned long arch_align_stack(unsigned long sp) | 867 | unsigned long arch_align_stack(unsigned long sp) |
836 | { | 868 | { |
837 | if (randomize_va_space) | 869 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
838 | sp -= get_random_int() % 8192; | 870 | sp -= get_random_int() % 8192; |
839 | return sp & ~0xf; | 871 | return sp & ~0xf; |
840 | } | 872 | } |