diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-09-13 05:25:35 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-09-13 05:25:35 -0400 |
commit | d2bb1d42b95fa88f092623bbb8ed533f316b6a3c (patch) | |
tree | fb796db809a266906fa358f24f1c07ced4df33f0 /arch/x86/lib | |
parent | 3bd7617596df560e2cb22ad97888cb42dae39d02 (diff) | |
parent | 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff) |
Merge tag 'v4.3-rc1' into perf/core, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/delay.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index 39d6a3db0b96..e912b2f6d36e 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
21 | #include <asm/delay.h> | 21 | #include <asm/delay.h> |
22 | #include <asm/timer.h> | 22 | #include <asm/timer.h> |
23 | #include <asm/mwait.h> | ||
23 | 24 | ||
24 | #ifdef CONFIG_SMP | 25 | #ifdef CONFIG_SMP |
25 | # include <asm/smp.h> | 26 | # include <asm/smp.h> |
@@ -49,16 +50,14 @@ static void delay_loop(unsigned long loops) | |||
49 | /* TSC based delay: */ | 50 | /* TSC based delay: */ |
50 | static void delay_tsc(unsigned long __loops) | 51 | static void delay_tsc(unsigned long __loops) |
51 | { | 52 | { |
52 | u32 bclock, now, loops = __loops; | 53 | u64 bclock, now, loops = __loops; |
53 | int cpu; | 54 | int cpu; |
54 | 55 | ||
55 | preempt_disable(); | 56 | preempt_disable(); |
56 | cpu = smp_processor_id(); | 57 | cpu = smp_processor_id(); |
57 | rdtsc_barrier(); | 58 | bclock = rdtsc_ordered(); |
58 | rdtscl(bclock); | ||
59 | for (;;) { | 59 | for (;;) { |
60 | rdtsc_barrier(); | 60 | now = rdtsc_ordered(); |
61 | rdtscl(now); | ||
62 | if ((now - bclock) >= loops) | 61 | if ((now - bclock) >= loops) |
63 | break; | 62 | break; |
64 | 63 | ||
@@ -79,14 +78,51 @@ static void delay_tsc(unsigned long __loops) | |||
79 | if (unlikely(cpu != smp_processor_id())) { | 78 | if (unlikely(cpu != smp_processor_id())) { |
80 | loops -= (now - bclock); | 79 | loops -= (now - bclock); |
81 | cpu = smp_processor_id(); | 80 | cpu = smp_processor_id(); |
82 | rdtsc_barrier(); | 81 | bclock = rdtsc_ordered(); |
83 | rdtscl(bclock); | ||
84 | } | 82 | } |
85 | } | 83 | } |
86 | preempt_enable(); | 84 | preempt_enable(); |
87 | } | 85 | } |
88 | 86 | ||
89 | /* | 87 | /* |
88 | * On some AMD platforms, MWAITX has a configurable 32-bit timer, that | ||
89 | * counts with TSC frequency. The input value is the loop of the | ||
90 | * counter, it will exit when the timer expires. | ||
91 | */ | ||
92 | static void delay_mwaitx(unsigned long __loops) | ||
93 | { | ||
94 | u64 start, end, delay, loops = __loops; | ||
95 | |||
96 | start = rdtsc_ordered(); | ||
97 | |||
98 | for (;;) { | ||
99 | delay = min_t(u64, MWAITX_MAX_LOOPS, loops); | ||
100 | |||
101 | /* | ||
102 | * Use cpu_tss as a cacheline-aligned, seldomly | ||
103 | * accessed per-cpu variable as the monitor target. | ||
104 | */ | ||
105 | __monitorx(this_cpu_ptr(&cpu_tss), 0, 0); | ||
106 | |||
107 | /* | ||
108 | * AMD, like Intel, supports the EAX hint and EAX=0xf | ||
109 | * means, do not enter any deep C-state and we use it | ||
110 | * here in delay() to minimize wakeup latency. | ||
111 | */ | ||
112 | __mwaitx(MWAITX_DISABLE_CSTATES, delay, MWAITX_ECX_TIMER_ENABLE); | ||
113 | |||
114 | end = rdtsc_ordered(); | ||
115 | |||
116 | if (loops <= end - start) | ||
117 | break; | ||
118 | |||
119 | loops -= end - start; | ||
120 | |||
121 | start = end; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* | ||
90 | * Since we calibrate only once at boot, this | 126 | * Since we calibrate only once at boot, this |
91 | * function should be set once at boot and not changed | 127 | * function should be set once at boot and not changed |
92 | */ | 128 | */ |
@@ -94,13 +130,19 @@ static void (*delay_fn)(unsigned long) = delay_loop; | |||
94 | 130 | ||
95 | void use_tsc_delay(void) | 131 | void use_tsc_delay(void) |
96 | { | 132 | { |
97 | delay_fn = delay_tsc; | 133 | if (delay_fn == delay_loop) |
134 | delay_fn = delay_tsc; | ||
135 | } | ||
136 | |||
137 | void use_mwaitx_delay(void) | ||
138 | { | ||
139 | delay_fn = delay_mwaitx; | ||
98 | } | 140 | } |
99 | 141 | ||
100 | int read_current_timer(unsigned long *timer_val) | 142 | int read_current_timer(unsigned long *timer_val) |
101 | { | 143 | { |
102 | if (delay_fn == delay_tsc) { | 144 | if (delay_fn == delay_tsc) { |
103 | rdtscll(*timer_val); | 145 | *timer_val = rdtsc(); |
104 | return 0; | 146 | return 0; |
105 | } | 147 | } |
106 | return -1; | 148 | return -1; |