From: Lakshmi Sowjanya D <lakshmi.sowjanya.d@xxxxxxxxx> Add a function to convert TSC(Time Stamp Capture) time to ART. The Intel(R) PMC Timed I/O device uses ART to trigger output events. The TSC to ART translation converts the TSC value yielded by ktime_convert_real_to_system_counter() to ART. The conversion is required to program the COMPV register that will be compared against the art time to generate output events. Co-developed-by: Christopher Hall <christopher.s.hall@xxxxxxxxx> Signed-off-by: Christopher Hall <christopher.s.hall@xxxxxxxxx> Signed-off-by: Tamal Saha <tamal.saha@xxxxxxxxx> Signed-off-by: Lakshmi Sowjanya D <lakshmi.sowjanya.d@xxxxxxxxx> Reviewed-by: Mark Gross <mgross@xxxxxxxxxxxxxxx> --- arch/x86/include/asm/tsc.h | 3 +++ arch/x86/kernel/tsc.c | 35 ++++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index a50b0102e5c1..f1de7ede3ec9 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -8,6 +8,8 @@ #include <asm/processor.h> #include <asm/cpufeature.h> +struct system_counterval_t; + /* * Standard way to access the cycle counter. */ @@ -29,6 +31,7 @@ static inline cycles_t get_cycles(void) } extern u64 read_art_time(void); +extern int convert_tsc_to_art(const struct system_counterval_t *tsc, u64 *art); extern struct system_counterval_t convert_art_to_tsc(u64 art); extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns); diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index bbab6cf1a73b..040109228100 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -1231,22 +1231,43 @@ int unsynchronized_tsc(void) } /* - * Converts the current TSC to the current ART value using conversion + * Converts input TSC to the corresponding ART value using conversion * factors discovered by detect_art() */ -u64 read_art_time(void) +int convert_tsc_to_art(const struct system_counterval_t *system_counter, u64 *art) { - u64 tsc, tmp, res, rem; + u64 tmp, res, rem; + + if (system_counter->cs != art_related_clocksource) + return -EINVAL; - tsc = read_tsc(NULL) - art_to_tsc_offset; - rem = do_div(tsc, art_to_tsc_numerator); + res = system_counter->cycles - art_to_tsc_offset; + rem = do_div(res, art_to_tsc_numerator); - res = tsc * art_to_tsc_denominator; + *art = res * art_to_tsc_denominator; tmp = rem * art_to_tsc_denominator; do_div(tmp, art_to_tsc_numerator); + *art += tmp; + + return 0; +} +EXPORT_SYMBOL(convert_tsc_to_art); + +/* + * Converts the current TSC to the current ART value using conversion + * factors discovered by detect_art() + */ +u64 read_art_time(void) +{ + struct system_counterval_t tsc; + u64 art = 0; + + tsc.cs = art_related_clocksource; + tsc.cycles = read_tsc(NULL); + convert_tsc_to_art(&tsc, &art); - return res + tmp; + return art; } EXPORT_SYMBOL(read_art_time); -- 2.17.1