KVM: selftests: Expand negative testing of guest writes to PERF_CAPABILITIES
[linux-block.git] / tools / testing / selftests / kvm / x86_64 / vmx_pmu_caps_test.c
CommitLineData
f88d4f2f
LX
1// SPDX-License-Identifier: GPL-2.0
2/*
825be3b5 3 * Test for VMX-pmu perf capability msr
f88d4f2f
LX
4 *
5 * Copyright (C) 2021 Intel Corporation
6 *
825be3b5
YW
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.
f88d4f2f
LX
12 */
13
14#define _GNU_SOURCE /* for program_invocation_short_name */
15#include <sys/ioctl.h>
16
37f4e79c
SC
17#include <linux/bitmap.h>
18
f88d4f2f
LX
19#include "kvm_util.h"
20#include "vmx.h"
21
f88d4f2f
LX
22#define PMU_CAP_LBR_FMT 0x3f
23
f88d4f2f
LX
24union perf_capabilities {
25 struct {
26 u64 lbr_format:6;
27 u64 pebs_trap:1;
28 u64 pebs_arch_reg:1;
29 u64 pebs_format:4;
30 u64 smm_freeze:1;
31 u64 full_width_write:1;
32 u64 pebs_baseline:1;
33 u64 perf_metrics:1;
34 u64 pebs_output_pt_available:1;
35 u64 anythread_deprecated:1;
36 };
37 u64 capabilities;
38};
39
37f4e79c
SC
40/*
41 * The LBR format and most PEBS features are immutable, all other features are
42 * fungible (if supported by the host and KVM).
43 */
44static const union perf_capabilities immutable_caps = {
45 .lbr_format = -1,
46 .pebs_trap = 1,
47 .pebs_arch_reg = 1,
48 .pebs_format = -1,
49 .pebs_baseline = 1,
50};
51
a2a34d14
SC
52static const union perf_capabilities format_caps = {
53 .lbr_format = -1,
54 .pebs_format = -1,
55};
56
baa36dac 57static void guest_code(uint64_t current_val)
f88d4f2f 58{
baa36dac
SC
59 uint8_t vector;
60 int i;
61
62 vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES, current_val);
63 GUEST_ASSERT_2(vector == GP_VECTOR, current_val, vector);
64
65 vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES, 0);
66 GUEST_ASSERT_2(vector == GP_VECTOR, 0, vector);
67
68 for (i = 0; i < 64; i++) {
69 vector = wrmsr_safe(MSR_IA32_PERF_CAPABILITIES,
70 current_val ^ BIT_ULL(i));
71 GUEST_ASSERT_2(vector == GP_VECTOR,
72 current_val ^ BIT_ULL(i), vector);
73 }
74
75 GUEST_DONE();
76}
77
78/*
79 * Verify that guest WRMSRs to PERF_CAPABILITIES #GP regardless of the value
80 * written, that the guest always sees the userspace controlled value, and that
81 * PERF_CAPABILITIES is immutable after KVM_RUN.
82 */
83static void test_guest_wrmsr_perf_capabilities(union perf_capabilities host_cap)
84{
85 struct kvm_vcpu *vcpu;
86 struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, guest_code);
87 struct ucall uc;
88
89 vm_init_descriptor_tables(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_2(uc, "val = 0x%lx, vector = %lu");
100 break;
101 case UCALL_DONE:
102 break;
103 default:
104 TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
105 }
106
107 ASSERT_EQ(vcpu_get_msr(vcpu, MSR_IA32_PERF_CAPABILITIES), host_cap.capabilities);
108
109 kvm_vm_free(vm);
f88d4f2f
LX
110}
111
710fb612
SC
112/*
113 * Verify KVM allows writing PERF_CAPABILITIES with all KVM-supported features
114 * enabled, as well as '0' (to disable all features).
115 */
116static void test_basic_perf_capabilities(union perf_capabilities host_cap)
117{
118 struct kvm_vcpu *vcpu;
119 struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
120
121 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, 0);
710fb612 122 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
710fb612
SC
123
124 kvm_vm_free(vm);
125}
126
e4d86fb9 127static void test_fungible_perf_capabilities(union perf_capabilities host_cap)
f88d4f2f 128{
37f4e79c
SC
129 const uint64_t fungible_caps = host_cap.capabilities & ~immutable_caps.capabilities;
130
d8b5b5d1 131 struct kvm_vcpu *vcpu;
baa36dac 132 struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
37f4e79c 133 int bit;
f88d4f2f 134
37f4e79c
SC
135 for_each_set_bit(bit, &fungible_caps, 64) {
136 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, BIT_ULL(bit));
137 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,
138 host_cap.capabilities & ~BIT_ULL(bit));
139 }
140 vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, host_cap.capabilities);
f88d4f2f 141
e4d86fb9
SC
142 kvm_vm_free(vm);
143}
144
a2a34d14
SC
145/*
146 * Verify KVM rejects attempts to set unsupported and/or immutable features in
147 * PERF_CAPABILITIES. Note, LBR format and PEBS format need to be validated
148 * separately as they are multi-bit values, e.g. toggling or setting a single
149 * bit can generate a false positive without dedicated safeguards.
150 */
e4d86fb9
SC
151static void test_immutable_perf_capabilities(union perf_capabilities host_cap)
152{
a2a34d14
SC
153 const uint64_t reserved_caps = (~host_cap.capabilities |
154 immutable_caps.capabilities) &
155 ~format_caps.capabilities;
156
e4d86fb9
SC
157 struct kvm_vcpu *vcpu;
158 struct kvm_vm *vm = vm_create_with_one_vcpu(&vcpu, NULL);
159 uint64_t val;
a2a34d14
SC
160 int r, bit;
161
162 for_each_set_bit(bit, &reserved_caps, 64) {
163 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES,
164 host_cap.capabilities ^ BIT_ULL(bit));
165 TEST_ASSERT(!r, "%s immutable feature 0x%llx (bit %d) didn't fail",
166 host_cap.capabilities & BIT_ULL(bit) ? "Setting" : "Clearing",
167 BIT_ULL(bit), bit);
168 }
e4d86fb9 169
9d27d461 170 /*
e4d86fb9
SC
171 * KVM only supports the host's native LBR format, as well as '0' (to
172 * disable LBR support). Verify KVM rejects all other LBR formats.
9d27d461
SC
173 */
174 for (val = 1; val <= PMU_CAP_LBR_FMT; val++) {
175 if (val == (host_cap.capabilities & PMU_CAP_LBR_FMT))
176 continue;
177
a2a34d14
SC
178 r = _vcpu_set_msr(vcpu, MSR_IA32_PERF_CAPABILITIES, val);
179 TEST_ASSERT(!r, "Bad LBR FMT = 0x%lx didn't fail", val);
9d27d461 180 }
a2a34d14 181
e4d86fb9
SC
182 kvm_vm_free(vm);
183}
184
185int main(int argc, char *argv[])
186{
187 union perf_capabilities host_cap;
188
189 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_PDCM));
190
191 TEST_REQUIRE(kvm_cpu_has_p(X86_PROPERTY_PMU_VERSION));
192 TEST_REQUIRE(kvm_cpu_property(X86_PROPERTY_PMU_VERSION) > 0);
193
194 host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);
e4d86fb9 195
b1b70562
SC
196 TEST_ASSERT(host_cap.full_width_write,
197 "Full-width writes should always be supported");
198
710fb612 199 test_basic_perf_capabilities(host_cap);
e4d86fb9
SC
200 test_fungible_perf_capabilities(host_cap);
201 test_immutable_perf_capabilities(host_cap);
baa36dac 202 test_guest_wrmsr_perf_capabilities(host_cap);
f88d4f2f 203
825be3b5 204 printf("Completed perf capability tests.\n");
f88d4f2f 205}