brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · 7c92536 Raw
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