1414#define _GNU_SOURCE /* for program_invocation_short_name */
1515#include <sys/ioctl.h>
1616
17+ #include <linux/bitmap.h>
18+
1719#include "kvm_util.h"
1820#include "vmx.h"
1921
20- #define PMU_CAP_FW_WRITES (1ULL << 13)
2122#define PMU_CAP_LBR_FMT 0x3f
2223
2324union perf_capabilities {
@@ -36,6 +37,18 @@ union perf_capabilities {
3637 u64 capabilities ;
3738};
3839
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+ */
44+ static 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+
3952static void guest_code (void )
4053{
4154 wrmsr (MSR_IA32_PERF_CAPABILITIES , PMU_CAP_LBR_FMT );
@@ -58,15 +71,22 @@ static void test_basic_perf_capabilities(union perf_capabilities host_cap)
5871
5972static void test_fungible_perf_capabilities (union perf_capabilities host_cap )
6073{
74+ const uint64_t fungible_caps = host_cap .capabilities & ~immutable_caps .capabilities ;
75+
6176 struct kvm_vcpu * vcpu ;
6277 struct kvm_vm * vm = vm_create_with_one_vcpu (& vcpu , guest_code );
78+ int bit ;
6379
64- /* testcase 1, set capabilities when we have PDCM bit */
65- vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES , PMU_CAP_FW_WRITES );
80+ for_each_set_bit (bit , & fungible_caps , 64 ) {
81+ vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES , BIT_ULL (bit ));
82+ vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES ,
83+ host_cap .capabilities & ~BIT_ULL (bit ));
84+ }
85+ vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES , host_cap .capabilities );
6686
6787 /* check whatever we write with KVM_SET_MSR is _not_ modified */
6888 vcpu_run (vcpu );
69- ASSERT_EQ (vcpu_get_msr (vcpu , MSR_IA32_PERF_CAPABILITIES ), PMU_CAP_FW_WRITES );
89+ ASSERT_EQ (vcpu_get_msr (vcpu , MSR_IA32_PERF_CAPABILITIES ), host_cap . capabilities );
7090
7191 kvm_vm_free (vm );
7292}
@@ -102,7 +122,6 @@ int main(int argc, char *argv[])
102122 TEST_REQUIRE (kvm_cpu_property (X86_PROPERTY_PMU_VERSION ) > 0 );
103123
104124 host_cap .capabilities = kvm_get_feature_msr (MSR_IA32_PERF_CAPABILITIES );
105- host_cap .capabilities &= (PMU_CAP_FW_WRITES | PMU_CAP_LBR_FMT );
106125
107126 TEST_ASSERT (host_cap .full_width_write ,
108127 "Full-width writes should always be supported" );
0 commit comments