aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tsc.c
diff options
context:
space:
mode:
authorRajvi Jingar <rajvi.jingar@intel.com>2018-03-08 12:28:36 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-03-16 10:14:35 -0400
commitfc804f65d46236c211f530174904c1ed70db5888 (patch)
tree942b8e3d74e1d012765a659e60cda360d367c6f4 /arch/x86/kernel/tsc.c
parentfc6eabbbf8ef99efed778dd5afabc83c21dba585 (diff)
x86/tsc: Convert ART in nanoseconds to TSC
Device drivers use get_device_system_crosststamp() to produce precise system/device cross-timestamps. The PHC clock and ALSA interfaces, for example, make the cross-timestamps available to user applications. On Intel platforms, get_device_system_crosststamp() requires a TSC value derived from ART (Always Running Timer) to compute the monotonic raw and realtime system timestamps. Starting with Intel Goldmont platforms, the PCIe root complex supports the PTM time sync protocol. PTM requires all timestamps to be in units of nanoseconds. The Intel root complex hardware propagates system time derived from ART in units of nanoseconds performing the conversion as follows: ART_NS = ART * 1e9 / <crystal frequency> When user software requests a cross-timestamp, the system timestamps (generally read from device registers) must be converted to TSC by the driver software as follows: TSC = ART_NS * TSC_KHZ / 1e6 This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set indicating that tsc_khz is derived from CPUID[15H]. Drivers should check whether this flag is set before conversion to TSC is attempted. Suggested-by: Christopher S. Hall <christopher.s.hall@intel.com> Signed-off-by: Rajvi Jingar <rajvi.jingar@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: peterz@infradead.org Link: https://lkml.kernel.org/r/1520530116-4925-1-git-send-email-rajvi.jingar@intel.com
Diffstat (limited to 'arch/x86/kernel/tsc.c')
-rw-r--r--arch/x86/kernel/tsc.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index fb4302738410..ef32297ff17e 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1179,6 +1179,45 @@ struct system_counterval_t convert_art_to_tsc(u64 art)
1179} 1179}
1180EXPORT_SYMBOL(convert_art_to_tsc); 1180EXPORT_SYMBOL(convert_art_to_tsc);
1181 1181
1182/**
1183 * convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC.
1184 * @art_ns: ART (Always Running Timer) in unit of nanoseconds
1185 *
1186 * PTM requires all timestamps to be in units of nanoseconds. When user
1187 * software requests a cross-timestamp, this function converts system timestamp
1188 * to TSC.
1189 *
1190 * This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set
1191 * indicating the tsc_khz is derived from CPUID[15H]. Drivers should check
1192 * that this flag is set before conversion to TSC is attempted.
1193 *
1194 * Return:
1195 * struct system_counterval_t - system counter value with the pointer to the
1196 * corresponding clocksource
1197 * @cycles: System counter value
1198 * @cs: Clocksource corresponding to system counter value. Used
1199 * by timekeeping code to verify comparibility of two cycle
1200 * values.
1201 */
1202
1203struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns)
1204{
1205 u64 tmp, res, rem;
1206
1207 rem = do_div(art_ns, USEC_PER_SEC);
1208
1209 res = art_ns * tsc_khz;
1210 tmp = rem * tsc_khz;
1211
1212 do_div(tmp, USEC_PER_SEC);
1213 res += tmp;
1214
1215 return (struct system_counterval_t) { .cs = art_related_clocksource,
1216 .cycles = res};
1217}
1218EXPORT_SYMBOL(convert_art_ns_to_tsc);
1219
1220
1182static void tsc_refine_calibration_work(struct work_struct *work); 1221static void tsc_refine_calibration_work(struct work_struct *work);
1183static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work); 1222static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
1184/** 1223/**