hv: nested: support for VMXON emulation

This patch emulates VMXON instruction. Basically checks some
prerequisites to enable VMX operation on L1 guest (next patch), and
prepares some virtual hardware environment in L0.

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-04-29 12:23:42 -07:00
committed by wenlingz
parent b93d6b2ef0
commit fc8f07e740
5 changed files with 70 additions and 4 deletions

View File

@@ -6,6 +6,7 @@
#include <types.h>
#include <logmsg.h>
#include <asm/guest/virq.h>
#include <asm/guest/vcpu.h>
#include <asm/guest/vm.h>
#include <asm/guest/nested.h>
@@ -220,3 +221,43 @@ int32_t read_vmx_msr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
*val = v;
return err;
}
void nested_vmx_result(enum VMXResult result, int error_number)
{
uint64_t rflags = exec_vmread(VMX_GUEST_RFLAGS);
/* ISDM: section 30.2 CONVENTIONS */
rflags &= ~(RFLAGS_C | RFLAGS_P | RFLAGS_A | RFLAGS_Z | RFLAGS_S | RFLAGS_O);
if (result == VMfailValid) {
rflags |= RFLAGS_Z;
exec_vmwrite(VMX_INSTR_ERROR, error_number);
} else if (result == VMfailInvalid) {
rflags |= RFLAGS_C;
} else {
/* VMsucceed, do nothing */
}
if (result != VMsucceed) {
pr_err("VMX failed: %d/%d", result, error_number);
}
exec_vmwrite(VMX_GUEST_RFLAGS, rflags);
}
/*
* @pre vcpu != NULL
*/
int32_t vmxon_vmexit_handler(struct acrn_vcpu *vcpu)
{
/* Will do permission check in next patch */
if (is_nvmx_configured(vcpu->vm)) {
vcpu->arch.nested.vmxon = true;
nested_vmx_result(VMsucceed, 0);
} else {
vcpu_inject_ud(vcpu);
}
return 0;
}

View File

@@ -94,8 +94,14 @@ static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
.handler = undefined_vmexit_handler},
[VMX_EXIT_REASON_VMXOFF] = {
.handler = undefined_vmexit_handler},
#ifndef CONFIG_NVMX_ENABLED
[VMX_EXIT_REASON_VMXON] = {
.handler = undefined_vmexit_handler},
#else
[VMX_EXIT_REASON_VMXON] = {
.handler = vmxon_vmexit_handler,
.need_exit_qualification = 1},
#endif
[VMX_EXIT_REASON_CR_ACCESS] = {
.handler = cr_access_vmexit_handler,
.need_exit_qualification = 1},
@@ -460,10 +466,8 @@ static int32_t loadiwkey_vmexit_handler(struct acrn_vcpu *vcpu)
return 0;
}
/* vmexit handler for just injecting a #UD exception
*
* ACRN doesn't support nested virtualization, the following VMExit will inject #UD
* VMCLEAR/VMLAUNCH/VMPTRST/VMREAD/VMRESUME/VMWRITE/VMXOFF/VMXON.
/*
* vmexit handler for just injecting a #UD exception
* ACRN doesn't enable VMFUNC, VMFUNC treated as undefined.
*/
static int32_t undefined_vmexit_handler(struct acrn_vcpu *vcpu)