aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/process_32.c43
-rw-r--r--arch/x86/kernel/process_64.c68
-rw-r--r--include/asm-x86/processor.h7
-rw-r--r--include/asm-x86/thread_info_64.h4
-rw-r--r--include/asm-x86/tsc.h1
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}
524EXPORT_SYMBOL_GPL(start_thread); 525EXPORT_SYMBOL_GPL(start_thread);
525 526
526#ifdef CONFIG_SECCOMP
527static void hard_disable_TSC(void) 527static 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
531void disable_TSC(void) 532void 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
542static void hard_enable_TSC(void) 544static 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
549void 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
561int 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
573int 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
548static noinline void 585static 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}
536EXPORT_SYMBOL_GPL(start_thread); 537EXPORT_SYMBOL_GPL(start_thread);
537 538
539static void hard_disable_TSC(void)
540{
541 write_cr4(read_cr4() | X86_CR4_TSD);
542}
543
544void 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
556static void hard_enable_TSC(void)
557{
558 write_cr4(read_cr4() & ~X86_CR4_TSD);
559}
560
561void 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
573int 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
585int 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
925extern int get_tsc_mode(unsigned long adr);
926extern 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;
18extern unsigned int tsc_khz; 18extern unsigned int tsc_khz;
19 19
20extern void disable_TSC(void); 20extern void disable_TSC(void);
21extern void enable_TSC(void);
21 22
22static inline cycles_t get_cycles(void) 23static inline cycles_t get_cycles(void)
23{ 24{