KVM: selftests: Verify post-RESET value of PERF_GLOBAL_CTRL in PMCs test
authorSean Christopherson <seanjc@google.com>
Sat, 9 Mar 2024 01:36:41 +0000 (17:36 -0800)
committerSean Christopherson <seanjc@google.com>
Mon, 8 Apr 2024 20:20:28 +0000 (13:20 -0700)
Add a guest assert in the PMU counters test to verify that KVM stuffs
the vCPU's post-RESET value to globally enable all general purpose
counters.  Per Intel's SDM,

  IA32_PERF_GLOBAL_CTRL:  Sets bits n-1:0 and clears the upper bits.

and

  Where "n" is the number of general-purpose counters available in
  the processor.

For the edge case where there are zero GP counters, follow the spirit
of the architecture, not the SDM's literal wording, which doesn't account
for this possibility and would require the CPU to set _all_ bits in
PERF_GLOBAL_CTRL.

Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://lore.kernel.org/r/20240309013641.1413400-3-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/x86_64/pmu_counters_test.c

index 29609b52f8fa0c58bfb38207ef29bf6283f43932..26c85815f7e983a33c025aa1daab6daa45c0f91b 100644 (file)
@@ -416,12 +416,30 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
 
 static void guest_test_gp_counters(void)
 {
+       uint8_t pmu_version = guest_get_pmu_version();
        uint8_t nr_gp_counters = 0;
        uint32_t base_msr;
 
-       if (guest_get_pmu_version())
+       if (pmu_version)
                nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS);
 
+       /*
+        * For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is
+        * "Sets bits n-1:0 and clears the upper bits", where 'n' is the number
+        * of GP counters.  If there are no GP counters, require KVM to leave
+        * PERF_GLOBAL_CTRL '0'.  This edge case isn't covered by the SDM, but
+        * follow the spirit of the architecture and only globally enable GP
+        * counters, of which there are none.
+        */
+       if (pmu_version > 1) {
+               uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL);
+
+               if (nr_gp_counters)
+                       GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0));
+               else
+                       GUEST_ASSERT_EQ(global_ctrl, 0);
+       }
+
        if (this_cpu_has(X86_FEATURE_PDCM) &&
            rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES)
                base_msr = MSR_IA32_PMC0;