aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-08-31 11:12:48 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-09-25 15:05:59 -0400
commit4c3711d7fb4763c63b2654f2d07cbe21ca5aadd4 (patch)
tree8601fdab0f9b823f687d0ae5ddef6b7ef6046710 /kernel/time
parent5df32107f609c1f621bcdac0a685c23677ef671e (diff)
timekeeping: Provide NMI safe access to clock realtime
The configurable printk timestamping wants access to clock realtime. Right now there is no ktime_get_real_fast_ns() accessor because reading the monotonic base and the realtime offset cannot be done atomically. Contrary to boot time this offset can change during runtime and cause half updated readouts. struct tk_read_base was fully packed when the fast timekeeper access was implemented. commit ceea5e3771ed ("time: Fix clock->read(clock) race around clocksource changes") removed the 'read' function pointer from the structure, but of course left the comment stale. So now the structure can fit a new 64bit member w/o violating the cache line constraints. Add real_base to tk_read_base and update it in the fast timekeeper update sequence. Implement an accessor which follows the same scheme as the accessor to clock monotonic, but uses the new real_base to access clock real time. The runtime overhead for updating real_base is minimal as it just adds two cache hot values and stores them into an already dirtied cache line along with the other fast timekeeper updates. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Prarit Bhargava <prarit@redhat.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Peter Zijlstra <peterz@infradead,org> Link: https://lkml.kernel.org/r/1505757060-2004-3-git-send-email-prarit@redhat.com
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/timekeeping.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 6a92794427c9..8af77006e937 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -496,6 +496,39 @@ u64 notrace ktime_get_boot_fast_ns(void)
496} 496}
497EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns); 497EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns);
498 498
499
500/*
501 * See comment for __ktime_get_fast_ns() vs. timestamp ordering
502 */
503static __always_inline u64 __ktime_get_real_fast_ns(struct tk_fast *tkf)
504{
505 struct tk_read_base *tkr;
506 unsigned int seq;
507 u64 now;
508
509 do {
510 seq = raw_read_seqcount_latch(&tkf->seq);
511 tkr = tkf->base + (seq & 0x01);
512 now = ktime_to_ns(tkr->base_real);
513
514 now += timekeeping_delta_to_ns(tkr,
515 clocksource_delta(
516 tk_clock_read(tkr),
517 tkr->cycle_last,
518 tkr->mask));
519 } while (read_seqcount_retry(&tkf->seq, seq));
520
521 return now;
522}
523
524/**
525 * ktime_get_real_fast_ns: - NMI safe and fast access to clock realtime.
526 */
527u64 ktime_get_real_fast_ns(void)
528{
529 return __ktime_get_real_fast_ns(&tk_fast_mono);
530}
531
499/** 532/**
500 * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. 533 * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource.
501 * @tk: Timekeeper to snapshot. 534 * @tk: Timekeeper to snapshot.
@@ -514,6 +547,7 @@ static void halt_fast_timekeeper(struct timekeeper *tk)
514 memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy)); 547 memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
515 cycles_at_suspend = tk_clock_read(tkr); 548 cycles_at_suspend = tk_clock_read(tkr);
516 tkr_dummy.clock = &dummy_clock; 549 tkr_dummy.clock = &dummy_clock;
550 tkr_dummy.base_real = tkr->base + tk->offs_real;
517 update_fast_timekeeper(&tkr_dummy, &tk_fast_mono); 551 update_fast_timekeeper(&tkr_dummy, &tk_fast_mono);
518 552
519 tkr = &tk->tkr_raw; 553 tkr = &tk->tkr_raw;
@@ -661,6 +695,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
661 update_vsyscall(tk); 695 update_vsyscall(tk);
662 update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET); 696 update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
663 697
698 tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
664 update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono); 699 update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
665 update_fast_timekeeper(&tk->tkr_raw, &tk_fast_raw); 700 update_fast_timekeeper(&tk->tkr_raw, &tk_fast_raw);
666 701