225 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Test for VMX-pmu perf capability msr4 *5 * Copyright (C) 2021 Intel Corporation6 *7 * Test to check the effect of various CPUID settings on8 * MSR_IA32_PERF_CAPABILITIES MSR, and check that what9 * we write with KVM_SET_MSR is _not_ modified by the guest10 * and check it can be retrieved with KVM_GET_MSR, also test11 * the invalid LBR formats are rejected.12 */13#include <sys/ioctl.h>14 15#include <linux/bitmap.h>16 17#include "kvm_test_harness.h"18#include "kvm_util.h"19#include "vmx.h"20 21static union perf_capabilities {22 struct {23 u64 lbr_format:6;24 u64 pebs_trap:1;25 u64 pebs_arch_reg:1;26 u64 pebs_format:4;27 u64 smm_freeze:1;28 u64 full_width_write:1;29 u64 pebs_baseline:1;30 u64 perf_metrics:1;31 u64 pebs_output_pt_available:1;32 u64 anythread_deprecated:1;33 };34 u64 capabilities;35} host_cap;36 37/*38 * The LBR format and most PEBS features are immutable, all other features are39 * fungible (if supported by the host and KVM).40 */41static const union perf_capabilities immutable_caps = {42 .lbr_format = -1,43 .pebs_trap = 1,44 .pebs_arch_reg = 1,45 .pebs_format = -1,46 .pebs_baseline = 1,47};48 49static const union perf_capabilities format_caps = {50 .lbr_format = -1,51 .pebs_format = -1,52};53 54static void guest_test_perf_capabilities_gp(uint64_t val)55{56 uint8_t vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES, val);57 58 __GUEST_ASSERT(vector == GP_VECTOR,59 "Expected #GP for value '0x%lx', got vector '0x%x'",60 val, vector);61}62 63static void guest_code(uint64_t current_val)64{65 int i;66 67 guest_test_perf_capabilities_gp(current_val);68 guest_test_perf_capabilities_gp(0);69 70 for (i = 0; i < 64; i++)71 guest_test_perf_capabilities_gp(current_val ^ BIT_ULL(i));72 73 GUEST_DONE();74}75 76KVM_ONE_VCPU_TEST_SUITE(vmx_pmu_caps);77 78/*79 * Verify that guest WRMSRs to PERF_CAPABILITIES #GP regardless of the value80 * written, that the guest always sees the userspace controlled value, and that81 * PERF_CAPABILITIES is immutable after KVM_RUN.82 */83KVM_ONE_VCPU_TEST(vmx_pmu_caps, guest_wrmsr_perf_capabilities, guest_code)84{85 struct ucall uc;86 int r, i;87 88 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);89 90 vcpu_args_set(vcpu, 1, host_cap.capabilities);91 vcpu_run(vcpu);92 93 switch (get_ucall(vcpu, &uc)) {94 case UCALL_ABORT:95 REPORT_GUEST_ASSERT(uc);96 break;97 case UCALL_DONE:98 break;99 default:100 TEST_FAIL("Unexpected ucall: %lu", uc.cmd);101 }102 103 TEST_ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES),104 host_cap.capabilities);105 106 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);107 108 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);109 TEST_ASSERT(!r, "Post-KVM_RUN write '0' didn't fail");110 111 for (i = 0; i < 64; i++) {112 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,113 host_cap.capabilities ^ BIT_ULL(i));114 TEST_ASSERT(!r, "Post-KVM_RUN write '0x%llx'didn't fail",115 host_cap.capabilities ^ BIT_ULL(i));116 }117}118 119/*120 * Verify KVM allows writing PERF_CAPABILITIES with all KVM-supported features121 * enabled, as well as '0' (to disable all features).122 */123KVM_ONE_VCPU_TEST(vmx_pmu_caps, basic_perf_capabilities, guest_code)124{125 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);126 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);127}128 129KVM_ONE_VCPU_TEST(vmx_pmu_caps, fungible_perf_capabilities, guest_code)130{131 const uint64_t fungible_caps = host_cap.capabilities & ~immutable_caps.capabilities;132 int bit;133 134 for_each_set_bit(bit, &fungible_caps, 64) {135 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, BIT_ULL(bit));136 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,137 host_cap.capabilities & ~BIT_ULL(bit));138 }139 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);140}141 142/*143 * Verify KVM rejects attempts to set unsupported and/or immutable features in144 * PERF_CAPABILITIES. Note, LBR format and PEBS format need to be validated145 * separately as they are multi-bit values, e.g. toggling or setting a single146 * bit can generate a false positive without dedicated safeguards.147 */148KVM_ONE_VCPU_TEST(vmx_pmu_caps, immutable_perf_capabilities, guest_code)149{150 const uint64_t reserved_caps = (~host_cap.capabilities |151 immutable_caps.capabilities) &152 ~format_caps.capabilities;153 union perf_capabilities val = host_cap;154 int r, bit;155 156 for_each_set_bit(bit, &reserved_caps, 64) {157 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,158 host_cap.capabilities ^ BIT_ULL(bit));159 TEST_ASSERT(!r, "%s immutable feature 0x%llx (bit %d) didn't fail",160 host_cap.capabilities & BIT_ULL(bit) ? "Setting" : "Clearing",161 BIT_ULL(bit), bit);162 }163 164 /*165 * KVM only supports the host's native LBR format, as well as '0' (to166 * disable LBR support). Verify KVM rejects all other LBR formats.167 */168 for (val.lbr_format = 1; val.lbr_format; val.lbr_format++) {169 if (val.lbr_format == host_cap.lbr_format)170 continue;171 172 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val.capabilities);173 TEST_ASSERT(!r, "Bad LBR FMT = 0x%x didn't fail, host = 0x%x",174 val.lbr_format, host_cap.lbr_format);175 }176 177 /* Ditto for the PEBS format. */178 for (val.pebs_format = 1; val.pebs_format; val.pebs_format++) {179 if (val.pebs_format == host_cap.pebs_format)180 continue;181 182 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val.capabilities);183 TEST_ASSERT(!r, "Bad PEBS FMT = 0x%x didn't fail, host = 0x%x",184 val.pebs_format, host_cap.pebs_format);185 }186}187 188/*189 * Test that LBR MSRs are writable when LBRs are enabled, and then verify that190 * disabling the vPMU via CPUID also disables LBR support. Set bits 2:0 of191 * LBR_TOS as those bits are writable across all uarch implementations (arch192 * LBRs will need to poke a different MSR).193 */194KVM_ONE_VCPU_TEST(vmx_pmu_caps, lbr_perf_capabilities, guest_code)195{196 int r;197 198 if (!host_cap.lbr_format)199 return;200 201 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);202 vcpu_set_msr(vcpu, MSR_LBR_TOS, 7);203 204 vcpu_clear_cpuid_entry(vcpu, X86_PROPERTY_PMU_VERSION.function);205 206 r = _vcpu_set_msr(vcpu, MSR_LBR_TOS, 7);207 TEST_ASSERT(!r, "Writing LBR_TOS should fail after disabling vPMU");208}209 210int main(int argc, char *argv[])211{212 TEST_REQUIRE(kvm_is_pmu_enabled());213 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_PDCM));214 215 TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));216 TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);217 218 host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);219 220 TEST_ASSERT(host_cap.full_width_write,221 "Full-width writes should always be supported");222 223 return test_harness_run(argc, argv);224}225