Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: selftests: Add infrastructure for getting vCPU binary stats

Now that the binary stats cache infrastructure is largely scope agnostic,
add support for vCPU-scoped stats. Like VM stats, open and cache the
stats FD when the vCPU is created so that it's guaranteed to be valid when
vcpu_get_stats() is invoked.

Account for the extra per-vCPU file descriptor in kvm_set_files_rlimit(),
so that tests that create large VMs don't run afoul of resource limits.

To sanity check that the infrastructure actually works, and to get a bit
of bonus coverage, add an assert in x86's xapic_ipi_test to verify that
the number of HLTs executed by the test matches the number of HLT exits
observed by KVM.

Tested-by: Manali Shukla <Manali.Shukla@amd.com>
Link: https://lore.kernel.org/r/20250111005049.1247555-9-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+27 -27
+12 -8
tools/testing/selftests/kvm/include/kvm_util.h
··· 61 61 #ifdef __x86_64__ 62 62 struct kvm_cpuid2 *cpuid; 63 63 #endif 64 + struct kvm_binary_stats stats; 64 65 struct kvm_dirty_gfn *dirty_gfns; 65 66 uint32_t fetch_index; 66 67 uint32_t dirty_gfns_count; ··· 535 534 struct kvm_stats_desc *desc, uint64_t *data, 536 535 size_t max_elements); 537 536 538 - void __vm_get_stat(struct kvm_vm *vm, const char *stat_name, uint64_t *data, 539 - size_t max_elements); 537 + void kvm_get_stat(struct kvm_binary_stats *stats, const char *name, 538 + uint64_t *data, size_t max_elements); 540 539 541 - #define vm_get_stat(vm, stat) \ 542 - ({ \ 543 - uint64_t data; \ 544 - \ 545 - __vm_get_stat(vm, #stat, &data, 1); \ 546 - data; \ 540 + #define __get_stat(stats, stat) \ 541 + ({ \ 542 + uint64_t data; \ 543 + \ 544 + kvm_get_stat(stats, #stat, &data, 1); \ 545 + data; \ 547 546 }) 547 + 548 + #define vm_get_stat(vm, stat) __get_stat(&(vm)->stats, stat) 549 + #define vcpu_get_stat(vcpu, stat) __get_stat(&(vcpu)->stats, stat) 548 550 549 551 void vm_create_irqchip(struct kvm_vm *vm); 550 552
+13 -19
tools/testing/selftests/kvm/lib/kvm_util.c
··· 415 415 void kvm_set_files_rlimit(uint32_t nr_vcpus) 416 416 { 417 417 /* 418 - * Number of file descriptors required, nr_vpucs vCPU fds + an arbitrary 419 - * number for everything else. 418 + * Each vCPU will open two file descriptors: the vCPU itself and the 419 + * vCPU's binary stats file descriptor. Add an arbitrary amount of 420 + * buffer for all other files a test may open. 420 421 */ 421 - int nr_fds_wanted = nr_vcpus + 100; 422 + int nr_fds_wanted = nr_vcpus * 2 + 100; 422 423 struct rlimit rl; 423 424 424 425 /* ··· 746 745 747 746 ret = close(vcpu->fd); 748 747 TEST_ASSERT(!ret, __KVM_SYSCALL_ERROR("close()", ret)); 748 + 749 + kvm_stats_release(&vcpu->stats); 749 750 750 751 list_del(&vcpu->list); 751 752 ··· 1341 1338 PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0); 1342 1339 TEST_ASSERT(vcpu->run != MAP_FAILED, 1343 1340 __KVM_SYSCALL_ERROR("mmap()", (int)(unsigned long)MAP_FAILED)); 1341 + 1342 + if (kvm_has_cap(KVM_CAP_BINARY_STATS_FD)) 1343 + vcpu->stats.fd = vcpu_get_stats_fd(vcpu); 1344 + else 1345 + vcpu->stats.fd = -1; 1344 1346 1345 1347 /* Add to linked-list of VCPUs. */ 1346 1348 list_add(&vcpu->list, &vm->vcpus); ··· 2259 2251 desc->name, size, ret); 2260 2252 } 2261 2253 2262 - /* 2263 - * Read the data of the named stat 2264 - * 2265 - * Input Args: 2266 - * vm - the VM for which the stat should be read 2267 - * stat_name - the name of the stat to read 2268 - * max_elements - the maximum number of 8-byte values to read into data 2269 - * 2270 - * Output Args: 2271 - * data - the buffer into which stat data should be read 2272 - * 2273 - * Read the data values of a specified stat from the binary stats interface. 2274 - */ 2275 - void __vm_get_stat(struct kvm_vm *vm, const char *name, uint64_t *data, 2276 - size_t max_elements) 2254 + void kvm_get_stat(struct kvm_binary_stats *stats, const char *name, 2255 + uint64_t *data, size_t max_elements) 2277 2256 { 2278 - struct kvm_binary_stats *stats = &vm->stats; 2279 2257 struct kvm_stats_desc *desc; 2280 2258 size_t size_desc; 2281 2259 int i;
+2
tools/testing/selftests/kvm/x86/xapic_ipi_test.c
··· 465 465 cancel_join_vcpu_thread(threads[0], params[0].vcpu); 466 466 cancel_join_vcpu_thread(threads[1], params[1].vcpu); 467 467 468 + TEST_ASSERT_EQ(data->hlt_count, vcpu_get_stat(params[0].vcpu, halt_exits)); 469 + 468 470 fprintf(stderr, 469 471 "Test successful after running for %d seconds.\n" 470 472 "Sending vCPU sent %lu IPIs to halting vCPU\n"