1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56#include "sched.h"
57#include <linux/sched_clock.h>
58
59
60
61
62
63
64unsigned long long __weak sched_clock(void)
65{
66 return (unsigned long long)(jiffies - INITIAL_JIFFIES)
67 * (NSEC_PER_SEC / HZ);
68}
69EXPORT_SYMBOL_GPL(sched_clock);
70
71static DEFINE_STATIC_KEY_FALSE(sched_clock_running);
72
73#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
74
75
76
77
78
79
80
81static DEFINE_STATIC_KEY_FALSE(__sched_clock_stable);
82static int __sched_clock_stable_early = 1;
83
84
85
86
87__read_mostly u64 __sched_clock_offset;
88static __read_mostly u64 __gtod_offset;
89
90struct sched_clock_data {
91 u64 tick_raw;
92 u64 tick_gtod;
93 u64 clock;
94};
95
96static DEFINE_PER_CPU_SHARED_ALIGNED(struct sched_clock_data, sched_clock_data);
97
98static inline struct sched_clock_data *this_scd(void)
99{
100 return this_cpu_ptr(&sched_clock_data);
101}
102
103static inline struct sched_clock_data *cpu_sdc(int cpu)
104{
105 return &per_cpu(sched_clock_data, cpu);
106}
107
108int sched_clock_stable(void)
109{
110 return static_branch_likely(&__sched_clock_stable);
111}
112
113static void __scd_stamp(struct sched_clock_data *scd)
114{
115 scd->tick_gtod = ktime_get_ns();
116 scd->tick_raw = sched_clock();
117}
118
119static void __set_sched_clock_stable(void)
120{
121 struct sched_clock_data *scd;
122
123
124
125
126
127 local_irq_disable();
128 scd = this_scd();
129
130
131
132 __sched_clock_offset = (scd->tick_gtod + __gtod_offset) - (scd->tick_raw);
133 local_irq_enable();
134
135 printk(KERN_INFO "sched_clock: Marking stable (%lld, %lld)->(%lld, %lld)\n",
136 scd->tick_gtod, __gtod_offset,
137 scd->tick_raw, __sched_clock_offset);
138
139 static_branch_enable(&__sched_clock_stable);
140 tick_dep_clear(TICK_DEP_BIT_CLOCK_UNSTABLE);
141}
142
143
144
145
146
147
148
149
150
151
152
153
154static void __sched_clock_work(struct work_struct *work)
155{
156 struct sched_clock_data *scd;
157 int cpu;
158
159
160 preempt_disable();
161 scd = this_scd();
162 __scd_stamp(scd);
163 scd->clock = scd->tick_gtod + __gtod_offset;
164 preempt_enable();
165
166
167 for_each_possible_cpu(cpu)
168 per_cpu(sched_clock_data, cpu) = *scd;
169
170 printk(KERN_WARNING "TSC found unstable after boot, most likely due to broken BIOS. Use 'tsc=unstable'.\n");
171 printk(KERN_INFO "sched_clock: Marking unstable (%lld, %lld)<-(%lld, %lld)\n",
172 scd->tick_gtod, __gtod_offset,
173 scd->tick_raw, __sched_clock_offset);
174
175 static_branch_disable(&__sched_clock_stable);
176}
177
178static DECLARE_WORK(sched_clock_work, __sched_clock_work);
179
180static void __clear_sched_clock_stable(void)
181{
182 if (!sched_clock_stable())
183 return;
184
185 tick_dep_set(TICK_DEP_BIT_CLOCK_UNSTABLE);
186 schedule_work(&sched_clock_work);
187}
188
189void clear_sched_clock_stable(void)
190{
191 __sched_clock_stable_early = 0;
192
193 smp_mb();
194
195 if (static_key_count(&sched_clock_running.key) == 2)
196 __clear_sched_clock_stable();
197}
198
199static void __sched_clock_gtod_offset(void)
200{
201 struct sched_clock_data *scd = this_scd();
202
203 __scd_stamp(scd);
204 __gtod_offset = (scd->tick_raw + __sched_clock_offset) - scd->tick_gtod;
205}
206
207void __init sched_clock_init(void)
208{
209
210
211
212
213
214
215
216 local_irq_disable();
217 __sched_clock_gtod_offset();
218 local_irq_enable();
219
220 static_branch_inc(&sched_clock_running);
221}
222
223
224
225
226static int __init sched_clock_init_late(void)
227{
228 static_branch_inc(&sched_clock_running);
229
230
231
232
233
234
235
236 smp_mb();
237
238 if (__sched_clock_stable_early)
239 __set_sched_clock_stable();
240
241 return 0;
242}
243late_initcall(sched_clock_init_late);
244
245
246
247
248
249static inline u64 wrap_min(u64 x, u64 y)
250{
251 return (s64)(x - y) < 0 ? x : y;
252}
253
254static inline u64 wrap_max(u64 x, u64 y)
255{
256 return (s64)(x - y) > 0 ? x : y;
257}
258
259
260
261
262
263
264
265static u64 sched_clock_local(struct sched_clock_data *scd)
266{
267 u64 now, clock, old_clock, min_clock, max_clock, gtod;
268 s64 delta;
269
270again:
271 now = sched_clock();
272 delta = now - scd->tick_raw;
273 if (unlikely(delta < 0))
274 delta = 0;
275
276 old_clock = scd->clock;
277
278
279
280
281
282
283
284 gtod = scd->tick_gtod + __gtod_offset;
285 clock = gtod + delta;
286 min_clock = wrap_max(gtod, old_clock);
287 max_clock = wrap_max(old_clock, gtod + TICK_NSEC);
288
289 clock = wrap_max(clock, min_clock);
290 clock = wrap_min(clock, max_clock);
291
292 if (cmpxchg64(&scd->clock, old_clock, clock) != old_clock)
293 goto again;
294
295 return clock;
296}
297
298static u64 sched_clock_remote(struct sched_clock_data *scd)
299{
300 struct sched_clock_data *my_scd = this_scd();
301 u64 this_clock, remote_clock;
302 u64 *ptr, old_val, val;
303
304#if BITS_PER_LONG != 64
305again:
306
307
308
309
310
311
312
313
314
315
316
317 this_clock = sched_clock_local(my_scd);
318
319
320
321
322
323 remote_clock = cmpxchg64(&scd->clock, 0, 0);
324#else
325
326
327
328
329 sched_clock_local(my_scd);
330again:
331 this_clock = my_scd->clock;
332 remote_clock = scd->clock;
333#endif
334
335
336
337
338
339
340
341 if (likely((s64)(remote_clock - this_clock) < 0)) {
342 ptr = &scd->clock;
343 old_val = remote_clock;
344 val = this_clock;
345 } else {
346
347
348
349 ptr = &my_scd->clock;
350 old_val = this_clock;
351 val = remote_clock;
352 }
353
354 if (cmpxchg64(ptr, old_val, val) != old_val)
355 goto again;
356
357 return val;
358}
359
360
361
362
363
364
365u64 sched_clock_cpu(int cpu)
366{
367 struct sched_clock_data *scd;
368 u64 clock;
369
370 if (sched_clock_stable())
371 return sched_clock() + __sched_clock_offset;
372
373 if (!static_branch_likely(&sched_clock_running))
374 return sched_clock();
375
376 preempt_disable_notrace();
377 scd = cpu_sdc(cpu);
378
379 if (cpu != smp_processor_id())
380 clock = sched_clock_remote(scd);
381 else
382 clock = sched_clock_local(scd);
383 preempt_enable_notrace();
384
385 return clock;
386}
387EXPORT_SYMBOL_GPL(sched_clock_cpu);
388
389void sched_clock_tick(void)
390{
391 struct sched_clock_data *scd;
392
393 if (sched_clock_stable())
394 return;
395
396 if (!static_branch_likely(&sched_clock_running))
397 return;
398
399 lockdep_assert_irqs_disabled();
400
401 scd = this_scd();
402 __scd_stamp(scd);
403 sched_clock_local(scd);
404}
405
406void sched_clock_tick_stable(void)
407{
408 if (!sched_clock_stable())
409 return;
410
411
412
413
414
415
416
417
418 local_irq_disable();
419 __sched_clock_gtod_offset();
420 local_irq_enable();
421}
422
423
424
425
426void sched_clock_idle_sleep_event(void)
427{
428 sched_clock_cpu(smp_processor_id());
429}
430EXPORT_SYMBOL_GPL(sched_clock_idle_sleep_event);
431
432
433
434
435void sched_clock_idle_wakeup_event(void)
436{
437 unsigned long flags;
438
439 if (sched_clock_stable())
440 return;
441
442 if (unlikely(timekeeping_suspended))
443 return;
444
445 local_irq_save(flags);
446 sched_clock_tick();
447 local_irq_restore(flags);
448}
449EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
450
451#else
452
453void __init sched_clock_init(void)
454{
455 static_branch_inc(&sched_clock_running);
456 local_irq_disable();
457 generic_sched_clock_init();
458 local_irq_enable();
459}
460
461u64 sched_clock_cpu(int cpu)
462{
463 if (!static_branch_likely(&sched_clock_running))
464 return 0;
465
466 return sched_clock();
467}
468
469#endif
470
471
472
473
474
475
476
477
478
479u64 __weak running_clock(void)
480{
481 return local_clock();
482}
483