1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2026, Google LLC. 4 */ 5 #include "kvm_util.h" 6 #include "vmx.h" 7 #include "svm_util.h" 8 #include "kselftest.h" 9 10 11 #define L2_GUEST_STACK_SIZE 64 12 13 static void l2_guest_code(void) 14 { 15 unsigned long efer = rdmsr(MSR_EFER); 16 17 /* generic_svm_setup() initializes EFER_SVME set for L2 */ 18 GUEST_ASSERT(efer & EFER_SVME); 19 wrmsr(MSR_EFER, efer & ~EFER_SVME); 20 21 /* Unreachable, L1 should be shutdown */ 22 GUEST_ASSERT(0); 23 } 24 25 static void l1_guest_code(struct svm_test_data *svm) 26 { 27 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 28 29 generic_svm_setup(svm, l2_guest_code, 30 &l2_guest_stack[L2_GUEST_STACK_SIZE]); 31 run_guest(svm->vmcb, svm->vmcb_gpa); 32 33 /* Unreachable, L1 should be shutdown */ 34 GUEST_ASSERT(0); 35 } 36 37 int main(int argc, char *argv[]) 38 { 39 struct kvm_vcpu *vcpu; 40 struct kvm_vm *vm; 41 vm_vaddr_t nested_gva = 0; 42 43 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SVM)); 44 45 vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 46 47 vcpu_alloc_svm(vm, &nested_gva); 48 vcpu_args_set(vcpu, 1, nested_gva); 49 50 vcpu_run(vcpu); 51 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); 52 53 kvm_vm_free(vm); 54 return 0; 55 } 56