hv: nested: support for VMXOFF emulation

This patch implements the VMXOFF instruction. By issuing VMXOFF,
L1 guest Leaves VMX Operation.

- cleanup VCPU nested virtualization context states in VMXOFF handler.
- implement check_vmx_permission() to check permission for VMX operation
  for VMXOFF and other VMX instructions.

Tracked-On: #5923
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@Intel.com>
This commit is contained in:
Zide Chen 2021-05-07 09:37:20 -07:00 committed by wenlingz
parent 3fdad3c6d1
commit 0a1ac2f4a0
3 changed files with 43 additions and 1 deletions

View File

@ -6,7 +6,9 @@
#include <types.h>
#include <logmsg.h>
#include <asm/mmu.h>
#include <asm/guest/virq.h>
#include <asm/guest/ept.h>
#include <asm/guest/vcpu.h>
#include <asm/guest/vm.h>
#include <asm/guest/nested.h>
@ -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;
}

View File

@ -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},

View File

@ -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 {