Skip to content

Commit a8a37f5

Browse files
committed
KVM: selftests: Extend PMU counters test to validate RDPMC after WRMSR
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>
1 parent b5e66df commit a8a37f5

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

tools/testing/selftests/kvm/x86_64/pmu_counters_test.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,30 @@ __GUEST_ASSERT(expect_gp ? vector == GP_VECTOR : !vector, \
325325
"Expected " #insn "(0x%x) to yield 0x%lx, got 0x%lx", \
326326
msr, expected_val, val);
327327

328+
static void guest_test_rdpmc(uint32_t rdpmc_idx, bool expect_success,
329+
uint64_t expected_val)
330+
{
331+
uint8_t vector;
332+
uint64_t val;
333+
334+
vector = rdpmc_safe(rdpmc_idx, &val);
335+
GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
336+
if (expect_success)
337+
GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);
338+
339+
if (!is_forced_emulation_enabled)
340+
return;
341+
342+
vector = rdpmc_safe_fep(rdpmc_idx, &val);
343+
GUEST_ASSERT_PMC_MSR_ACCESS(RDPMC, rdpmc_idx, !expect_success, vector);
344+
if (expect_success)
345+
GUEST_ASSERT_PMC_VALUE(RDPMC, rdpmc_idx, val, expected_val);
346+
}
347+
328348
static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters,
329349
uint8_t nr_counters, uint32_t or_mask)
330350
{
351+
const bool pmu_has_fast_mode = !guest_get_pmu_version();
331352
uint8_t i;
332353

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

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

390+
/*
391+
* Redo the read tests with RDPMC, which has different indexing
392+
* semantics and additional capabilities.
393+
*/
394+
rdpmc_idx = i;
395+
if (base_msr == MSR_CORE_PERF_FIXED_CTR0)
396+
rdpmc_idx |= INTEL_RDPMC_FIXED;
397+
398+
guest_test_rdpmc(rdpmc_idx, expect_success, expected_val);
399+
400+
/*
401+
* KVM doesn't support non-architectural PMUs, i.e. it should
402+
* impossible to have fast mode RDPMC. Verify that attempting
403+
* to use fast RDPMC always #GPs.
404+
*/
405+
GUEST_ASSERT(!expect_success || !pmu_has_fast_mode);
406+
rdpmc_idx |= INTEL_RDPMC_FAST;
407+
guest_test_rdpmc(rdpmc_idx, false, -1ull);
408+
368409
vector = wrmsr_safe(msr, 0);
369410
GUEST_ASSERT_PMC_MSR_ACCESS(WRMSR, msr, expect_gp, vector);
370411
}

0 commit comments

Comments
 (0)