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

KVM: selftests: Update x86's KVM PV test to match KVM's disabling exits behavior

Rework x86's KVM PV features test to align with KVM's new, fixed behavior
of not allowing userspace to disable HLT-exiting after vCPUs have been
created. Rework the core testcase to disable HLT-exiting before creating
a vCPU, and opportunistically modify keep the paired VM+vCPU creation to
verify that KVM rejects KVM_CAP_X86_DISABLE_EXITS as expected.

Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Link: https://lore.kernel.org/r/20241128013424.4096668-18-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

+30 -3
+30 -3
tools/testing/selftests/kvm/x86/kvm_pv_test.c
··· 139 139 struct kvm_vm *vm; 140 140 struct kvm_cpuid_entry2 *ent; 141 141 u32 kvm_sig_old; 142 + int r; 142 143 143 144 if (!(kvm_check_cap(KVM_CAP_X86_DISABLE_EXITS) & KVM_X86_DISABLE_EXITS_HLT)) 144 145 return; ··· 153 152 TEST_ASSERT(vcpu_cpuid_has(vcpu, X86_FEATURE_KVM_PV_UNHALT), 154 153 "Enabling X86_FEATURE_KVM_PV_UNHALT had no effect"); 155 154 156 - /* Make sure KVM clears vcpu->arch.kvm_cpuid */ 155 + /* Verify KVM disallows disabling exits after vCPU creation. */ 156 + r = __vm_enable_cap(vm, KVM_CAP_X86_DISABLE_EXITS, KVM_X86_DISABLE_EXITS_HLT); 157 + TEST_ASSERT(r && errno == EINVAL, 158 + "Disabling exits after vCPU creation didn't fail as expected"); 159 + 160 + kvm_vm_free(vm); 161 + 162 + /* Verify that KVM clear PV_UNHALT from guest CPUID. */ 163 + vm = vm_create(1); 164 + vm_enable_cap(vm, KVM_CAP_X86_DISABLE_EXITS, KVM_X86_DISABLE_EXITS_HLT); 165 + 166 + vcpu = vm_vcpu_add(vm, 0, NULL); 167 + TEST_ASSERT(!vcpu_cpuid_has(vcpu, X86_FEATURE_KVM_PV_UNHALT), 168 + "vCPU created with PV_UNHALT set by default"); 169 + 170 + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_KVM_PV_UNHALT); 171 + TEST_ASSERT(!vcpu_cpuid_has(vcpu, X86_FEATURE_KVM_PV_UNHALT), 172 + "PV_UNHALT set in guest CPUID when HLT-exiting is disabled"); 173 + 174 + /* 175 + * Clobber the KVM PV signature and verify KVM does NOT clear PV_UNHALT 176 + * when KVM PV is not present, and DOES clear PV_UNHALT when switching 177 + * back to the correct signature.. 178 + */ 157 179 ent = vcpu_get_cpuid_entry(vcpu, KVM_CPUID_SIGNATURE); 158 180 kvm_sig_old = ent->ebx; 159 181 ent->ebx = 0xdeadbeef; 160 182 vcpu_set_cpuid(vcpu); 161 183 162 - vm_enable_cap(vm, KVM_CAP_X86_DISABLE_EXITS, KVM_X86_DISABLE_EXITS_HLT); 184 + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_KVM_PV_UNHALT); 185 + TEST_ASSERT(vcpu_cpuid_has(vcpu, X86_FEATURE_KVM_PV_UNHALT), 186 + "PV_UNHALT cleared when using bogus KVM PV signature"); 187 + 163 188 ent = vcpu_get_cpuid_entry(vcpu, KVM_CPUID_SIGNATURE); 164 189 ent->ebx = kvm_sig_old; 165 190 vcpu_set_cpuid(vcpu); 166 191 167 192 TEST_ASSERT(!vcpu_cpuid_has(vcpu, X86_FEATURE_KVM_PV_UNHALT), 168 - "KVM_FEATURE_PV_UNHALT is set with KVM_CAP_X86_DISABLE_EXITS"); 193 + "PV_UNHALT set in guest CPUID when HLT-exiting is disabled"); 169 194 170 195 /* FIXME: actually test KVM_FEATURE_PV_UNHALT feature */ 171 196