From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933527AbdKOS3c (ORCPT ); Wed, 15 Nov 2017 13:29:32 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:42855 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933024AbdKOS2D (ORCPT ); Wed, 15 Nov 2017 13:28:03 -0500 Message-Id: <20171115182657.463124645@linutronix.de> User-Agent: quilt/0.63-1 Date: Wed, 15 Nov 2017 19:15:35 +0100 From: Thomas Gleixner To: LKML Cc: Linus Torvalds , Prarit Bhargava , Mark Salyzyn , Petr Mladek , Ingo Molnar , "H. Peter Anvin" , Peter Zijlstra , Andrew Morton , Sergey Senozhatsky , Steven Rostedt , Joe Perches Subject: [RFC patch 4/7] timekeeping: Add NMI safe accessor to mono/boot/real clocks References: <20171115181531.322572387@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Disposition: inline; filename=timekeeping--Add-NMI-safe-accessor-to-full-data.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Clock MONOTONIC timestamps are not allowing reliable correlation to other timestamps (clock REALTIME/BOOTTIME). For post mortem analysis and other purposes its helpful to store all of these time stamps in the printk ring buffer entries. Rework __ktime_get_real_fast() so it captures both MONOTONIC and REALTIME atomically and provide an accessor which stores these plus BOOTTIME in a new system_timestamp data structure. Signed-off-by: Thomas Gleixner --- include/linux/timekeeping.h | 17 ++++++++++++++++- kernel/time/timekeeping.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 41 insertions(+), 12 deletions(-) --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h @@ -146,7 +146,19 @@ extern void timekeeping_inject_sleeptime * PPS accessor */ extern void ktime_get_raw_and_real_ts64(struct timespec64 *ts_raw, - struct timespec64 *ts_real); + struct timespec64 *ts_real); + +/* + * struct system_timestamps - Simultaneous mono/boot/real timestamps + * @mono: Monotonic timestamp + * @boot: Boottime timestamp + * @real: Realtime timestamp + */ +struct system_timestamps { + u64 mono; + u64 boot; + u64 real; +}; /* * struct system_time_snapshot - simultaneous raw/real time capture with @@ -206,6 +218,9 @@ extern int get_device_system_crosststamp */ extern void ktime_get_snapshot(struct system_time_snapshot *systime_snapshot); +/* NMI safe mono/boot/realtime timestamps */ +extern void ktime_get_fast_timestamps(struct system_timestamps *ts); + /* * Persistent clock related interfaces */ --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -496,29 +496,29 @@ u64 notrace ktime_get_boot_fast_ns(void) } EXPORT_SYMBOL_GPL(ktime_get_boot_fast_ns); - /* * See comment for __ktime_get_fast_ns() vs. timestamp ordering */ -static __always_inline u64 __ktime_get_real_fast_ns(struct tk_fast *tkf) +static notrace u64 __ktime_get_real_fast(struct tk_fast *tkf, u64 *mono) { struct tk_read_base *tkr; + u64 basem, baser, delta; unsigned int seq; - u64 now; do { seq = raw_read_seqcount_latch(&tkf->seq); tkr = tkf->base + (seq & 0x01); - now = ktime_to_ns(tkr->base_real); + basem = ktime_to_ns(tkr->base); + baser = ktime_to_ns(tkr->base_real); - now += timekeeping_delta_to_ns(tkr, - clocksource_delta( - tk_clock_read(tkr), - tkr->cycle_last, - tkr->mask)); + delta = timekeeping_delta_to_ns(tkr, + clocksource_delta(tk_clock_read(tkr), + tkr->cycle_last, tkr->mask)); } while (read_seqcount_retry(&tkf->seq, seq)); - return now; + if (mono) + *mono = basem + delta; + return baser + delta; } /** @@ -526,11 +526,25 @@ static __always_inline u64 __ktime_get_r */ u64 ktime_get_real_fast_ns(void) { - return __ktime_get_real_fast_ns(&tk_fast_mono); + return __ktime_get_real_fast(&tk_fast_mono, NULL); } EXPORT_SYMBOL_GPL(ktime_get_real_fast_ns); /** + * ktime_get_fast_timestamps: - NMI safe timestamps + * @ts: Pointer to timestamp storage + * + * Stores clock monotonic, boottime and realtime time stamps + */ +void ktime_get_fast_timestamps(struct system_timestamps *ts) +{ + struct timekeeper *tk = &tk_core.timekeeper; + + ts->real = __ktime_get_real_fast(&tk_fast_mono, &ts->mono); + ts->boot = ts->mono + ktime_to_ns(tk->offs_boot); +} + +/** * halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource. * @tk: Timekeeper to snapshot. *