Run a basic test to ensure we can write an arbitrary value to the core counters and read it back.
Signed-off-by: Colton Lewis coltonlewis@google.com --- .../selftests/kvm/x86_64/pmu_counters_test.c | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c index 5b240585edc5..79ca7d608e00 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c @@ -641,11 +641,65 @@ static uint8_t nr_core_counters(void) return AMD_NR_CORE_EXT_COUNTERS;
return AMD_NR_CORE_COUNTERS; +} + +static uint8_t guest_nr_core_counters(void) +{ + uint8_t nr_counters = this_cpu_property(X86_PROPERTY_NUM_PERF_CTR_CORE); + bool core_ext = this_cpu_has(X86_FEATURE_PERF_CTR_EXT_CORE); + + if (nr_counters != 0) + return nr_counters; + + if (core_ext) + return AMD_NR_CORE_EXT_COUNTERS; + + return AMD_NR_CORE_COUNTERS; + +}
+static void guest_test_rdwr_core_counters(void) +{ + bool core_ext = this_cpu_has(X86_FEATURE_PERF_CTR_EXT_CORE); + uint8_t nr_counters = guest_nr_core_counters(); + uint8_t i; + uint32_t esel_msr_base = core_ext ? MSR_F15H_PERF_CTL : MSR_K7_EVNTSEL0; + uint32_t cnt_msr_base = core_ext ? MSR_F15H_PERF_CTR : MSR_K7_PERFCTR0; + uint32_t msr_step = core_ext ? 2 : 1; + + for (i = 0; i < AMD_NR_CORE_EXT_COUNTERS; i++) { + uint64_t test_val = 0xffff; + uint32_t esel_msr = esel_msr_base + msr_step * i; + uint32_t cnt_msr = cnt_msr_base + msr_step * i; + bool expect_gp = !(i < nr_counters); + uint8_t vector; + uint64_t val; + + /* Test event selection register. */ + vector = wrmsr_safe(esel_msr, test_val); + GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, esel_msr, expect_gp, vector); + + vector = rdmsr_safe(esel_msr, &val); + GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, esel_msr, expect_gp, vector); + + if (!expect_gp) + GUEST_ASSERT_PMC_VALUE(RDMSR, esel_msr, val, test_val); + + /* Test counter register. */ + vector = wrmsr_safe(cnt_msr, test_val); + GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, cnt_msr, expect_gp, vector); + + vector = rdmsr_safe(cnt_msr, &val); + GUEST_ASSERT_PMC_MSR_ACCESS(RDMSR, cnt_msr, expect_gp, vector); + + if (!expect_gp) + GUEST_ASSERT_PMC_VALUE(RDMSR, cnt_msr, val, test_val); + } }
static void guest_test_core_counters(void) { + guest_test_rdwr_core_counters(); GUEST_DONE(); }