diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
| -rw-r--r-- | arch/i386/kernel/process.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 06dfa65ad18..6c49acb9698 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
| @@ -538,8 +538,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
| 538 | return 1; | 538 | return 1; |
| 539 | } | 539 | } |
| 540 | 540 | ||
| 541 | static noinline void __switch_to_xtra(struct task_struct *next_p, | 541 | #ifdef CONFIG_SECCOMP |
| 542 | struct tss_struct *tss) | 542 | void hard_disable_TSC(void) |
| 543 | { | ||
| 544 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 545 | } | ||
| 546 | void disable_TSC(void) | ||
| 547 | { | ||
| 548 | preempt_disable(); | ||
| 549 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
| 550 | /* | ||
| 551 | * Must flip the CPU state synchronously with | ||
| 552 | * TIF_NOTSC in the current running context. | ||
| 553 | */ | ||
| 554 | hard_disable_TSC(); | ||
| 555 | preempt_enable(); | ||
| 556 | } | ||
| 557 | void hard_enable_TSC(void) | ||
| 558 | { | ||
| 559 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 560 | } | ||
| 561 | #endif /* CONFIG_SECCOMP */ | ||
| 562 | |||
| 563 | static noinline void | ||
| 564 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
| 565 | struct tss_struct *tss) | ||
| 543 | { | 566 | { |
| 544 | struct thread_struct *next; | 567 | struct thread_struct *next; |
| 545 | 568 | ||
| @@ -555,6 +578,17 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
| 555 | set_debugreg(next->debugreg[7], 7); | 578 | set_debugreg(next->debugreg[7], 7); |
| 556 | } | 579 | } |
| 557 | 580 | ||
| 581 | #ifdef CONFIG_SECCOMP | ||
| 582 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
| 583 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
| 584 | /* prev and next are different */ | ||
| 585 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
| 586 | hard_disable_TSC(); | ||
| 587 | else | ||
| 588 | hard_enable_TSC(); | ||
| 589 | } | ||
| 590 | #endif | ||
| 591 | |||
| 558 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 592 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |
| 559 | /* | 593 | /* |
| 560 | * Disable the bitmap via an invalid offset. We still cache | 594 | * Disable the bitmap via an invalid offset. We still cache |
| @@ -586,33 +620,6 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
| 586 | } | 620 | } |
| 587 | 621 | ||
| 588 | /* | 622 | /* |
| 589 | * This function selects if the context switch from prev to next | ||
| 590 | * has to tweak the TSC disable bit in the cr4. | ||
| 591 | */ | ||
| 592 | static inline void disable_tsc(struct task_struct *prev_p, | ||
| 593 | struct task_struct *next_p) | ||
| 594 | { | ||
| 595 | struct thread_info *prev, *next; | ||
| 596 | |||
| 597 | /* | ||
| 598 | * gcc should eliminate the ->thread_info dereference if | ||
| 599 | * has_secure_computing returns 0 at compile time (SECCOMP=n). | ||
| 600 | */ | ||
| 601 | prev = task_thread_info(prev_p); | ||
| 602 | next = task_thread_info(next_p); | ||
| 603 | |||
| 604 | if (has_secure_computing(prev) || has_secure_computing(next)) { | ||
| 605 | /* slow path here */ | ||
| 606 | if (has_secure_computing(prev) && | ||
| 607 | !has_secure_computing(next)) { | ||
| 608 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
| 609 | } else if (!has_secure_computing(prev) && | ||
| 610 | has_secure_computing(next)) | ||
| 611 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
| 612 | } | ||
| 613 | } | ||
| 614 | |||
| 615 | /* | ||
| 616 | * switch_to(x,yn) should switch tasks from x to y. | 623 | * switch_to(x,yn) should switch tasks from x to y. |
| 617 | * | 624 | * |
| 618 | * We fsave/fwait so that an exception goes off at the right time | 625 | * We fsave/fwait so that an exception goes off at the right time |
| @@ -689,11 +696,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
| 689 | /* | 696 | /* |
| 690 | * Now maybe handle debug registers and/or IO bitmaps | 697 | * Now maybe handle debug registers and/or IO bitmaps |
| 691 | */ | 698 | */ |
| 692 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW) | 699 | if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV || |
| 693 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))) | 700 | task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT)) |
| 694 | __switch_to_xtra(next_p, tss); | 701 | __switch_to_xtra(prev_p, next_p, tss); |
| 695 | |||
| 696 | disable_tsc(prev_p, next_p); | ||
| 697 | 702 | ||
| 698 | /* | 703 | /* |
| 699 | * Leave lazy mode, flushing any hypercalls made here. | 704 | * Leave lazy mode, flushing any hypercalls made here. |
