Messages in this thread | | | Date | Wed, 7 Dec 2022 23:51:18 +0800 | Subject | Re: [PATCH kvm-unit-tests] x86/pmu: Add Intel Guest Transactional (commited) cycles testcase | From | "Yang, Weijiang" <> |
| |
On 12/7/2022 3:15 PM, Like Xu wrote: > From: Like Xu <likexu@tencent.com> > > 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@tencent.com> > --- > 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; Since the test case is for xbegin/xend, HLE check may omit as it's for other X-instructions. > + > + 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); The purpose is to collect total cycles, why not print out the data here for each GP counter? > + } > + > + 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)
| |