1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Test for x86 KVM_SET_PMU_EVENT_FILTER.
4 *
5 * Copyright (C) 2022, Google LLC.
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2.
8 *
9 * Verifies the expected behavior of allow lists and deny lists for
10 * virtual PMU events.
11 */
12
13 #define _GNU_SOURCE /* for program_invocation_short_name */
14 #include "test_util.h"
15 #include "kvm_util.h"
16 #include "processor.h"
17
18 /*
19 * In lieu of copying perf_event.h into tools...
20 */
21 #define ARCH_PERFMON_EVENTSEL_OS (1ULL << 17)
22 #define ARCH_PERFMON_EVENTSEL_ENABLE (1ULL << 22)
23
24 union cpuid10_eax {
25 struct {
26 unsigned int version_id:8;
27 unsigned int num_counters:8;
28 unsigned int bit_width:8;
29 unsigned int mask_length:8;
30 } split;
31 unsigned int full;
32 };
33
34 union cpuid10_ebx {
35 struct {
36 unsigned int no_unhalted_core_cycles:1;
37 unsigned int no_instructions_retired:1;
38 unsigned int no_unhalted_reference_cycles:1;
39 unsigned int no_llc_reference:1;
40 unsigned int no_llc_misses:1;
41 unsigned int no_branch_instruction_retired:1;
42 unsigned int no_branch_misses_retired:1;
43 } split;
44 unsigned int full;
45 };
46
47 /* End of stuff taken from perf_event.h. */
48
49 /* Oddly, this isn't in perf_event.h. */
50 #define ARCH_PERFMON_BRANCHES_RETIRED 5
51
52 #define NUM_BRANCHES 42
53
54 /*
55 * This is how the event selector and unit mask are stored in an AMD
56 * core performance event-select register. Intel's format is similar,
57 * but the event selector is only 8 bits.
58 */
59 #define EVENT(select, umask) ((select & 0xf00UL) << 24 | (select & 0xff) | \
60 (umask & 0xff) << 8)
61
62 /*
63 * "Branch instructions retired", from the Intel SDM, volume 3,
64 * "Pre-defined Architectural Performance Events."
65 */
66
67 #define INTEL_BR_RETIRED EVENT(0xc4, 0)
68
69 /*
70 * "Retired branch instructions", from Processor Programming Reference
71 * (PPR) for AMD Family 17h Model 01h, Revision B1 Processors,
72 * Preliminary Processor Programming Reference (PPR) for AMD Family
73 * 17h Model 31h, Revision B0 Processors, and Preliminary Processor
74 * Programming Reference (PPR) for AMD Family 19h Model 01h, Revision
75 * B1 Processors Volume 1 of 2.
76 */
77
78 #define AMD_ZEN_BR_RETIRED EVENT(0xc2, 0)
79
80 /*
81 * This event list comprises Intel's eight architectural events plus
82 * AMD's "retired branch instructions" for Zen[123] (and possibly
83 * other AMD CPUs).
84 */
85 static const uint64_t event_list[] = {
86 EVENT(0x3c, 0),
87 EVENT(0xc0, 0),
88 EVENT(0x3c, 1),
89 EVENT(0x2e, 0x4f),
90 EVENT(0x2e, 0x41),
91 EVENT(0xc4, 0),
92 EVENT(0xc5, 0),
93 EVENT(0xa4, 1),
94 AMD_ZEN_BR_RETIRED,
95 };
96
97 /*
98 * If we encounter a #GP during the guest PMU sanity check, then the guest
99 * PMU is not functional. Inform the hypervisor via GUEST_SYNC(0).
100 */
guest_gp_handler(struct ex_regs * regs)101 static void guest_gp_handler(struct ex_regs *regs)
102 {
103 GUEST_SYNC(0);
104 }
105
106 /*
107 * Check that we can write a new value to the given MSR and read it back.
108 * The caller should provide a non-empty set of bits that are safe to flip.
109 *
110 * Return on success. GUEST_SYNC(0) on error.
111 */
check_msr(uint32_t msr,uint64_t bits_to_flip)112 static void check_msr(uint32_t msr, uint64_t bits_to_flip)
113 {
114 uint64_t v = rdmsr(msr) ^ bits_to_flip;
115
116 wrmsr(msr, v);
117 if (rdmsr(msr) != v)
118 GUEST_SYNC(0);
119
120 v ^= bits_to_flip;
121 wrmsr(msr, v);
122 if (rdmsr(msr) != v)
123 GUEST_SYNC(0);
124 }
125
intel_guest_code(void)126 static void intel_guest_code(void)
127 {
128 check_msr(MSR_CORE_PERF_GLOBAL_CTRL, 1);
129 check_msr(MSR_P6_EVNTSEL0, 0xffff);
130 check_msr(MSR_IA32_PMC0, 0xffff);
131 GUEST_SYNC(1);
132
133 for (;;) {
134 uint64_t br0, br1;
135
136 wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
137 wrmsr(MSR_P6_EVNTSEL0, ARCH_PERFMON_EVENTSEL_ENABLE |
138 ARCH_PERFMON_EVENTSEL_OS | INTEL_BR_RETIRED);
139 wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 1);
140 br0 = rdmsr(MSR_IA32_PMC0);
141 __asm__ __volatile__("loop ." : "+c"((int){NUM_BRANCHES}));
142 br1 = rdmsr(MSR_IA32_PMC0);
143 GUEST_SYNC(br1 - br0);
144 }
145 }
146
147 /*
148 * To avoid needing a check for CPUID.80000001:ECX.PerfCtrExtCore[bit 23],
149 * this code uses the always-available, legacy K7 PMU MSRs, which alias to
150 * the first four of the six extended core PMU MSRs.
151 */
amd_guest_code(void)152 static void amd_guest_code(void)
153 {
154 check_msr(MSR_K7_EVNTSEL0, 0xffff);
155 check_msr(MSR_K7_PERFCTR0, 0xffff);
156 GUEST_SYNC(1);
157
158 for (;;) {
159 uint64_t br0, br1;
160
161 wrmsr(MSR_K7_EVNTSEL0, 0);
162 wrmsr(MSR_K7_EVNTSEL0, ARCH_PERFMON_EVENTSEL_ENABLE |
163 ARCH_PERFMON_EVENTSEL_OS | AMD_ZEN_BR_RETIRED);
164 br0 = rdmsr(MSR_K7_PERFCTR0);
165 __asm__ __volatile__("loop ." : "+c"((int){NUM_BRANCHES}));
166 br1 = rdmsr(MSR_K7_PERFCTR0);
167 GUEST_SYNC(br1 - br0);
168 }
169 }
170
171 /*
172 * Run the VM to the next GUEST_SYNC(value), and return the value passed
173 * to the sync. Any other exit from the guest is fatal.
174 */
run_vcpu_to_sync(struct kvm_vcpu * vcpu)175 static uint64_t run_vcpu_to_sync(struct kvm_vcpu *vcpu)
176 {
177 struct kvm_run *run = vcpu->run;
178 struct ucall uc;
179
180 vcpu_run(vcpu);
181 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
182 "Exit_reason other than KVM_EXIT_IO: %u (%s)\n",
183 run->exit_reason,
184 exit_reason_str(run->exit_reason));
185 get_ucall(vcpu, &uc);
186 TEST_ASSERT(uc.cmd == UCALL_SYNC,
187 "Received ucall other than UCALL_SYNC: %lu", uc.cmd);
188 return uc.args[1];
189 }
190
191 /*
192 * In a nested environment or if the vPMU is disabled, the guest PMU
193 * might not work as architected (accessing the PMU MSRs may raise
194 * #GP, or writes could simply be discarded). In those situations,
195 * there is no point in running these tests. The guest code will perform
196 * a sanity check and then GUEST_SYNC(success). In the case of failure,
197 * the behavior of the guest on resumption is undefined.
198 */
sanity_check_pmu(struct kvm_vcpu * vcpu)199 static bool sanity_check_pmu(struct kvm_vcpu *vcpu)
200 {
201 bool success;
202
203 vm_install_exception_handler(vcpu->vm, GP_VECTOR, guest_gp_handler);
204 success = run_vcpu_to_sync(vcpu);
205 vm_install_exception_handler(vcpu->vm, GP_VECTOR, NULL);
206
207 return success;
208 }
209
alloc_pmu_event_filter(uint32_t nevents)210 static struct kvm_pmu_event_filter *alloc_pmu_event_filter(uint32_t nevents)
211 {
212 struct kvm_pmu_event_filter *f;
213 int size = sizeof(*f) + nevents * sizeof(f->events[0]);
214
215 f = malloc(size);
216 TEST_ASSERT(f, "Out of memory");
217 memset(f, 0, size);
218 f->nevents = nevents;
219 return f;
220 }
221
222
223 static struct kvm_pmu_event_filter *
create_pmu_event_filter(const uint64_t event_list[],int nevents,uint32_t action)224 create_pmu_event_filter(const uint64_t event_list[],
225 int nevents, uint32_t action)
226 {
227 struct kvm_pmu_event_filter *f;
228 int i;
229
230 f = alloc_pmu_event_filter(nevents);
231 f->action = action;
232 for (i = 0; i < nevents; i++)
233 f->events[i] = event_list[i];
234
235 return f;
236 }
237
event_filter(uint32_t action)238 static struct kvm_pmu_event_filter *event_filter(uint32_t action)
239 {
240 return create_pmu_event_filter(event_list,
241 ARRAY_SIZE(event_list),
242 action);
243 }
244
245 /*
246 * Remove the first occurrence of 'event' (if any) from the filter's
247 * event list.
248 */
remove_event(struct kvm_pmu_event_filter * f,uint64_t event)249 static struct kvm_pmu_event_filter *remove_event(struct kvm_pmu_event_filter *f,
250 uint64_t event)
251 {
252 bool found = false;
253 int i;
254
255 for (i = 0; i < f->nevents; i++) {
256 if (found)
257 f->events[i - 1] = f->events[i];
258 else
259 found = f->events[i] == event;
260 }
261 if (found)
262 f->nevents--;
263 return f;
264 }
265
test_without_filter(struct kvm_vcpu * vcpu)266 static void test_without_filter(struct kvm_vcpu *vcpu)
267 {
268 uint64_t count = run_vcpu_to_sync(vcpu);
269
270 if (count != NUM_BRANCHES)
271 pr_info("%s: Branch instructions retired = %lu (expected %u)\n",
272 __func__, count, NUM_BRANCHES);
273 TEST_ASSERT(count, "Allowed PMU event is not counting");
274 }
275
test_with_filter(struct kvm_vcpu * vcpu,struct kvm_pmu_event_filter * f)276 static uint64_t test_with_filter(struct kvm_vcpu *vcpu,
277 struct kvm_pmu_event_filter *f)
278 {
279 vm_ioctl(vcpu->vm, KVM_SET_PMU_EVENT_FILTER, f);
280 return run_vcpu_to_sync(vcpu);
281 }
282
test_amd_deny_list(struct kvm_vcpu * vcpu)283 static void test_amd_deny_list(struct kvm_vcpu *vcpu)
284 {
285 uint64_t event = EVENT(0x1C2, 0);
286 struct kvm_pmu_event_filter *f;
287 uint64_t count;
288
289 f = create_pmu_event_filter(&event, 1, KVM_PMU_EVENT_DENY);
290 count = test_with_filter(vcpu, f);
291
292 free(f);
293 if (count != NUM_BRANCHES)
294 pr_info("%s: Branch instructions retired = %lu (expected %u)\n",
295 __func__, count, NUM_BRANCHES);
296 TEST_ASSERT(count, "Allowed PMU event is not counting");
297 }
298
test_member_deny_list(struct kvm_vcpu * vcpu)299 static void test_member_deny_list(struct kvm_vcpu *vcpu)
300 {
301 struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_DENY);
302 uint64_t count = test_with_filter(vcpu, f);
303
304 free(f);
305 if (count)
306 pr_info("%s: Branch instructions retired = %lu (expected 0)\n",
307 __func__, count);
308 TEST_ASSERT(!count, "Disallowed PMU Event is counting");
309 }
310
test_member_allow_list(struct kvm_vcpu * vcpu)311 static void test_member_allow_list(struct kvm_vcpu *vcpu)
312 {
313 struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_ALLOW);
314 uint64_t count = test_with_filter(vcpu, f);
315
316 free(f);
317 if (count != NUM_BRANCHES)
318 pr_info("%s: Branch instructions retired = %lu (expected %u)\n",
319 __func__, count, NUM_BRANCHES);
320 TEST_ASSERT(count, "Allowed PMU event is not counting");
321 }
322
test_not_member_deny_list(struct kvm_vcpu * vcpu)323 static void test_not_member_deny_list(struct kvm_vcpu *vcpu)
324 {
325 struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_DENY);
326 uint64_t count;
327
328 remove_event(f, INTEL_BR_RETIRED);
329 remove_event(f, AMD_ZEN_BR_RETIRED);
330 count = test_with_filter(vcpu, f);
331 free(f);
332 if (count != NUM_BRANCHES)
333 pr_info("%s: Branch instructions retired = %lu (expected %u)\n",
334 __func__, count, NUM_BRANCHES);
335 TEST_ASSERT(count, "Allowed PMU event is not counting");
336 }
337
test_not_member_allow_list(struct kvm_vcpu * vcpu)338 static void test_not_member_allow_list(struct kvm_vcpu *vcpu)
339 {
340 struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_ALLOW);
341 uint64_t count;
342
343 remove_event(f, INTEL_BR_RETIRED);
344 remove_event(f, AMD_ZEN_BR_RETIRED);
345 count = test_with_filter(vcpu, f);
346 free(f);
347 if (count)
348 pr_info("%s: Branch instructions retired = %lu (expected 0)\n",
349 __func__, count);
350 TEST_ASSERT(!count, "Disallowed PMU Event is counting");
351 }
352
353 /*
354 * Verify that setting KVM_PMU_CAP_DISABLE prevents the use of the PMU.
355 *
356 * Note that KVM_CAP_PMU_CAPABILITY must be invoked prior to creating VCPUs.
357 */
test_pmu_config_disable(void (* guest_code)(void))358 static void test_pmu_config_disable(void (*guest_code)(void))
359 {
360 struct kvm_vcpu *vcpu;
361 int r;
362 struct kvm_vm *vm;
363
364 r = kvm_check_cap(KVM_CAP_PMU_CAPABILITY);
365 if (!(r & KVM_PMU_CAP_DISABLE))
366 return;
367
368 vm = vm_create(1);
369
370 vm_enable_cap(vm, KVM_CAP_PMU_CAPABILITY, KVM_PMU_CAP_DISABLE);
371
372 vcpu = vm_vcpu_add(vm, 0, guest_code);
373 vm_init_descriptor_tables(vm);
374 vcpu_init_descriptor_tables(vcpu);
375
376 TEST_ASSERT(!sanity_check_pmu(vcpu),
377 "Guest should not be able to use disabled PMU.");
378
379 kvm_vm_free(vm);
380 }
381
382 /*
383 * Check for a non-zero PMU version, at least one general-purpose
384 * counter per logical processor, an EBX bit vector of length greater
385 * than 5, and EBX[5] clear.
386 */
check_intel_pmu_leaf(const struct kvm_cpuid_entry2 * entry)387 static bool check_intel_pmu_leaf(const struct kvm_cpuid_entry2 *entry)
388 {
389 union cpuid10_eax eax = { .full = entry->eax };
390 union cpuid10_ebx ebx = { .full = entry->ebx };
391
392 return eax.split.version_id && eax.split.num_counters > 0 &&
393 eax.split.mask_length > ARCH_PERFMON_BRANCHES_RETIRED &&
394 !ebx.split.no_branch_instruction_retired;
395 }
396
397 /*
398 * Note that CPUID leaf 0xa is Intel-specific. This leaf should be
399 * clear on AMD hardware.
400 */
use_intel_pmu(void)401 static bool use_intel_pmu(void)
402 {
403 const struct kvm_cpuid_entry2 *entry;
404
405 entry = kvm_get_supported_cpuid_entry(0xa);
406 return is_intel_cpu() && check_intel_pmu_leaf(entry);
407 }
408
is_zen1(uint32_t eax)409 static bool is_zen1(uint32_t eax)
410 {
411 return x86_family(eax) == 0x17 && x86_model(eax) <= 0x0f;
412 }
413
is_zen2(uint32_t eax)414 static bool is_zen2(uint32_t eax)
415 {
416 return x86_family(eax) == 0x17 &&
417 x86_model(eax) >= 0x30 && x86_model(eax) <= 0x3f;
418 }
419
is_zen3(uint32_t eax)420 static bool is_zen3(uint32_t eax)
421 {
422 return x86_family(eax) == 0x19 && x86_model(eax) <= 0x0f;
423 }
424
425 /*
426 * Determining AMD support for a PMU event requires consulting the AMD
427 * PPR for the CPU or reference material derived therefrom. The AMD
428 * test code herein has been verified to work on Zen1, Zen2, and Zen3.
429 *
430 * Feel free to add more AMD CPUs that are documented to support event
431 * select 0xc2 umask 0 as "retired branch instructions."
432 */
use_amd_pmu(void)433 static bool use_amd_pmu(void)
434 {
435 const struct kvm_cpuid_entry2 *entry;
436
437 entry = kvm_get_supported_cpuid_entry(1);
438 return is_amd_cpu() &&
439 (is_zen1(entry->eax) ||
440 is_zen2(entry->eax) ||
441 is_zen3(entry->eax));
442 }
443
main(int argc,char * argv[])444 int main(int argc, char *argv[])
445 {
446 void (*guest_code)(void);
447 struct kvm_vcpu *vcpu;
448 struct kvm_vm *vm;
449
450 /* Tell stdout not to buffer its content */
451 setbuf(stdout, NULL);
452
453 TEST_REQUIRE(kvm_has_cap(KVM_CAP_PMU_EVENT_FILTER));
454
455 TEST_REQUIRE(use_intel_pmu() || use_amd_pmu());
456 guest_code = use_intel_pmu() ? intel_guest_code : amd_guest_code;
457
458 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
459
460 vm_init_descriptor_tables(vm);
461 vcpu_init_descriptor_tables(vcpu);
462
463 TEST_REQUIRE(sanity_check_pmu(vcpu));
464
465 if (use_amd_pmu())
466 test_amd_deny_list(vcpu);
467
468 test_without_filter(vcpu);
469 test_member_deny_list(vcpu);
470 test_member_allow_list(vcpu);
471 test_not_member_deny_list(vcpu);
472 test_not_member_allow_list(vcpu);
473
474 kvm_vm_free(vm);
475
476 test_pmu_config_disable(guest_code);
477
478 return 0;
479 }
480