From: Like Xu <likexu@xxxxxxxxxxx> On Intel platforms with TSX feature, pmu users in guest can collect the commited or total transactional cycles for a tsx-enabled workload, adding new test cases to cover them, as they are not strictly the same as normal hardware events from the KVM implementation point of view. Signed-off-by: Like Xu <likexu@xxxxxxxxxxx> --- x86/pmu.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/x86/pmu.c b/x86/pmu.c index 72c2c9c..d4c6813 100644 --- a/x86/pmu.c +++ b/x86/pmu.c @@ -20,7 +20,7 @@ typedef struct { uint32_t ctr; - uint32_t config; + uint64_t config; uint64_t count; int idx; } pmu_counter_t; @@ -547,6 +547,76 @@ static void check_emulated_instr(void) report_prefix_pop(); } +#define _XBEGIN_STARTED (~0u) + +static inline int _xbegin(void) +{ + int ret = _XBEGIN_STARTED; + asm volatile(".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); + return ret; +} + +static inline void _xend(void) +{ + asm volatile(".byte 0x0f,0x01,0xd5" ::: "memory"); +} + +int *ptr; + +static void tsx_fault(void) +{ + int value = 0; + + ptr = NULL; + if(_xbegin() == _XBEGIN_STARTED) { + value++; + // causes abort + *ptr = value; + _xend(); + } +} + +static void tsx_normal(void) +{ + int value = 0; + + if(_xbegin() == _XBEGIN_STARTED) { + value++; + _xend(); + } +} + +static void check_tsx_cycles(void) +{ + pmu_counter_t cnt; + int i; + + if (!this_cpu_has(X86_FEATURE_RTM) || !this_cpu_has(X86_FEATURE_HLE)) + return; + + report_prefix_push("TSX cycles"); + + for (i = 0; i < pmu.nr_gp_counters; i++) { + cnt.ctr = MSR_GP_COUNTERx(i); + + if (i == 2) + /* Transactional cycles commited only on gp counter 2 */ + cnt.config = EVNTSEL_OS | EVNTSEL_USR | 0x30000003c; + else + /* Transactional cycles */ + cnt.config = EVNTSEL_OS | EVNTSEL_USR | 0x10000003c; + + start_event(&cnt); + tsx_fault(); + tsx_normal(); + stop_event(&cnt); + + report(cnt.count > 0, "gp cntr-%d", i); + } + + report_prefix_pop(); +} + static void check_counters(void) { if (is_fep_available()) @@ -559,6 +629,7 @@ static void check_counters(void) check_counter_overflow(); check_gp_counter_cmask(); check_running_counter_wrmsr(); + check_tsx_cycles(); } static void do_unsupported_width_counter_write(void *index) -- 2.38.1