* Functions used to update vtime in probe context.
*/
BL_SENTRY(typeof(ktime_get_raw_fast_ns), ktime_get_raw_fast_ns)
+BL_DENTRY(void *, raw_read_seqcount)
+BL_DENTRY(void *, read_seqcount_retry)
+BL_DENTRY(void *, __read_seqcount_retry)
+
/* xen_clocksource */
BL_DENTRY(void *, xen_clocksource_get_cycles)
BL_DENTRY(void *, xen_clocksource_read)
-/* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. */
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ */
#ifndef _LINUX_DTRACE_OS_H_
#define _LINUX_DTRACE_OS_H_
#include <linux/ktime.h>
#include <linux/mm.h>
#include <linux/notifier.h>
+#include <linux/timekeeper_internal.h>
#if defined(CONFIG_DT_FASTTRAP) || defined(CONFIG_DT_FASTTRAP_MODULE)
#include <linux/uprobes.h>
#endif
extern dtrace_vtime_state_t dtrace_vtime_active;
+extern void dtrace_update_time(struct timekeeper *);
extern ktime_t dtrace_get_walltime(void);
extern void dtrace_vtime_enable(void);
#define dtrace_no_pf(ignore) 0
+/*
+ * See kernel/timekeeper.c
+ */
+#define dtrace_update_time(ignore)
+
#endif /* CONFIG_DTRACE */
#endif /* !HEADERS_CHECK */
\*---------------------------------------------------------------------------*/
dtrace_vtime_state_t dtrace_vtime_active = 0;
+/*
+ * Until Linux kernel gains lock-free realtime clock access we are maintaining
+ * our own version for lock-free access from within a probe context.
+ */
+static struct dtrace_time_fast {
+ seqcount_t dtwf_seq;
+ ktime_t dtwf_offsreal[2];
+} dtrace_time ____cacheline_aligned;
+
+/*
+ * Callback from timekeeper code that allows dtrace to update its own time data.
+ */
+void dtrace_update_time(struct timekeeper *tk)
+{
+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
+ dtrace_time.dtwf_offsreal[0] = tk->offs_real;
+ raw_write_seqcount_latch(&dtrace_time.dtwf_seq);
+ dtrace_time.dtwf_offsreal[1] = tk->offs_real;
+}
+
+/* Lock free walltime */
ktime_t dtrace_get_walltime(void)
{
- struct timespec t = __current_kernel_time();
+ u64 nsec = ktime_get_mono_fast_ns();
+ unsigned int seq;
+ ktime_t *offset;
+
+ do {
+ seq = raw_read_seqcount(&dtrace_time.dtwf_seq);
+ offset = dtrace_time.dtwf_offsreal + (seq & 0x1);
+ } while (read_seqcount_retry(&dtrace_time.dtwf_seq, seq));
- return ns_to_ktime(timespec64_to_ns(&t));
+ return ktime_add_ns(*offset, nsec);
}
EXPORT_SYMBOL(dtrace_get_walltime);
#include <linux/stop_machine.h>
#include <linux/pvclock_gtod.h>
#include <linux/compiler.h>
+#include <linux/dtrace_os.h>
#include "tick-internal.h"
#include "ntp_internal.h"
tk_update_ktime_data(tk);
update_vsyscall(tk);
+ dtrace_update_time(tk);
update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
if (action & TK_MIRROR)