1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020, Google LLC.
5 * Tests for KVM paravirtual feature disablement
7 #include <asm/kvm_para.h>
8 #include <linux/kvm_para.h>
11 #include "test_util.h"
13 #include "processor.h"
20 #define TEST_MSR(msr) { .idx = msr, .name = #msr }
21 #define UCALL_PR_MSR 0xdeadbeef
22 #define PR_MSR(msr) ucall(UCALL_PR_MSR, 1, msr)
25 * KVM paravirtual msrs to test. Expect a #GP if any of these msrs are read or
26 * written, as the KVM_CPUID_FEATURES leaf is cleared.
28 static struct msr_data msrs_to_test
[] = {
29 TEST_MSR(MSR_KVM_SYSTEM_TIME
),
30 TEST_MSR(MSR_KVM_SYSTEM_TIME_NEW
),
31 TEST_MSR(MSR_KVM_WALL_CLOCK
),
32 TEST_MSR(MSR_KVM_WALL_CLOCK_NEW
),
33 TEST_MSR(MSR_KVM_ASYNC_PF_EN
),
34 TEST_MSR(MSR_KVM_STEAL_TIME
),
35 TEST_MSR(MSR_KVM_PV_EOI_EN
),
36 TEST_MSR(MSR_KVM_POLL_CONTROL
),
37 TEST_MSR(MSR_KVM_ASYNC_PF_INT
),
38 TEST_MSR(MSR_KVM_ASYNC_PF_ACK
),
41 static void test_msr(struct msr_data
*msr
)
48 vector
= rdmsr_safe(msr
->idx
, &ignored
);
49 GUEST_ASSERT_EQ(vector
, GP_VECTOR
);
51 vector
= wrmsr_safe(msr
->idx
, 0);
52 GUEST_ASSERT_EQ(vector
, GP_VECTOR
);
60 #define TEST_HCALL(hc) { .nr = hc, .name = #hc }
61 #define UCALL_PR_HCALL 0xdeadc0de
62 #define PR_HCALL(hc) ucall(UCALL_PR_HCALL, 1, hc)
65 * KVM hypercalls to test. Expect -KVM_ENOSYS when called, as the corresponding
66 * features have been cleared in KVM_CPUID_FEATURES.
68 static struct hcall_data hcalls_to_test
[] = {
69 TEST_HCALL(KVM_HC_KICK_CPU
),
70 TEST_HCALL(KVM_HC_SEND_IPI
),
71 TEST_HCALL(KVM_HC_SCHED_YIELD
),
74 static void test_hcall(struct hcall_data
*hc
)
79 r
= kvm_hypercall(hc
->nr
, 0, 0, 0, 0);
80 GUEST_ASSERT_EQ(r
, -KVM_ENOSYS
);
83 static void guest_main(void)
87 for (i
= 0; i
< ARRAY_SIZE(msrs_to_test
); i
++) {
88 test_msr(&msrs_to_test
[i
]);
91 for (i
= 0; i
< ARRAY_SIZE(hcalls_to_test
); i
++) {
92 test_hcall(&hcalls_to_test
[i
]);
98 static void pr_msr(struct ucall
*uc
)
100 struct msr_data
*msr
= (struct msr_data
*)uc
->args
[0];
102 pr_info("testing msr: %s (%#x)\n", msr
->name
, msr
->idx
);
105 static void pr_hcall(struct ucall
*uc
)
107 struct hcall_data
*hc
= (struct hcall_data
*)uc
->args
[0];
109 pr_info("testing hcall: %s (%lu)\n", hc
->name
, hc
->nr
);
112 static void enter_guest(struct kvm_vcpu
*vcpu
)
118 TEST_ASSERT_KVM_EXIT_REASON(vcpu
, KVM_EXIT_IO
);
120 switch (get_ucall(vcpu
, &uc
)) {
128 REPORT_GUEST_ASSERT(uc
);
136 static void test_pv_unhalt(void)
138 struct kvm_vcpu
*vcpu
;
140 struct kvm_cpuid_entry2
*ent
;
143 pr_info("testing KVM_FEATURE_PV_UNHALT\n");
145 TEST_REQUIRE(KVM_CAP_X86_DISABLE_EXITS
);
147 /* KVM_PV_UNHALT test */
148 vm
= vm_create_with_one_vcpu(&vcpu
, guest_main
);
149 vcpu_set_cpuid_feature(vcpu
, X86_FEATURE_KVM_PV_UNHALT
);
151 TEST_ASSERT(vcpu_cpuid_has(vcpu
, X86_FEATURE_KVM_PV_UNHALT
),
152 "Enabling X86_FEATURE_KVM_PV_UNHALT had no effect");
154 /* Make sure KVM clears vcpu->arch.kvm_cpuid */
155 ent
= vcpu_get_cpuid_entry(vcpu
, KVM_CPUID_SIGNATURE
);
156 kvm_sig_old
= ent
->ebx
;
157 ent
->ebx
= 0xdeadbeef;
158 vcpu_set_cpuid(vcpu
);
160 vm_enable_cap(vm
, KVM_CAP_X86_DISABLE_EXITS
, KVM_X86_DISABLE_EXITS_HLT
);
161 ent
= vcpu_get_cpuid_entry(vcpu
, KVM_CPUID_SIGNATURE
);
162 ent
->ebx
= kvm_sig_old
;
163 vcpu_set_cpuid(vcpu
);
165 TEST_ASSERT(!vcpu_cpuid_has(vcpu
, X86_FEATURE_KVM_PV_UNHALT
),
166 "KVM_FEATURE_PV_UNHALT is set with KVM_CAP_X86_DISABLE_EXITS");
168 /* FIXME: actually test KVM_FEATURE_PV_UNHALT feature */
175 struct kvm_vcpu
*vcpu
;
178 TEST_REQUIRE(kvm_has_cap(KVM_CAP_ENFORCE_PV_FEATURE_CPUID
));
180 vm
= vm_create_with_one_vcpu(&vcpu
, guest_main
);
182 vcpu_enable_cap(vcpu
, KVM_CAP_ENFORCE_PV_FEATURE_CPUID
, 1);
184 vcpu_clear_cpuid_entry(vcpu
, KVM_CPUID_FEATURES
);