vmx_pmu_caps_test.c (3433B)
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 14#define _GNU_SOURCE /* for program_invocation_short_name */ 15#include <sys/ioctl.h> 16 17#include "kvm_util.h" 18#include "vmx.h" 19 20#define VCPU_ID 0 21 22#define X86_FEATURE_PDCM (1<<15) 23#define PMU_CAP_FW_WRITES (1ULL << 13) 24#define PMU_CAP_LBR_FMT 0x3f 25 26union cpuid10_eax { 27 struct { 28 unsigned int version_id:8; 29 unsigned int num_counters:8; 30 unsigned int bit_width:8; 31 unsigned int mask_length:8; 32 } split; 33 unsigned int full; 34}; 35 36union perf_capabilities { 37 struct { 38 u64 lbr_format:6; 39 u64 pebs_trap:1; 40 u64 pebs_arch_reg:1; 41 u64 pebs_format:4; 42 u64 smm_freeze:1; 43 u64 full_width_write:1; 44 u64 pebs_baseline:1; 45 u64 perf_metrics:1; 46 u64 pebs_output_pt_available:1; 47 u64 anythread_deprecated:1; 48 }; 49 u64 capabilities; 50}; 51 52static void guest_code(void) 53{ 54 wrmsr(MSR_IA32_PERF_CAPABILITIES, PMU_CAP_LBR_FMT); 55} 56 57int main(int argc, char *argv[]) 58{ 59 struct kvm_cpuid2 *cpuid; 60 struct kvm_cpuid_entry2 *entry_1_0; 61 struct kvm_cpuid_entry2 *entry_a_0; 62 bool pdcm_supported = false; 63 struct kvm_vm *vm; 64 int ret; 65 union cpuid10_eax eax; 66 union perf_capabilities host_cap; 67 68 host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES); 69 host_cap.capabilities &= (PMU_CAP_FW_WRITES | PMU_CAP_LBR_FMT); 70 71 /* Create VM */ 72 vm = vm_create_default(VCPU_ID, 0, guest_code); 73 cpuid = kvm_get_supported_cpuid(); 74 75 if (kvm_get_cpuid_max_basic() >= 0xa) { 76 entry_1_0 = kvm_get_supported_cpuid_index(1, 0); 77 entry_a_0 = kvm_get_supported_cpuid_index(0xa, 0); 78 pdcm_supported = entry_1_0 && !!(entry_1_0->ecx & X86_FEATURE_PDCM); 79 eax.full = entry_a_0->eax; 80 } 81 if (!pdcm_supported) { 82 print_skip("MSR_IA32_PERF_CAPABILITIES is not supported by the vCPU"); 83 exit(KSFT_SKIP); 84 } 85 if (!eax.split.version_id) { 86 print_skip("PMU is not supported by the vCPU"); 87 exit(KSFT_SKIP); 88 } 89 90 /* testcase 1, set capabilities when we have PDCM bit */ 91 vcpu_set_cpuid(vm, VCPU_ID, cpuid); 92 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, PMU_CAP_FW_WRITES); 93 94 /* check capabilities can be retrieved with KVM_GET_MSR */ 95 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES); 96 97 /* check whatever we write with KVM_SET_MSR is _not_ modified */ 98 vcpu_run(vm, VCPU_ID); 99 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES); 100 101 /* testcase 2, check valid LBR formats are accepted */ 102 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0); 103 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), 0); 104 105 vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, host_cap.lbr_format); 106 ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), (u64)host_cap.lbr_format); 107 108 /* testcase 3, check invalid LBR format is rejected */ 109 /* Note, on Arch LBR capable platforms, LBR_FMT in perf capability msr is 0x3f, 110 * to avoid the failure, use a true invalid format 0x30 for the test. */ 111 ret = _vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0x30); 112 TEST_ASSERT(ret == 0, "Bad PERF_CAPABILITIES didn't fail."); 113 114 printf("Completed perf capability tests.\n"); 115 kvm_vm_free(vm); 116}