@@ -54,9 +54,59 @@ static const union perf_capabilities format_caps = {
5454 .pebs_format = -1 ,
5555};
5656
57- static void guest_code (void )
57+ static void guest_code (uint64_t current_val )
5858{
59- wrmsr (MSR_IA32_PERF_CAPABILITIES , PMU_CAP_LBR_FMT );
59+ uint8_t vector ;
60+ int i ;
61+
62+ vector = wrmsr_safe (MSR_IA32_PERF_CAPABILITIES , current_val );
63+ GUEST_ASSERT_2 (vector == GP_VECTOR , current_val , vector );
64+
65+ vector = wrmsr_safe (MSR_IA32_PERF_CAPABILITIES , 0 );
66+ GUEST_ASSERT_2 (vector == GP_VECTOR , 0 , vector );
67+
68+ for (i = 0 ; i < 64 ; i ++ ) {
69+ vector = wrmsr_safe (MSR_IA32_PERF_CAPABILITIES ,
70+ current_val ^ BIT_ULL (i ));
71+ GUEST_ASSERT_2 (vector == GP_VECTOR ,
72+ current_val ^ BIT_ULL (i ), vector );
73+ }
74+
75+ GUEST_DONE ();
76+ }
77+
78+ /*
79+ * Verify that guest WRMSRs to PERF_CAPABILITIES #GP regardless of the value
80+ * written, that the guest always sees the userspace controlled value, and that
81+ * PERF_CAPABILITIES is immutable after KVM_RUN.
82+ */
83+ static void test_guest_wrmsr_perf_capabilities (union perf_capabilities host_cap )
84+ {
85+ struct kvm_vcpu * vcpu ;
86+ struct kvm_vm * vm = vm_create_with_one_vcpu (& vcpu , guest_code );
87+ struct ucall uc ;
88+
89+ vm_init_descriptor_tables (vm );
90+ vcpu_init_descriptor_tables (vcpu );
91+
92+ vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES , host_cap .capabilities );
93+
94+ vcpu_args_set (vcpu , 1 , host_cap .capabilities );
95+ vcpu_run (vcpu );
96+
97+ switch (get_ucall (vcpu , & uc )) {
98+ case UCALL_ABORT :
99+ REPORT_GUEST_ASSERT_2 (uc , "val = 0x%lx, vector = %lu" );
100+ break ;
101+ case UCALL_DONE :
102+ break ;
103+ default :
104+ TEST_FAIL ("Unexpected ucall: %lu" , uc .cmd );
105+ }
106+
107+ ASSERT_EQ (vcpu_get_msr (vcpu , MSR_IA32_PERF_CAPABILITIES ), host_cap .capabilities );
108+
109+ kvm_vm_free (vm );
60110}
61111
62112/*
@@ -79,7 +129,7 @@ static void test_fungible_perf_capabilities(union perf_capabilities host_cap)
79129 const uint64_t fungible_caps = host_cap .capabilities & ~immutable_caps .capabilities ;
80130
81131 struct kvm_vcpu * vcpu ;
82- struct kvm_vm * vm = vm_create_with_one_vcpu (& vcpu , guest_code );
132+ struct kvm_vm * vm = vm_create_with_one_vcpu (& vcpu , NULL );
83133 int bit ;
84134
85135 for_each_set_bit (bit , & fungible_caps , 64 ) {
@@ -89,10 +139,6 @@ static void test_fungible_perf_capabilities(union perf_capabilities host_cap)
89139 }
90140 vcpu_set_msr (vcpu , MSR_IA32_PERF_CAPABILITIES , host_cap .capabilities );
91141
92- /* check whatever we write with KVM_SET_MSR is _not_ modified */
93- vcpu_run (vcpu );
94- ASSERT_EQ (vcpu_get_msr (vcpu , MSR_IA32_PERF_CAPABILITIES ), host_cap .capabilities );
95-
96142 kvm_vm_free (vm );
97143}
98144
@@ -153,6 +199,7 @@ int main(int argc, char *argv[])
153199 test_basic_perf_capabilities (host_cap );
154200 test_fungible_perf_capabilities (host_cap );
155201 test_immutable_perf_capabilities (host_cap );
202+ test_guest_wrmsr_perf_capabilities (host_cap );
156203
157204 printf ("Completed perf capability tests.\n" );
158205}
0 commit comments