From: Sean Christopherson <seanjc@google.com>
To: Jim Mattson <jmattson@google.com>
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH v3 2/2] KVM: selftests: Test behavior of KVM_X86_DISABLE_EXITS_APERFMPERF
Date: Mon, 28 Apr 2025 18:26:37 -0700 [thread overview]
Message-ID: <aBAqzZOiCCYWgOrM@google.com> (raw)
In-Reply-To: <20250321221444.2449974-3-jmattson@google.com>
On Fri, Mar 21, 2025, Jim Mattson wrote:
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <pthread.h>
> +#include <sched.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdint.h>
> +#include <unistd.h>
> +#include <asm/msr-index.h>
> +
> +#include "kvm_util.h"
> +#include "processor.h"
> +#include "test_util.h"
> +
> +#define NUM_ITERATIONS 100
> +
> +static void pin_thread(int cpu)
> +{
> + cpu_set_t cpuset;
> + int rc;
> +
> + CPU_ZERO(&cpuset);
> + CPU_SET(cpu, &cpuset);
> +
> + rc = pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
> + TEST_ASSERT(rc == 0, "%s: Can't set thread affinity", __func__);
Heh, you copy-pasted this from hardware_disable_test.c, didn't you? :-)
Would it make sense to turn this into a generic API that takes care of the entire
sched_getcpu() => pthread_setaffinity_np()? E.g. kvm_pin_task_to_current_cpu().
I suspect there are other (potential) tests that don't care about what CPU they
run on, so long as the test is pinned.
> +}
> +
> +static int open_dev_msr(int cpu)
> +{
> + char path[PATH_MAX];
> + int msr_fd;
> +
> + snprintf(path, sizeof(path), "/dev/cpu/%d/msr", cpu);
> + msr_fd = open(path, O_RDONLY);
> + __TEST_REQUIRE(msr_fd >= 0, "Can't open %s for read", path);
Please use open_path_or_exit().
Hmm, and I'm planning on posting a small series to add a variant that takes an
ENOENT message, and spits out a (hopefully) helpful message for the EACCES case.
It would be nice to have this one spit out something like "Is msk.ko loaded?",
but I would say don't worry about trying to coordinate anything. Worst case
scenario we can add a help message when the dust settles.
> + return msr_fd;
> +}
> +
> +static uint64_t read_dev_msr(int msr_fd, uint32_t msr)
> +{
> + uint64_t data;
> + ssize_t rc;
> +
> + rc = pread(msr_fd, &data, sizeof(data), msr);
> + TEST_ASSERT(rc == sizeof(data), "Read of MSR 0x%x failed", msr);
> +
> + return data;
> +}
> +
> +static void guest_code(void)
> +{
> + int i;
> +
> + for (i = 0; i < NUM_ITERATIONS; i++) {
> + uint64_t aperf = rdmsr(MSR_IA32_APERF);
> + uint64_t mperf = rdmsr(MSR_IA32_MPERF);
> +
> + GUEST_SYNC2(aperf, mperf);
Does the test generate multiple RDMSR per MSR if you do:
GUEST_SYNC2(rdmsr(MSR_IA32_APERF), rdmsr(MSR_IA32_MPERF));
If the code generation comes out
> + }
> +
> + GUEST_DONE();
> +}
> +
> +static bool kvm_can_disable_aperfmperf_exits(struct kvm_vm *vm)
> +{
> + int flags = vm_check_cap(vm, KVM_CAP_X86_DISABLE_EXITS);
> +
> + return flags & KVM_X86_DISABLE_EXITS_APERFMPERF;
> +}
Please don't add one-off helpers like this, especially when they're the condition
for TEST_REQUIRE(). I *want* the gory details if the test is skipped, so that I
don't have to go look at the source code to figure out what's missing.
And it's literally more code.
> +
> +int main(int argc, char *argv[])
> +{
> + uint64_t host_aperf_before, host_mperf_before;
> + int cpu = sched_getcpu();
> + struct kvm_vcpu *vcpu;
> + struct kvm_vm *vm;
> + int msr_fd;
> + int i;
> +
> + pin_thread(cpu);
> +
> + msr_fd = open_dev_msr(cpu);
> +
> + /*
> + * This test requires a non-standard VM initialization, because
> + * KVM_ENABLE_CAP cannot be used on a VM file descriptor after
> + * a VCPU has been created.
Hrm, we should really sort this out. Every test that needs to enable a capability
is having to copy+paste this pattern. I don't love the idea of expanding
__vm_create_with_one_vcpu(), but there's gotta be a solution that isn't horrible,
and anything is better than endly copy paste.
> + */
> + vm = vm_create(1);
> +
> + TEST_REQUIRE(kvm_can_disable_aperfmperf_exits(vm));
TEST_REQUIRE(vm_check_cap(vm, KVM_CAP_X86_DISABLE_EXITS) &
KVM_X86_DISABLE_EXITS_APERFMPERF);
> +
> + vm_enable_cap(vm, KVM_CAP_X86_DISABLE_EXITS,
> + KVM_X86_DISABLE_EXITS_APERFMPERF);
> +
> + vcpu = vm_vcpu_add(vm, 0, guest_code);
> +
> + host_aperf_before = read_dev_msr(msr_fd, MSR_IA32_APERF);
> + host_mperf_before = read_dev_msr(msr_fd, MSR_IA32_MPERF);
> +
> + for (i = 0; i < NUM_ITERATIONS; i++) {
> + uint64_t host_aperf_after, host_mperf_after;
> + uint64_t guest_aperf, guest_mperf;
> + struct ucall uc;
> +
> + vcpu_run(vcpu);
> + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
> +
> + switch (get_ucall(vcpu, &uc)) {
> + case UCALL_DONE:
> + break;
> + case UCALL_ABORT:
> + REPORT_GUEST_ASSERT(uc);
> + case UCALL_SYNC:
> + guest_aperf = uc.args[0];
> + guest_mperf = uc.args[1];
> +
> + host_aperf_after = read_dev_msr(msr_fd, MSR_IA32_APERF);
> + host_mperf_after = read_dev_msr(msr_fd, MSR_IA32_MPERF);
> +
> + TEST_ASSERT(host_aperf_before < guest_aperf,
> + "APERF: host_before (%lu) >= guest (%lu)",
> + host_aperf_before, guest_aperf);
Honest question, is decimal really better than hex for these?
> + TEST_ASSERT(guest_aperf < host_aperf_after,
> + "APERF: guest (%lu) >= host_after (%lu)",
> + guest_aperf, host_aperf_after);
> + TEST_ASSERT(host_mperf_before < guest_mperf,
> + "MPERF: host_before (%lu) >= guest (%lu)",
> + host_mperf_before, guest_mperf);
> + TEST_ASSERT(guest_mperf < host_mperf_after,
> + "MPERF: guest (%lu) >= host_after (%lu)",
> + guest_mperf, host_mperf_after);
> +
> + host_aperf_before = host_aperf_after;
> + host_mperf_before = host_mperf_after;
> +
> + break;
> + }
> + }
> +
> + TEST_ASSERT_EQ(i, NUM_ITERATIONS);
Why?
next prev parent reply other threads:[~2025-04-29 1:26 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-21 22:14 [PATCH v3 0/2] KVM: x86: Provide a capability to disable APERF/MPERF read intercepts Jim Mattson
2025-03-21 22:14 ` [PATCH v3 1/2] " Jim Mattson
2025-04-28 22:58 ` Sean Christopherson
2025-05-05 15:51 ` Jim Mattson
2025-05-05 16:34 ` Sean Christopherson
2025-05-07 18:09 ` Jim Mattson
2025-03-21 22:14 ` [PATCH v3 2/2] KVM: selftests: Test behavior of KVM_X86_DISABLE_EXITS_APERFMPERF Jim Mattson
2025-04-29 1:26 ` Sean Christopherson [this message]
2025-05-07 18:19 ` Jim Mattson
2025-05-07 19:54 ` 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=aBAqzZOiCCYWgOrM@google.com \
--to=seanjc@google.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.