Skip to content

Commit

Permalink
KVM: selftests: Extend PMU counters test to validate RDPMC after WRMSR
Browse files Browse the repository at this point in the history
Extend the read/write PMU counters subtest to verify that RDPMC also reads
back the written value.  Opportunsitically verify that attempting to use
the "fast" mode of RDPMC fails, as the "fast" flag is only supported by
non-architectural PMUs, which KVM doesn't virtualize.

Tested-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://lore.kernel.org/r/20240109230250.424295-30-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
  • Loading branch information
sean-jc committed Jan 30, 2024
1 parent b5e66df commit a8a37f5
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions tools/testing/selftests/kvm/x86_64/pmu_counters_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,30 @@ __GUEST_ASSERT(expect_gp ? vector == GP_VECTOR : !vector, \
"Expected " #insn "(0x%x) to yield 0x%lx, got 0x%lx", \
msr, expected_val, val);

static void guest_test_rdpmc(uint32_t rdpmc_idx, bool expect_success,
uint64_t expected_val)
{
uint8_t vector;
uint64_t val;

vector = rdpmc_safe(rdpmc_idx, &val);
GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
if (expect_success)
GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);

if (!is_forced_emulation_enabled)
return;

vector = rdpmc_safe_fep(rdpmc_idx, &val);
GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
if (expect_success)
GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);
}

static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters,
uint8_t nr_counters, uint32_t or_mask)
{
const bool pmu_has_fast_mode = !guest_get_pmu_version();
uint8_t i;

for (i = 0; i < nr_possible_counters; i++) {
Expand All @@ -352,6 +373,7 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
const uint64_t expected_val = expect_success ? test_val : 0;
const bool expect_gp = !expect_success && msr != MSR_P6_PERFCTR0 &&
msr != MSR_P6_PERFCTR1;
uint32_t rdpmc_idx;
uint8_t vector;
uint64_t val;

Expand All @@ -365,6 +387,25 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters
if (!expect_gp)
GUEST_ASSERT_PMC_VALUE(RDMSR, msr, val, expected_val);

/*
* Redo the read tests with RDPMC, which has different indexing
* semantics and additional capabilities.
*/
rdpmc_idx = i;
if (base_msr == MSR_CORE_PERF_FIXED_CTR0)
rdpmc_idx |= INTEL_RDPMC_FIXED;

guest_test_rdpmc(rdpmc_idx, expect_success, expected_val);

/*
* KVM doesn't support non-architectural PMUs, i.e. it should
* impossible to have fast mode RDPMC. Verify that attempting
* to use fast RDPMC always #GPs.
*/
GUEST_ASSERT(!expect_success || !pmu_has_fast_mode);
rdpmc_idx |= INTEL_RDPMC_FAST;
guest_test_rdpmc(rdpmc_idx, false, -1ull);

vector = wrmsr_safe(msr, 0);
GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);
}
Expand Down

0 comments on commit a8a37f5

Please sign in to comment.