diff options
-rw-r--r-- | arch/x86/kernel/process_32.c | 43 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 68 | ||||
-rw-r--r-- | include/asm-x86/processor.h | 7 | ||||
-rw-r--r-- | include/asm-x86/thread_info_64.h | 4 | ||||
-rw-r--r-- | include/asm-x86/tsc.h | 1 |
5 files changed, 118 insertions, 5 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 91e147b486dd..a3790a3f8a83 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/personality.h> | 36 | #include <linux/personality.h> |
37 | #include <linux/tick.h> | 37 | #include <linux/tick.h> |
38 | #include <linux/percpu.h> | 38 | #include <linux/percpu.h> |
39 | #include <linux/prctl.h> | ||
39 | 40 | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
@@ -523,11 +524,11 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
523 | } | 524 | } |
524 | EXPORT_SYMBOL_GPL(start_thread); | 525 | EXPORT_SYMBOL_GPL(start_thread); |
525 | 526 | ||
526 | #ifdef CONFIG_SECCOMP | ||
527 | static void hard_disable_TSC(void) | 527 | static void hard_disable_TSC(void) |
528 | { | 528 | { |
529 | write_cr4(read_cr4() | X86_CR4_TSD); | 529 | write_cr4(read_cr4() | X86_CR4_TSD); |
530 | } | 530 | } |
531 | |||
531 | void disable_TSC(void) | 532 | void disable_TSC(void) |
532 | { | 533 | { |
533 | preempt_disable(); | 534 | preempt_disable(); |
@@ -539,11 +540,47 @@ void disable_TSC(void) | |||
539 | hard_disable_TSC(); | 540 | hard_disable_TSC(); |
540 | preempt_enable(); | 541 | preempt_enable(); |
541 | } | 542 | } |
543 | |||
542 | static void hard_enable_TSC(void) | 544 | static void hard_enable_TSC(void) |
543 | { | 545 | { |
544 | write_cr4(read_cr4() & ~X86_CR4_TSD); | 546 | write_cr4(read_cr4() & ~X86_CR4_TSD); |
545 | } | 547 | } |
546 | #endif /* CONFIG_SECCOMP */ | 548 | |
549 | void enable_TSC(void) | ||
550 | { | ||
551 | preempt_disable(); | ||
552 | if (test_and_clear_thread_flag(TIF_NOTSC)) | ||
553 | /* | ||
554 | * Must flip the CPU state synchronously with | ||
555 | * TIF_NOTSC in the current running context. | ||
556 | */ | ||
557 | hard_enable_TSC(); | ||
558 | preempt_enable(); | ||
559 | } | ||
560 | |||
561 | int get_tsc_mode(unsigned long adr) | ||
562 | { | ||
563 | unsigned int val; | ||
564 | |||
565 | if (test_thread_flag(TIF_NOTSC)) | ||
566 | val = PR_TSC_SIGSEGV; | ||
567 | else | ||
568 | val = PR_TSC_ENABLE; | ||
569 | |||
570 | return put_user(val, (unsigned int __user *)adr); | ||
571 | } | ||
572 | |||
573 | int set_tsc_mode(unsigned int val) | ||
574 | { | ||
575 | if (val == PR_TSC_SIGSEGV) | ||
576 | disable_TSC(); | ||
577 | else if (val == PR_TSC_ENABLE) | ||
578 | enable_TSC(); | ||
579 | else | ||
580 | return -EINVAL; | ||
581 | |||
582 | return 0; | ||
583 | } | ||
547 | 584 | ||
548 | static noinline void | 585 | static noinline void |
549 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | 586 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, |
@@ -577,7 +614,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
577 | set_debugreg(next->debugreg7, 7); | 614 | set_debugreg(next->debugreg7, 7); |
578 | } | 615 | } |
579 | 616 | ||
580 | #ifdef CONFIG_SECCOMP | ||
581 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | 617 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ |
582 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | 618 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { |
583 | /* prev and next are different */ | 619 | /* prev and next are different */ |
@@ -586,7 +622,6 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
586 | else | 622 | else |
587 | hard_enable_TSC(); | 623 | hard_enable_TSC(); |
588 | } | 624 | } |
589 | #endif | ||
590 | 625 | ||
591 | #ifdef X86_BTS | 626 | #ifdef X86_BTS |
592 | if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) | 627 | if (test_tsk_thread_flag(prev_p, TIF_BTS_TRACE_TS)) |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index e75ccc8a2b87..4c13b1406c70 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/kprobes.h> | 36 | #include <linux/kprobes.h> |
37 | #include <linux/kdebug.h> | 37 | #include <linux/kdebug.h> |
38 | #include <linux/tick.h> | 38 | #include <linux/tick.h> |
39 | #include <linux/prctl.h> | ||
39 | 40 | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
@@ -535,6 +536,64 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
535 | } | 536 | } |
536 | EXPORT_SYMBOL_GPL(start_thread); | 537 | EXPORT_SYMBOL_GPL(start_thread); |
537 | 538 | ||
539 | static void hard_disable_TSC(void) | ||
540 | { | ||
541 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
542 | } | ||
543 | |||
544 | void disable_TSC(void) | ||
545 | { | ||
546 | preempt_disable(); | ||
547 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
548 | /* | ||
549 | * Must flip the CPU state synchronously with | ||
550 | * TIF_NOTSC in the current running context. | ||
551 | */ | ||
552 | hard_disable_TSC(); | ||
553 | preempt_enable(); | ||
554 | } | ||
555 | |||
556 | static void hard_enable_TSC(void) | ||
557 | { | ||
558 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
559 | } | ||
560 | |||
561 | void enable_TSC(void) | ||
562 | { | ||
563 | preempt_disable(); | ||
564 | if (test_and_clear_thread_flag(TIF_NOTSC)) | ||
565 | /* | ||
566 | * Must flip the CPU state synchronously with | ||
567 | * TIF_NOTSC in the current running context. | ||
568 | */ | ||
569 | hard_enable_TSC(); | ||
570 | preempt_enable(); | ||
571 | } | ||
572 | |||
573 | int get_tsc_mode(unsigned long adr) | ||
574 | { | ||
575 | unsigned int val; | ||
576 | |||
577 | if (test_thread_flag(TIF_NOTSC)) | ||
578 | val = PR_TSC_SIGSEGV; | ||
579 | else | ||
580 | val = PR_TSC_ENABLE; | ||
581 | |||
582 | return put_user(val, (unsigned int __user *)adr); | ||
583 | } | ||
584 | |||
585 | int set_tsc_mode(unsigned int val) | ||
586 | { | ||
587 | if (val == PR_TSC_SIGSEGV) | ||
588 | disable_TSC(); | ||
589 | else if (val == PR_TSC_ENABLE) | ||
590 | enable_TSC(); | ||
591 | else | ||
592 | return -EINVAL; | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
538 | /* | 597 | /* |
539 | * This special macro can be used to load a debugging register | 598 | * This special macro can be used to load a debugging register |
540 | */ | 599 | */ |
@@ -572,6 +631,15 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, | |||
572 | loaddebug(next, 7); | 631 | loaddebug(next, 7); |
573 | } | 632 | } |
574 | 633 | ||
634 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
635 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
636 | /* prev and next are different */ | ||
637 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
638 | hard_disable_TSC(); | ||
639 | else | ||
640 | hard_enable_TSC(); | ||
641 | } | ||
642 | |||
575 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 643 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |
576 | /* | 644 | /* |
577 | * Copy the relevant range of the IO bitmap. | 645 | * Copy the relevant range of the IO bitmap. |
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h index 6e26c7c717a2..eaf4548a23d2 100644 --- a/include/asm-x86/processor.h +++ b/include/asm-x86/processor.h | |||
@@ -918,4 +918,11 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip, | |||
918 | 918 | ||
919 | #define KSTK_EIP(task) (task_pt_regs(task)->ip) | 919 | #define KSTK_EIP(task) (task_pt_regs(task)->ip) |
920 | 920 | ||
921 | /* Get/set a process' ability to use the timestamp counter instruction */ | ||
922 | #define GET_TSC_CTL(adr) get_tsc_mode((adr)) | ||
923 | #define SET_TSC_CTL(val) set_tsc_mode((val)) | ||
924 | |||
925 | extern int get_tsc_mode(unsigned long adr); | ||
926 | extern int set_tsc_mode(unsigned int val); | ||
927 | |||
921 | #endif | 928 | #endif |
diff --git a/include/asm-x86/thread_info_64.h b/include/asm-x86/thread_info_64.h index 1e5c6f6152cd..b17f5f6c2c59 100644 --- a/include/asm-x86/thread_info_64.h +++ b/include/asm-x86/thread_info_64.h | |||
@@ -126,6 +126,7 @@ static inline struct thread_info *stack_thread_info(void) | |||
126 | #define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */ | 126 | #define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */ |
127 | #define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */ | 127 | #define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */ |
128 | #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */ | 128 | #define TIF_BTS_TRACE_TS 27 /* record scheduling event timestamps */ |
129 | #define TIF_NOTSC 28 /* TSC is not accessible in userland */ | ||
129 | 130 | ||
130 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 131 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
131 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 132 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
@@ -147,6 +148,7 @@ static inline struct thread_info *stack_thread_info(void) | |||
147 | #define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR) | 148 | #define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR) |
148 | #define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR) | 149 | #define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR) |
149 | #define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS) | 150 | #define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS) |
151 | #define _TIF_NOTSC (1 << TIF_NOTSC) | ||
150 | 152 | ||
151 | /* work to do on interrupt/exception return */ | 153 | /* work to do on interrupt/exception return */ |
152 | #define _TIF_WORK_MASK \ | 154 | #define _TIF_WORK_MASK \ |
@@ -160,7 +162,7 @@ static inline struct thread_info *stack_thread_info(void) | |||
160 | 162 | ||
161 | /* flags to check in __switch_to() */ | 163 | /* flags to check in __switch_to() */ |
162 | #define _TIF_WORK_CTXSW \ | 164 | #define _TIF_WORK_CTXSW \ |
163 | (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS) | 165 | (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_BTS_TRACE_TS|_TIF_NOTSC) |
164 | #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW | 166 | #define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW |
165 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) | 167 | #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) |
166 | 168 | ||
diff --git a/include/asm-x86/tsc.h b/include/asm-x86/tsc.h index d2d8eb5b55f5..0434bd8349a7 100644 --- a/include/asm-x86/tsc.h +++ b/include/asm-x86/tsc.h | |||
@@ -18,6 +18,7 @@ extern unsigned int cpu_khz; | |||
18 | extern unsigned int tsc_khz; | 18 | extern unsigned int tsc_khz; |
19 | 19 | ||
20 | extern void disable_TSC(void); | 20 | extern void disable_TSC(void); |
21 | extern void enable_TSC(void); | ||
21 | 22 | ||
22 | static inline cycles_t get_cycles(void) | 23 | static inline cycles_t get_cycles(void) |
23 | { | 24 | { |