From: Like Xu <like.xu.linux@gmail.com>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Jinrong Liang <cloudliang@tencent.com>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH 3/7] KVM: selftests: Test consistency of CPUID with num of GP counters
Date: Thu, 23 Mar 2023 15:27:10 +0800 [thread overview]
Message-ID: <20230323072714.82289-4-likexu@tencent.com> (raw)
In-Reply-To: <20230323072714.82289-1-likexu@tencent.com>
From: Like Xu <likexu@tencent.com>
Add test to check if non-existent counters can be accessed in guest after
determining the number of Intel generic performance counters by CPUID.
When the num of counters is less than 3, KVM does not emulate #GP if
a counter isn't present due to compatibility MSR_P6_PERFCTRx handling.
Nor will the KVM emulate more counters than it can support.
Co-developed-by: Jinrong Liang <cloudliang@tencent.com>
Signed-off-by: Jinrong Liang <cloudliang@tencent.com>
Signed-off-by: Like Xu <likexu@tencent.com>
---
.../selftests/kvm/x86_64/pmu_cpuid_test.c | 102 ++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/tools/testing/selftests/kvm/x86_64/pmu_cpuid_test.c b/tools/testing/selftests/kvm/x86_64/pmu_cpuid_test.c
index 75434aa2a0ec..50902187d2c9 100644
--- a/tools/testing/selftests/kvm/x86_64/pmu_cpuid_test.c
+++ b/tools/testing/selftests/kvm/x86_64/pmu_cpuid_test.c
@@ -49,11 +49,31 @@ static const uint64_t arch_events[] = {
/* Association of Fixed Counters with Architectural Performance Events */
static int fixed_events[] = {1, 0, 7};
+static const uint64_t perf_caps[] = {
+ 0,
+ PMU_CAP_FW_WRITES,
+};
+
+/*
+ * KVM implements the first two non-existent counters (MSR_P6_PERFCTRx)
+ * via kvm_pr_unimpl_wrmsr() instead of #GP. It is acceptable here to test
+ * the third counter as there are usually more than 3 available gp counters.
+ */
+#define MSR_INTEL_ARCH_PMU_GPCTR (MSR_IA32_PERFCTR0 + 2)
+
static uint64_t evt_code_for_fixed_ctr(uint8_t idx)
{
return arch_events[fixed_events[idx]];
}
+static uint8_t kvm_gp_ctrs_num(void)
+{
+ const struct kvm_cpuid_entry2 *kvm_entry;
+
+ kvm_entry = get_cpuid_entry(kvm_get_supported_cpuid(), 0xa, 0);
+ return (kvm_entry->eax & GP_CTR_NUM_MASK) >> GP_CTR_NUM_OFS_BIT;
+}
+
static struct kvm_vcpu *new_vcpu(void *guest_code)
{
struct kvm_vm *vm;
@@ -98,6 +118,30 @@ static bool first_uc_arg_non_zero(struct ucall *uc, void *data)
return uc->args[1];
}
+static bool first_uc_arg_equals(struct ucall *uc, void *data)
+{
+ return uc->args[1] == (uint64_t)data;
+}
+
+static void guest_gp_handler(struct ex_regs *regs)
+{
+ GUEST_SYNC(GP_VECTOR);
+ GUEST_DONE();
+}
+
+static void guest_wr_and_rd_msrs(uint32_t base, uint64_t value,
+ uint8_t begin, uint8_t offset)
+{
+ unsigned int i;
+
+ for (i = begin; i < begin + offset; i++) {
+ wrmsr(base + i, value);
+ GUEST_SYNC(rdmsr(base + i));
+ }
+
+ GUEST_DONE();
+}
+
static void intel_guest_run_arch_event(uint8_t version, uint8_t max_gp_num,
uint8_t max_fixed_num, bool supported,
uint32_t ctr_base_msr, uint64_t evt_code)
@@ -165,6 +209,27 @@ static void test_arch_events_setup(struct kvm_vcpu *vcpu, uint8_t evt_vector,
ctr_msr, arch_events[idx]);
}
+static void test_oob_gp_counter_setup(struct kvm_vcpu *vcpu, uint8_t eax_gp_num,
+ uint64_t perf_cap)
+{
+ struct kvm_cpuid_entry2 *entry;
+ uint32_t ctr_msr = MSR_IA32_PERFCTR0;
+
+ entry = vcpu_get_cpuid_entry(vcpu, 0xa);
+ entry->eax = (entry->eax & ~GP_CTR_NUM_MASK) |
+ (eax_gp_num << GP_CTR_NUM_OFS_BIT);
+ vcpu_set_cpuid(vcpu);
+
+ if (perf_cap & PMU_CAP_FW_WRITES)
+ ctr_msr = MSR_IA32_PMC0;
+
+ vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, perf_cap);
+ vcpu_args_set(vcpu, 4, ctr_msr, 0xffff,
+ min(eax_gp_num, kvm_gp_ctrs_num()), 1);
+
+ vm_install_exception_handler(vcpu->vm, GP_VECTOR, guest_gp_handler);
+}
+
static void intel_check_arch_event_is_unavl(uint8_t idx)
{
const char *msg = "Unavailable arch event is counting.";
@@ -190,6 +255,42 @@ static void intel_check_arch_event_is_unavl(uint8_t idx)
}
}
+/* Access the first out-of-range counter register to trigger #GP */
+static void test_oob_gp_counter(uint8_t eax_gp_num, uint64_t perf_cap)
+{
+ const char *msg = "At least one unsupported GP counter is visible.";
+ struct kvm_vcpu *vcpu;
+
+ vcpu = new_vcpu(guest_wr_and_rd_msrs);
+ test_oob_gp_counter_setup(vcpu, eax_gp_num, perf_cap);
+ run_vcpu(vcpu, msg, first_uc_arg_equals, (void *)GP_VECTOR);
+ free_vcpu(vcpu);
+}
+
+static void intel_test_counters_num(void)
+{
+ uint8_t kvm_gp_num = kvm_gp_ctrs_num();
+ unsigned int i;
+
+ TEST_REQUIRE(kvm_gp_num > 2);
+
+ for (i = 0; i < ARRAY_SIZE(perf_caps); i++) {
+ /*
+ * For compatibility reasons, KVM does not emulate #GP
+ * when MSR_P6_PERFCTR[0|1] is not present, but it doesn't
+ * affect checking the presence of MSR_IA32_PMCx with #GP.
+ */
+ if (perf_caps[i] & PMU_CAP_FW_WRITES)
+ test_oob_gp_counter(0, perf_caps[i]);
+
+ test_oob_gp_counter(2, perf_caps[i]);
+ test_oob_gp_counter(kvm_gp_num, perf_caps[i]);
+
+ /* KVM doesn't emulate more counters than it can support. */
+ test_oob_gp_counter(kvm_gp_num + 1, perf_caps[i]);
+ }
+}
+
static void intel_test_arch_events(void)
{
uint8_t idx;
@@ -213,6 +314,7 @@ static void intel_test_arch_events(void)
static void intel_test_pmu_cpuid(void)
{
intel_test_arch_events();
+ intel_test_counters_num();
}
int main(int argc, char *argv[])
--
2.40.0
next prev parent reply other threads:[~2023-03-23 7:27 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-23 7:27 [PATCH 0/7] KVM: selftests: Test the consistency of the PMU's CPUID and its features Like Xu
2023-03-23 7:27 ` [PATCH 1/7] KVM: selftests: Test Intel PMU architectural events on gp counters Like Xu
2023-05-24 22:32 ` Sean Christopherson
2023-05-24 22:59 ` Jim Mattson
2023-03-23 7:27 ` [PATCH 2/7] KVM: selftests: Test Intel PMU architectural events on fixed counters Like Xu
2023-05-24 22:36 ` Sean Christopherson
2023-03-23 7:27 ` Like Xu [this message]
2023-05-24 22:44 ` [PATCH 3/7] KVM: selftests: Test consistency of CPUID with num of GP counters Sean Christopherson
2023-03-23 7:27 ` [PATCH 4/7] KVM: selftests: Test consistency of CPUID with num of Fixed counters Like Xu
2023-05-24 22:47 ` Sean Christopherson
2023-05-24 23:08 ` Jim Mattson
2023-03-23 7:27 ` [PATCH 5/7] KVM: selftests: Test Intel supported fixed counters bit mask Like Xu
2023-03-23 7:27 ` [PATCH 6/7] KVM: selftests: Test consistency of PMU MSRs with Intel PMU version Like Xu
2023-03-23 7:27 ` [PATCH 7/7] KVM: selftests: Test Intel counters' bit width emulation Like Xu
2023-05-24 22:52 ` Sean Christopherson
2023-05-24 22:53 ` [PATCH 0/7] KVM: selftests: Test the consistency of the PMU's CPUID and its features Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230323072714.82289-4-likexu@tencent.com \
--to=like.xu.linux@gmail.com \
--cc=cloudliang@tencent.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®