From nobody Thu Dec 18 01:37:29 2025 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E0F4727A93B for ; Fri, 30 May 2025 18:52:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748631177; cv=none; b=uAEEXzA8BByRFNdYoxmHkwEhjwia04AW6aAgepG7QiRRiGaznIANZ5xn2fBKueJkhLcOcbc0xYtrRBO3szhoc01PBHoB0D4q9cYscS4/TI+8O7cn38fKa2KsCMAChp+/LKoFDGm1A9md3avxQjih7rIRHGZC38LHMXZ/qHFdEGE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1748631177; c=relaxed/simple; bh=mhgEUlAtkWDdE5BIbN7qMPFDGIrHHNY/5plu1NKbztw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Si/oZWvGVvMEbahQMxt5r/7KCePzP/J7tnk/7CrJGEWOdSpfwJYY1yJ+ZN1NPd83hqHA8vZGNiiXMO2BdKVTLQ4HzPAymb/XewQcmkiQjpwYGxOWCubBaoOg0+ZLpYA5E9nwLTUKm8CRWfkRjLI0n0hk1zF/dPRYeVeACPQJrBs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=knUKkQM4; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jmattson.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="knUKkQM4" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-311ef4fb5fdso2299380a91.1 for ; Fri, 30 May 2025 11:52:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1748631175; x=1749235975; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=DM1PeXelXOrCQthfhESdwyT2BuwrcpH6F3C9kXkDTdw=; b=knUKkQM493mWtdIBtNYvDGiHbZXh94lPlQy9mucGuf6sJvG+mb47BCpaczP5kCn7Jr 0bhRhXCxQ9HFfoERs9c8tVBB9fyIwKhxfulVmMqpyhUT6x+V5wn5LDuq0EsU9e/ziQ+j ZWR0+KCpeOIiQ9aNiEKCHCmz0nHbS4JarrBAmOMfTZmj+I+yUIwCbEM+I0zrVH1telKm zi5iyGJAHZ0tDgXZLEjfs6KdU2dxTC3d2rVnxMUM0g9QdwkYpWDhPwTjwBgZiH3syKKl TLWF38rIyqEqrKfkcjVGvo5iX9XD/Op+PCR48QYlZZO4tbo75sCZXTm/BYjL0F0s9GJQ +irg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1748631175; x=1749235975; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=DM1PeXelXOrCQthfhESdwyT2BuwrcpH6F3C9kXkDTdw=; b=v20io/cIcHmEKbrEHNKELXTBbIxTeauI6eeGqk1tfSoMu09SIuheUTFWdZUTYtBYK1 DGNpsfvG6k3aYwQhlK7eW7Haham1425XRPqltKtaibWhU/5th8Vzl4W1txLK0CYvEvgW qEg6X+sBdIM9iA8rCkOVr+rGQLWliam9m4GUrXM0Ao1fe3o9qhWcvas07pYYYn+Nv9Uu B+bg5x5UGf5av8L7o9QTf8puq9amHjBaVMAtKajv2tgjRGJBe4Es5zHPJYrMFsodTuzD OxlV++tN1pCuUfFwkQlVhuSRjyJ+jjQtOZ6jU7+WVWSThn2HY687G2KJ6UM8DN4xgmwG U/DQ== X-Gm-Message-State: AOJu0YyW61x38gc68dE+nulhzxnKU16tGny0xl0GhOFMPh5sTBMG+AjL IixYSnJxTQf0w53dz2IHnirWhf3bn4Onp3p2DuTTzqZuHQ2POWNYUX2UEiKGH+JCqbIX92hYvw4 NBSSSO5pbmvkrHmQKPHIT4qoV4b7NHRIu2DmMtRXblpmHScOgPBDl0S7lqe8rdTGa+AZa20hHmy m/YmcIrhU8zqjptxf4XEDCmY+MwPUrQfcMhVy7BYV8sA7NpOJgkG7Z6X8= X-Google-Smtp-Source: AGHT+IGJy575wE5okiwZRZEZxyJYX3DS6QneORxGJCc2vLIidcgnpO9oZlLrQP9p7hgo6MrAXFbbDzTbr2mhIQ== X-Received: from pjbcz16.prod.google.com ([2002:a17:90a:d450:b0:311:c20d:676d]) (user=jmattson job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:3b90:b0:311:eb85:96df with SMTP id 98e67ed59e1d1-31241531935mr7475336a91.17.1748631174984; Fri, 30 May 2025 11:52:54 -0700 (PDT) Date: Fri, 30 May 2025 11:52:25 -0700 In-Reply-To: <20250530185239.2335185-1-jmattson@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250530185239.2335185-1-jmattson@google.com> X-Mailer: git-send-email 2.49.0.1204.g71687c7c1d-goog Message-ID: <20250530185239.2335185-4-jmattson@google.com> Subject: [PATCH v4 3/3] KVM: selftests: Test behavior of KVM_X86_DISABLE_EXITS_APERFMPERF From: Jim Mattson To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Sean Christopherson , Paolo Bonzini Cc: Jim Mattson Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For a VCPU thread pinned to a single LPU, verify that interleaved host and guest reads of IA32_[AM]PERF return strictly increasing values when APERFMPERF exiting is disabled. Signed-off-by: Jim Mattson --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../testing/selftests/kvm/include/kvm_util.h | 2 + tools/testing/selftests/kvm/lib/kvm_util.c | 17 +++ .../selftests/kvm/x86/aperfmperf_test.c | 132 ++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86/aperfmperf_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selft= ests/kvm/Makefile.kvm index 3e786080473d..8d42a3bd0dd8 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -131,6 +131,7 @@ TEST_GEN_PROGS_x86 +=3D x86/amx_test TEST_GEN_PROGS_x86 +=3D x86/max_vcpuid_cap_test TEST_GEN_PROGS_x86 +=3D x86/triple_fault_event_test TEST_GEN_PROGS_x86 +=3D x86/recalc_apic_map_test +TEST_GEN_PROGS_x86 +=3D x86/aperfmperf_test TEST_GEN_PROGS_x86 +=3D access_tracking_perf_test TEST_GEN_PROGS_x86 +=3D coalesced_io_test TEST_GEN_PROGS_x86 +=3D dirty_log_perf_test diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing= /selftests/kvm/include/kvm_util.h index 93013564428b..43a1bef10ec0 100644 --- a/tools/testing/selftests/kvm/include/kvm_util.h +++ b/tools/testing/selftests/kvm/include/kvm_util.h @@ -1158,4 +1158,6 @@ bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_= t paddr); =20 uint32_t guest_get_vcpuid(void); =20 +int pin_task_to_one_cpu(void); + #endif /* SELFTEST_KVM_UTIL_H */ diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/sel= ftests/kvm/lib/kvm_util.c index 5649cf2f40e8..b6c707ab92d7 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -10,6 +10,7 @@ #include "ucall_common.h" =20 #include +#include #include #include #include @@ -2321,3 +2322,19 @@ bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr= _t paddr) pg =3D paddr >> vm->page_shift; return sparsebit_is_set(region->protected_phy_pages, pg); } + +int pin_task_to_one_cpu(void) +{ + int cpu =3D sched_getcpu(); + cpu_set_t cpuset; + int rc; + + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + + rc =3D pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset); + TEST_ASSERT(rc =3D=3D 0, "%s: Can't set thread affinity", __func__); + + return cpu; +} + diff --git a/tools/testing/selftests/kvm/x86/aperfmperf_test.c b/tools/test= ing/selftests/kvm/x86/aperfmperf_test.c new file mode 100644 index 000000000000..64d976156693 --- /dev/null +++ b/tools/testing/selftests/kvm/x86/aperfmperf_test.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test for KVM_X86_DISABLE_EXITS_APERFMPERF + * + * Copyright (C) 2025, Google LLC. + * + * Test the ability to disable VM-exits for rdmsr of IA32_APERF and + * IA32_MPERF. When these VM-exits are disabled, reads of these MSRs + * return the host's values. + * + * Note: Requires read access to /dev/cpu//msr to read host MSRs. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" + +#define NUM_ITERATIONS 100 + +static int open_dev_msr(int cpu) +{ + char path[PATH_MAX]; + + snprintf(path, sizeof(path), "/dev/cpu/%d/msr", cpu); + return open_path_or_exit(path, O_RDONLY); +} + +static uint64_t read_dev_msr(int msr_fd, uint32_t msr) +{ + uint64_t data; + ssize_t rc; + + rc =3D pread(msr_fd, &data, sizeof(data), msr); + TEST_ASSERT(rc =3D=3D sizeof(data), "Read of MSR 0x%x failed", msr); + + return data; +} + +static void guest_code(void) +{ + int i; + + for (i =3D 0; i < NUM_ITERATIONS; i++) + GUEST_SYNC2(rdmsr(MSR_IA32_APERF), rdmsr(MSR_IA32_MPERF)); + + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + uint64_t host_aperf_before, host_mperf_before; + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + int msr_fd; + int cpu; + int i; + + cpu =3D pin_task_to_one_cpu(); + + msr_fd =3D 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. + */ + vm =3D vm_create(1); + + 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 =3D vm_vcpu_add(vm, 0, guest_code); + + host_aperf_before =3D read_dev_msr(msr_fd, MSR_IA32_APERF); + host_mperf_before =3D read_dev_msr(msr_fd, MSR_IA32_MPERF); + + for (i =3D 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 =3D uc.args[0]; + guest_mperf =3D uc.args[1]; + + host_aperf_after =3D read_dev_msr(msr_fd, MSR_IA32_APERF); + host_mperf_after =3D read_dev_msr(msr_fd, MSR_IA32_MPERF); + + TEST_ASSERT(host_aperf_before < guest_aperf, + "APERF: host_before (0x%" PRIx64 ") >=3D guest (0x%" PRIx64 ")", + host_aperf_before, guest_aperf); + TEST_ASSERT(guest_aperf < host_aperf_after, + "APERF: guest (0x%" PRIx64 ") >=3D host_after (0x%" PRIx64 ")", + guest_aperf, host_aperf_after); + TEST_ASSERT(host_mperf_before < guest_mperf, + "MPERF: host_before (0x%" PRIx64 ") >=3D guest (0x%" PRIx64 ")", + host_mperf_before, guest_mperf); + TEST_ASSERT(guest_mperf < host_mperf_after, + "MPERF: guest (0x%" PRIx64 ") >=3D host_after (0x%" PRIx64 ")", + guest_mperf, host_mperf_after); + + host_aperf_before =3D host_aperf_after; + host_mperf_before =3D host_mperf_after; + + break; + } + } + + kvm_vm_free(vm); + close(msr_fd); + + return 0; +} --=20 2.49.0.1204.g71687c7c1d-goog