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