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