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

Configure Feed

Select the types of activity you want to include in your feed.

KVM: selftests: Extend vmx_set_nested_state_test to cover SVM

Add test cases for the validation checks in svm_set_nested_state(), and
allow the test to run with SVM as well as VMX. The SVM test also makes
sure that KVM_SET_NESTED_STATE accepts GIF being set or cleared if
EFER.SVME is cleared, verifying a recently fixed bug where GIF was
incorrectly expected to always be set when EFER.SVME is cleared.

Signed-off-by: Yosry Ahmed <yosry.ahmed@linux.dev>
Link: https://patch.msgid.link/20251121204803.991707-5-yosry.ahmed@linux.dev
Signed-off-by: Sean Christopherson <seanjc@google.com>

authored by

Yosry Ahmed and committed by
Sean Christopherson
ca2eccb9 bda6ae6f

+112 -12
+1 -1
tools/testing/selftests/kvm/Makefile.kvm
··· 92 92 TEST_GEN_PROGS_x86 += x86/nested_emulation_test 93 93 TEST_GEN_PROGS_x86 += x86/nested_exceptions_test 94 94 TEST_GEN_PROGS_x86 += x86/nested_invalid_cr3_test 95 + TEST_GEN_PROGS_x86 += x86/nested_set_state_test 95 96 TEST_GEN_PROGS_x86 += x86/nested_tsc_adjust_test 96 97 TEST_GEN_PROGS_x86 += x86/nested_tsc_scaling_test 97 98 TEST_GEN_PROGS_x86 += x86/platform_info_test ··· 121 120 TEST_GEN_PROGS_x86 += x86/vmx_msrs_test 122 121 TEST_GEN_PROGS_x86 += x86/vmx_invalid_nested_guest_state 123 122 TEST_GEN_PROGS_x86 += x86/vmx_nested_la57_state_test 124 - TEST_GEN_PROGS_x86 += x86/vmx_set_nested_state_test 125 123 TEST_GEN_PROGS_x86 += x86/apic_bus_clock_test 126 124 TEST_GEN_PROGS_x86 += x86/xapic_ipi_test 127 125 TEST_GEN_PROGS_x86 += x86/xapic_state_test
+111 -11
tools/testing/selftests/kvm/x86/vmx_set_nested_state_test.c tools/testing/selftests/kvm/x86/nested_set_state_test.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * vmx_set_nested_state_test 4 - * 5 3 * Copyright (C) 2019, Google LLC. 6 4 * 7 5 * This test verifies the integrity of calling the ioctl KVM_SET_NESTED_STATE. ··· 9 11 #include "kvm_util.h" 10 12 #include "processor.h" 11 13 #include "vmx.h" 14 + #include "svm_util.h" 12 15 13 16 #include <errno.h> 14 17 #include <linux/kvm.h> ··· 248 249 free(state); 249 250 } 250 251 252 + static void vcpu_efer_enable_svm(struct kvm_vcpu *vcpu) 253 + { 254 + uint64_t old_efer = vcpu_get_msr(vcpu, MSR_EFER); 255 + 256 + vcpu_set_msr(vcpu, MSR_EFER, old_efer | EFER_SVME); 257 + } 258 + 259 + static void vcpu_efer_disable_svm(struct kvm_vcpu *vcpu) 260 + { 261 + uint64_t old_efer = vcpu_get_msr(vcpu, MSR_EFER); 262 + 263 + vcpu_set_msr(vcpu, MSR_EFER, old_efer & ~EFER_SVME); 264 + } 265 + 266 + void set_default_svm_state(struct kvm_nested_state *state, int size) 267 + { 268 + memset(state, 0, size); 269 + state->format = 1; 270 + state->size = size; 271 + state->hdr.svm.vmcb_pa = 0x3000; 272 + } 273 + 274 + void test_svm_nested_state(struct kvm_vcpu *vcpu) 275 + { 276 + /* Add a page for VMCB. */ 277 + const int state_sz = sizeof(struct kvm_nested_state) + getpagesize(); 278 + struct kvm_nested_state *state = 279 + (struct kvm_nested_state *)malloc(state_sz); 280 + 281 + vcpu_set_cpuid_feature(vcpu, X86_FEATURE_SVM); 282 + 283 + /* The format must be set to 1. 0 for VMX, 1 for SVM. */ 284 + set_default_svm_state(state, state_sz); 285 + state->format = 0; 286 + test_nested_state_expect_einval(vcpu, state); 287 + 288 + /* Invalid flags are rejected, KVM_STATE_NESTED_EVMCS is VMX-only */ 289 + set_default_svm_state(state, state_sz); 290 + state->flags = KVM_STATE_NESTED_EVMCS; 291 + test_nested_state_expect_einval(vcpu, state); 292 + 293 + /* 294 + * If EFER.SVME is clear, guest mode is disallowed and GIF can be set or 295 + * cleared. 296 + */ 297 + vcpu_efer_disable_svm(vcpu); 298 + 299 + set_default_svm_state(state, state_sz); 300 + state->flags = KVM_STATE_NESTED_GUEST_MODE; 301 + test_nested_state_expect_einval(vcpu, state); 302 + 303 + state->flags = 0; 304 + test_nested_state(vcpu, state); 305 + 306 + state->flags = KVM_STATE_NESTED_GIF_SET; 307 + test_nested_state(vcpu, state); 308 + 309 + /* Enable SVM in the guest EFER. */ 310 + vcpu_efer_enable_svm(vcpu); 311 + 312 + /* Setting vmcb_pa to a non-aligned address is only fine when not entering guest mode */ 313 + set_default_svm_state(state, state_sz); 314 + state->hdr.svm.vmcb_pa = -1ull; 315 + state->flags = 0; 316 + test_nested_state(vcpu, state); 317 + state->flags = KVM_STATE_NESTED_GUEST_MODE; 318 + test_nested_state_expect_einval(vcpu, state); 319 + 320 + /* 321 + * Size must be large enough to fit kvm_nested_state and VMCB 322 + * only when entering guest mode. 323 + */ 324 + set_default_svm_state(state, state_sz/2); 325 + state->flags = 0; 326 + test_nested_state(vcpu, state); 327 + state->flags = KVM_STATE_NESTED_GUEST_MODE; 328 + test_nested_state_expect_einval(vcpu, state); 329 + 330 + /* 331 + * Test that if we leave nesting the state reflects that when we get it 332 + * again, except for vmcb_pa, which is always returned as 0 when not in 333 + * guest mode. 334 + */ 335 + set_default_svm_state(state, state_sz); 336 + state->hdr.svm.vmcb_pa = -1ull; 337 + state->flags = KVM_STATE_NESTED_GIF_SET; 338 + test_nested_state(vcpu, state); 339 + vcpu_nested_state_get(vcpu, state); 340 + TEST_ASSERT(state->size >= sizeof(*state) && state->size <= state_sz, 341 + "Size must be between %ld and %d. The size returned was %d.", 342 + sizeof(*state), state_sz, state->size); 343 + 344 + TEST_ASSERT_EQ(state->hdr.svm.vmcb_pa, 0); 345 + TEST_ASSERT_EQ(state->flags, KVM_STATE_NESTED_GIF_SET); 346 + 347 + free(state); 348 + } 349 + 251 350 int main(int argc, char *argv[]) 252 351 { 253 352 struct kvm_vm *vm; ··· 354 257 355 258 have_evmcs = kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS); 356 259 260 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || 261 + kvm_cpu_has(X86_FEATURE_SVM)); 357 262 TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); 358 - 359 - /* 360 - * AMD currently does not implement set_nested_state, so for now we 361 - * just early out. 362 - */ 363 - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 364 263 365 264 vm = vm_create_with_one_vcpu(&vcpu, NULL); 366 265 367 266 /* 368 - * First run tests with VMX disabled to check error handling. 267 + * First run tests with VMX/SVM disabled to check error handling. 268 + * test_{vmx/svm}_nested_state() will re-enable as needed. 369 269 */ 370 - vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_VMX); 270 + if (kvm_cpu_has(X86_FEATURE_VMX)) 271 + vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_VMX); 272 + else 273 + vcpu_clear_cpuid_feature(vcpu, X86_FEATURE_SVM); 371 274 372 275 /* Passing a NULL kvm_nested_state causes a EFAULT. */ 373 276 test_nested_state_expect_efault(vcpu, NULL); ··· 396 299 state.flags = KVM_STATE_NESTED_RUN_PENDING; 397 300 test_nested_state_expect_einval(vcpu, &state); 398 301 399 - test_vmx_nested_state(vcpu); 302 + if (kvm_cpu_has(X86_FEATURE_VMX)) 303 + test_vmx_nested_state(vcpu); 304 + else 305 + test_svm_nested_state(vcpu); 400 306 401 307 kvm_vm_free(vm); 402 308 return 0;