|
@@ -1179,6 +1179,45 @@ struct system_counterval_t convert_art_to_tsc(u64 art)
|
|
|
}
|
|
|
EXPORT_SYMBOL(convert_art_to_tsc);
|
|
|
|
|
|
+/**
|
|
|
+ * convert_art_ns_to_tsc() - Convert ART in nanoseconds to TSC.
|
|
|
+ * @art_ns: ART (Always Running Timer) in unit of nanoseconds
|
|
|
+ *
|
|
|
+ * PTM requires all timestamps to be in units of nanoseconds. When user
|
|
|
+ * software requests a cross-timestamp, this function converts system timestamp
|
|
|
+ * to TSC.
|
|
|
+ *
|
|
|
+ * This is valid when CPU feature flag X86_FEATURE_TSC_KNOWN_FREQ is set
|
|
|
+ * indicating the tsc_khz is derived from CPUID[15H]. Drivers should check
|
|
|
+ * that this flag is set before conversion to TSC is attempted.
|
|
|
+ *
|
|
|
+ * Return:
|
|
|
+ * struct system_counterval_t - system counter value with the pointer to the
|
|
|
+ * corresponding clocksource
|
|
|
+ * @cycles: System counter value
|
|
|
+ * @cs: Clocksource corresponding to system counter value. Used
|
|
|
+ * by timekeeping code to verify comparibility of two cycle
|
|
|
+ * values.
|
|
|
+ */
|
|
|
+
|
|
|
+struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns)
|
|
|
+{
|
|
|
+ u64 tmp, res, rem;
|
|
|
+
|
|
|
+ rem = do_div(art_ns, USEC_PER_SEC);
|
|
|
+
|
|
|
+ res = art_ns * tsc_khz;
|
|
|
+ tmp = rem * tsc_khz;
|
|
|
+
|
|
|
+ do_div(tmp, USEC_PER_SEC);
|
|
|
+ res += tmp;
|
|
|
+
|
|
|
+ return (struct system_counterval_t) { .cs = art_related_clocksource,
|
|
|
+ .cycles = res};
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(convert_art_ns_to_tsc);
|
|
|
+
|
|
|
+
|
|
|
static void tsc_refine_calibration_work(struct work_struct *work);
|
|
|
static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
|
|
|
/**
|