aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/clock.c57
-rw-r--r--kernel/sched/core.c1
-rw-r--r--kernel/sched/debug.c2
-rw-r--r--kernel/time/sched_clock.c2
-rw-r--r--kernel/time/timekeeping.c62
5 files changed, 74 insertions, 50 deletions
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c
index 10c83e73837a..e3e3b979f9bd 100644
--- a/kernel/sched/clock.c
+++ b/kernel/sched/clock.c
@@ -53,6 +53,7 @@
53 * 53 *
54 */ 54 */
55#include "sched.h" 55#include "sched.h"
56#include <linux/sched_clock.h>
56 57
57/* 58/*
58 * Scheduler clock - returns current time in nanosec units. 59 * Scheduler clock - returns current time in nanosec units.
@@ -66,12 +67,7 @@ unsigned long long __weak sched_clock(void)
66} 67}
67EXPORT_SYMBOL_GPL(sched_clock); 68EXPORT_SYMBOL_GPL(sched_clock);
68 69
69__read_mostly int sched_clock_running; 70static DEFINE_STATIC_KEY_FALSE(sched_clock_running);
70
71void sched_clock_init(void)
72{
73 sched_clock_running = 1;
74}
75 71
76#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK 72#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
77/* 73/*
@@ -195,17 +191,40 @@ void clear_sched_clock_stable(void)
195 191
196 smp_mb(); /* matches sched_clock_init_late() */ 192 smp_mb(); /* matches sched_clock_init_late() */
197 193
198 if (sched_clock_running == 2) 194 if (static_key_count(&sched_clock_running.key) == 2)
199 __clear_sched_clock_stable(); 195 __clear_sched_clock_stable();
200} 196}
201 197
198static void __sched_clock_gtod_offset(void)
199{
200 struct sched_clock_data *scd = this_scd();
201
202 __scd_stamp(scd);
203 __gtod_offset = (scd->tick_raw + __sched_clock_offset) - scd->tick_gtod;
204}
205
206void __init sched_clock_init(void)
207{
208 /*
209 * Set __gtod_offset such that once we mark sched_clock_running,
210 * sched_clock_tick() continues where sched_clock() left off.
211 *
212 * Even if TSC is buggered, we're still UP at this point so it
213 * can't really be out of sync.
214 */
215 local_irq_disable();
216 __sched_clock_gtod_offset();
217 local_irq_enable();
218
219 static_branch_inc(&sched_clock_running);
220}
202/* 221/*
203 * We run this as late_initcall() such that it runs after all built-in drivers, 222 * We run this as late_initcall() such that it runs after all built-in drivers,
204 * notably: acpi_processor and intel_idle, which can mark the TSC as unstable. 223 * notably: acpi_processor and intel_idle, which can mark the TSC as unstable.
205 */ 224 */
206static int __init sched_clock_init_late(void) 225static int __init sched_clock_init_late(void)
207{ 226{
208 sched_clock_running = 2; 227 static_branch_inc(&sched_clock_running);
209 /* 228 /*
210 * Ensure that it is impossible to not do a static_key update. 229 * Ensure that it is impossible to not do a static_key update.
211 * 230 *
@@ -350,8 +369,8 @@ u64 sched_clock_cpu(int cpu)
350 if (sched_clock_stable()) 369 if (sched_clock_stable())
351 return sched_clock() + __sched_clock_offset; 370 return sched_clock() + __sched_clock_offset;
352 371
353 if (unlikely(!sched_clock_running)) 372 if (!static_branch_unlikely(&sched_clock_running))
354 return 0ull; 373 return sched_clock();
355 374
356 preempt_disable_notrace(); 375 preempt_disable_notrace();
357 scd = cpu_sdc(cpu); 376 scd = cpu_sdc(cpu);
@@ -373,7 +392,7 @@ void sched_clock_tick(void)
373 if (sched_clock_stable()) 392 if (sched_clock_stable())
374 return; 393 return;
375 394
376 if (unlikely(!sched_clock_running)) 395 if (!static_branch_unlikely(&sched_clock_running))
377 return; 396 return;
378 397
379 lockdep_assert_irqs_disabled(); 398 lockdep_assert_irqs_disabled();
@@ -385,8 +404,6 @@ void sched_clock_tick(void)
385 404
386void sched_clock_tick_stable(void) 405void sched_clock_tick_stable(void)
387{ 406{
388 u64 gtod, clock;
389
390 if (!sched_clock_stable()) 407 if (!sched_clock_stable())
391 return; 408 return;
392 409
@@ -398,9 +415,7 @@ void sched_clock_tick_stable(void)
398 * TSC to be unstable, any computation will be computing crap. 415 * TSC to be unstable, any computation will be computing crap.
399 */ 416 */
400 local_irq_disable(); 417 local_irq_disable();
401 gtod = ktime_get_ns(); 418 __sched_clock_gtod_offset();
402 clock = sched_clock();
403 __gtod_offset = (clock + __sched_clock_offset) - gtod;
404 local_irq_enable(); 419 local_irq_enable();
405} 420}
406 421
@@ -434,9 +449,17 @@ EXPORT_SYMBOL_GPL(sched_clock_idle_wakeup_event);
434 449
435#else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */ 450#else /* CONFIG_HAVE_UNSTABLE_SCHED_CLOCK */
436 451
452void __init sched_clock_init(void)
453{
454 static_branch_inc(&sched_clock_running);
455 local_irq_disable();
456 generic_sched_clock_init();
457 local_irq_enable();
458}
459
437u64 sched_clock_cpu(int cpu) 460u64 sched_clock_cpu(int cpu)
438{ 461{
439 if (unlikely(!sched_clock_running)) 462 if (!static_branch_unlikely(&sched_clock_running))
440 return 0; 463 return 0;
441 464
442 return sched_clock(); 465 return sched_clock();
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index d17d99778356..c45de46fdf10 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5916,7 +5916,6 @@ void __init sched_init(void)
5916 int i, j; 5916 int i, j;
5917 unsigned long alloc_size = 0, ptr; 5917 unsigned long alloc_size = 0, ptr;
5918 5918
5919 sched_clock_init();
5920 wait_bit_init(); 5919 wait_bit_init();
5921 5920
5922#ifdef CONFIG_FAIR_GROUP_SCHED 5921#ifdef CONFIG_FAIR_GROUP_SCHED
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index 870d4f3da285..60caf1fb94e0 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -622,8 +622,6 @@ void print_dl_rq(struct seq_file *m, int cpu, struct dl_rq *dl_rq)
622#undef PU 622#undef PU
623} 623}
624 624
625extern __read_mostly int sched_clock_running;
626
627static void print_cpu(struct seq_file *m, int cpu) 625static void print_cpu(struct seq_file *m, int cpu)
628{ 626{
629 struct rq *rq = cpu_rq(cpu); 627 struct rq *rq = cpu_rq(cpu);
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 2d8f05aad442..cbc72c2c1fca 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -237,7 +237,7 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
237 pr_debug("Registered %pF as sched_clock source\n", read); 237 pr_debug("Registered %pF as sched_clock source\n", read);
238} 238}
239 239
240void __init sched_clock_postinit(void) 240void __init generic_sched_clock_init(void)
241{ 241{
242 /* 242 /*
243 * If no sched_clock() function has been provided at that point, 243 * If no sched_clock() function has been provided at that point,
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d9e659a12c76..f3b22f456fac 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -17,6 +17,7 @@
17#include <linux/nmi.h> 17#include <linux/nmi.h>
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/sched/loadavg.h> 19#include <linux/sched/loadavg.h>
20#include <linux/sched/clock.h>
20#include <linux/syscore_ops.h> 21#include <linux/syscore_ops.h>
21#include <linux/clocksource.h> 22#include <linux/clocksource.h>
22#include <linux/jiffies.h> 23#include <linux/jiffies.h>
@@ -1505,18 +1506,23 @@ void __weak read_persistent_clock64(struct timespec64 *ts64)
1505} 1506}
1506 1507
1507/** 1508/**
1508 * read_boot_clock64 - Return time of the system start. 1509 * read_persistent_wall_and_boot_offset - Read persistent clock, and also offset
1510 * from the boot.
1509 * 1511 *
1510 * Weak dummy function for arches that do not yet support it. 1512 * Weak dummy function for arches that do not yet support it.
1511 * Function to read the exact time the system has been started. 1513 * wall_time - current time as returned by persistent clock
1512 * Returns a timespec64 with tv_sec=0 and tv_nsec=0 if unsupported. 1514 * boot_offset - offset that is defined as wall_time - boot_time
1513 *