mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 06:29:19 +00:00
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:
parent
f4b93f31b7
commit
55d9161138
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -133,7 +133,11 @@
|
||||
#define EFER_LMA 0x00000400U /* Long mode active (R) */
|
||||
|
||||
#define RFLAGS_C (1U<<0U)
|
||||
#define RFLAGS_P (1U<<2U)
|
||||
#define RFLAGS_A (1U<<4U)
|
||||
#define RFLAGS_Z (1U<<6U)
|
||||
#define RFLAGS_S (1U<<7U)
|
||||
#define RFLAGS_O (1U<<11U)
|
||||
#define RFLAGS_AC (1U<<18U)
|
||||
|
||||
/* CPU clock frequencies (FSB) */
|
||||
|
@ -51,11 +51,25 @@ union value_64 {
|
||||
*/
|
||||
#define VMCS12_REVISION_ID 0x15407E12U
|
||||
|
||||
enum VMXResult {
|
||||
VMsucceed,
|
||||
VMfailValid,
|
||||
VMfailInvalid,
|
||||
};
|
||||
void nested_vmx_result(enum VMXResult, int error_number);
|
||||
int32_t vmxon_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
|
||||
#ifdef CONFIG_NVMX_ENABLED
|
||||
struct acrn_nested {
|
||||
bool vmxon; /* To indicate if vCPU entered VMX operation */
|
||||
} __aligned(PAGE_SIZE);
|
||||
|
||||
bool is_vmx_msr(uint32_t msr);
|
||||
void init_vmx_msrs(struct acrn_vcpu *vcpu);
|
||||
int32_t read_vmx_msr(__unused struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val);
|
||||
#else
|
||||
struct acrn_nested {};
|
||||
|
||||
static inline bool is_vmx_msr(__unused uint32_t msr)
|
||||
{
|
||||
/*
|
||||
|
@ -219,6 +219,9 @@ struct acrn_vcpu_arch {
|
||||
/* vmcs region for this vcpu, MUST be 4KB-aligned */
|
||||
uint8_t vmcs[PAGE_SIZE];
|
||||
|
||||
/* context for nested virtualization, 4KB-aligned */
|
||||
struct acrn_nested nested;
|
||||
|
||||
/* MSR bitmap region for this vcpu, MUST be 4-Kbyte aligned */
|
||||
uint8_t msr_bitmap[PAGE_SIZE];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user