diff --git a/hypervisor/arch/x86/guest/nested.c b/hypervisor/arch/x86/guest/nested.c index 598beebaa..f78f4556c 100644 --- a/hypervisor/arch/x86/guest/nested.c +++ b/hypervisor/arch/x86/guest/nested.c @@ -6,7 +6,9 @@ #include #include +#include #include +#include #include #include #include @@ -438,3 +440,40 @@ int32_t vmxon_vmexit_handler(struct acrn_vcpu *vcpu) return 0; } + +/* + * @pre vcpu != NULL + */ +bool check_vmx_permission(struct acrn_vcpu *vcpu) +{ + bool permit = true; + + /* If this VM is not nVMX enabled, it implies that 'vmxon == false' */ + if ((vcpu->arch.nested.vmxon == false) + || ((vcpu_get_cr0(vcpu) & CR0_PE) == 0UL) + || ((vcpu_get_rflags(vcpu) & RFLAGS_VM) != 0U)) { + /* We rely on hardware to check "IA32_EFER.LMA = 1 and CS.L = 0" */ + vcpu_inject_ud(vcpu); + permit = false; + } else if (get_guest_cpl() != 0) { + vcpu_inject_gp(vcpu, 0U); + permit = false; + } + + return permit; +} + +/* + * @pre vcpu != NULL + * @pre vcpu->vm != NULL + */ +int32_t vmxoff_vmexit_handler(struct acrn_vcpu *vcpu) +{ + if (check_vmx_permission(vcpu)) { + vcpu->arch.nested.vmxon = false; + + nested_vmx_result(VMsucceed, 0); + } + + return 0; +} diff --git a/hypervisor/arch/x86/guest/vmexit.c b/hypervisor/arch/x86/guest/vmexit.c index 0c8ed839b..8fa25f5ee 100644 --- a/hypervisor/arch/x86/guest/vmexit.c +++ b/hypervisor/arch/x86/guest/vmexit.c @@ -92,12 +92,14 @@ static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = { .handler = undefined_vmexit_handler}, [VMX_EXIT_REASON_VMWRITE] = { .handler = undefined_vmexit_handler}, +#ifndef CONFIG_NVMX_ENABLED [VMX_EXIT_REASON_VMXOFF] = { .handler = undefined_vmexit_handler}, -#ifndef CONFIG_NVMX_ENABLED [VMX_EXIT_REASON_VMXON] = { .handler = undefined_vmexit_handler}, #else + [VMX_EXIT_REASON_VMXOFF] = { + .handler = vmxoff_vmexit_handler}, [VMX_EXIT_REASON_VMXON] = { .handler = vmxon_vmexit_handler, .need_exit_qualification = 1}, diff --git a/hypervisor/include/arch/x86/asm/guest/nested.h b/hypervisor/include/arch/x86/asm/guest/nested.h index 30b9d9f76..d8b30f4c4 100644 --- a/hypervisor/include/arch/x86/asm/guest/nested.h +++ b/hypervisor/include/arch/x86/asm/guest/nested.h @@ -82,6 +82,7 @@ enum VMXResult { }; void nested_vmx_result(enum VMXResult, int error_number); int32_t vmxon_vmexit_handler(struct acrn_vcpu *vcpu); +int32_t vmxoff_vmexit_handler(struct acrn_vcpu *vcpu); #ifdef CONFIG_NVMX_ENABLED struct acrn_nested {