hv: nested: define VMCS shadow fields

Enable VMCS shadowing for most of the VMCS fields, so that execution of
the VMREAD or VMWRITE on these shadow VMCS fields from L1 hypervisor
won't cause VM exits, but read from or write to the shadow VMCS.

Tracked-On: #5923
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Signed-off-by: Alexander Merritt <alex.merritt@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
This commit is contained in:
Zide Chen 2021-05-11 13:37:20 -07:00 committed by wenlingz
parent 863e58e539
commit 5379b14108
2 changed files with 159 additions and 2 deletions

View File

@ -228,8 +228,7 @@ int32_t read_vmx_msr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
return err; return err;
} }
/* make it 1 to be able to build. correctly initialize it in next patch */ #define MAX_SHADOW_VMCS_FIELDS 117U
#define MAX_SHADOW_VMCS_FIELDS 1
/* /*
* VMCS fields included in the dual-purpose VMCS: as shadow for L1 and * VMCS fields included in the dual-purpose VMCS: as shadow for L1 and
* as hardware VMCS for nested guest (L2). * as hardware VMCS for nested guest (L2).
@ -244,11 +243,157 @@ int32_t read_vmx_msr(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
* for all platforms. * for all platforms.
*/ */
static const uint32_t vmcs_shadowing_fields[MAX_SHADOW_VMCS_FIELDS] = { static const uint32_t vmcs_shadowing_fields[MAX_SHADOW_VMCS_FIELDS] = {
/* 16-bits */
VMX_VPID,
VMX_GUEST_ES_SEL,
VMX_GUEST_CS_SEL,
VMX_GUEST_SS_SEL,
VMX_GUEST_DS_SEL,
VMX_GUEST_FS_SEL,
VMX_GUEST_GS_SEL,
VMX_GUEST_LDTR_SEL,
VMX_GUEST_TR_SEL,
VMX_GUEST_PML_INDEX,
/* 64-bits */
VMX_IO_BITMAP_A_FULL,
VMX_IO_BITMAP_B_FULL,
VMX_EXIT_MSR_STORE_ADDR_FULL,
VMX_EXIT_MSR_LOAD_ADDR_FULL,
VMX_ENTRY_MSR_LOAD_ADDR_FULL,
VMX_EXECUTIVE_VMCS_PTR_FULL,
VMX_TSC_OFFSET_FULL,
VMX_VIRTUAL_APIC_PAGE_ADDR_FULL,
VMX_APIC_ACCESS_ADDR_FULL,
VMX_EPT_POINTER_FULL,
VMX_VMREAD_BITMAP_FULL,
VMX_VMWRITE_BITMAP_FULL,
VMX_XSS_EXITING_BITMAP_FULL,
VMX_TSC_MULTIPLIER_FULL,
VMX_GUEST_PHYSICAL_ADDR_FULL,
VMX_VMS_LINK_PTR_FULL,
VMX_GUEST_IA32_DEBUGCTL_FULL,
VMX_GUEST_IA32_PAT_FULL,
VMX_GUEST_IA32_EFER_FULL,
VMX_GUEST_IA32_PERF_CTL_FULL,
VMX_GUEST_PDPTE0_FULL,
VMX_GUEST_PDPTE1_FULL,
VMX_GUEST_PDPTE2_FULL,
VMX_GUEST_PDPTE3_FULL,
/* 32-bits */
VMX_PIN_VM_EXEC_CONTROLS,
VMX_PROC_VM_EXEC_CONTROLS,
VMX_EXCEPTION_BITMAP,
VMX_PF_ERROR_CODE_MASK,
VMX_PF_ERROR_CODE_MATCH,
VMX_CR3_TARGET_COUNT,
VMX_EXIT_CONTROLS,
VMX_EXIT_MSR_STORE_COUNT,
VMX_EXIT_MSR_LOAD_COUNT,
VMX_ENTRY_CONTROLS,
VMX_ENTRY_MSR_LOAD_COUNT,
VMX_ENTRY_INT_INFO_FIELD,
VMX_ENTRY_EXCEPTION_ERROR_CODE,
VMX_ENTRY_INSTR_LENGTH,
VMX_TPR_THRESHOLD,
VMX_PROC_VM_EXEC_CONTROLS2,
VMX_PLE_GAP,
VMX_PLE_WINDOW,
VMX_INSTR_ERROR,
VMX_EXIT_REASON,
VMX_EXIT_INT_INFO,
VMX_EXIT_INT_ERROR_CODE,
VMX_IDT_VEC_INFO_FIELD,
VMX_IDT_VEC_ERROR_CODE,
VMX_EXIT_INSTR_LEN,
VMX_INSTR_INFO,
VMX_GUEST_ES_LIMIT,
VMX_GUEST_CS_LIMIT,
VMX_GUEST_SS_LIMIT,
VMX_GUEST_DS_LIMIT,
VMX_GUEST_FS_LIMIT,
VMX_GUEST_GS_LIMIT,
VMX_GUEST_LDTR_LIMIT,
VMX_GUEST_TR_LIMIT,
VMX_GUEST_GDTR_LIMIT,
VMX_GUEST_IDTR_LIMIT,
VMX_GUEST_ES_ATTR,
VMX_GUEST_CS_ATTR,
VMX_GUEST_SS_ATTR,
VMX_GUEST_DS_ATTR,
VMX_GUEST_FS_ATTR,
VMX_GUEST_GS_ATTR,
VMX_GUEST_LDTR_ATTR,
VMX_GUEST_TR_ATTR,
VMX_GUEST_INTERRUPTIBILITY_INFO,
VMX_GUEST_ACTIVITY_STATE,
VMX_GUEST_SMBASE,
VMX_GUEST_IA32_SYSENTER_CS,
VMX_GUEST_TIMER,
VMX_CR0_GUEST_HOST_MASK,
VMX_CR4_GUEST_HOST_MASK,
VMX_CR0_READ_SHADOW,
VMX_CR4_READ_SHADOW,
VMX_CR3_TARGET_0,
VMX_CR3_TARGET_1,
VMX_CR3_TARGET_2,
VMX_CR3_TARGET_3,
VMX_EXIT_QUALIFICATION,
VMX_IO_RCX,
VMX_IO_RSI,
VMX_IO_RDI,
VMX_IO_RIP,
VMX_GUEST_LINEAR_ADDR,
VMX_GUEST_CR0,
VMX_GUEST_CR3,
VMX_GUEST_CR4,
VMX_GUEST_ES_BASE,
VMX_GUEST_CS_BASE,
VMX_GUEST_SS_BASE,
VMX_GUEST_DS_BASE,
VMX_GUEST_FS_BASE,
VMX_GUEST_GS_BASE,
VMX_GUEST_LDTR_BASE,
VMX_GUEST_TR_BASE,
VMX_GUEST_GDTR_BASE,
VMX_GUEST_IDTR_BASE,
VMX_GUEST_DR7,
VMX_GUEST_RSP,
VMX_GUEST_RIP,
VMX_GUEST_RFLAGS,
VMX_GUEST_PENDING_DEBUG_EXCEPT,
VMX_GUEST_IA32_SYSENTER_ESP,
VMX_GUEST_IA32_SYSENTER_EIP
}; };
/* to be shared by all vCPUs for all nested guests */ /* to be shared by all vCPUs for all nested guests */
static uint64_t vmcs_shadowing_bitmap[PAGE_SIZE / sizeof(uint64_t)] __aligned(PAGE_SIZE); static uint64_t vmcs_shadowing_bitmap[PAGE_SIZE / sizeof(uint64_t)] __aligned(PAGE_SIZE);
static void setup_vmcs_shadowing_bitmap(void)
{
uint16_t field_index;
uint32_t array_index;
uint16_t bit_pos;
/*
* Set all the bits to 1s first and clear out the bits for
* the corresponding fields that ACRN lets its guest to access Shadow VMCS
*/
memset((void *)vmcs_shadowing_bitmap, 0xFFU, PAGE_SIZE);
/*
* Refer to ISDM Section 24.6.15 VMCS Shadowing Bitmap Addresses
* and Section 30.3 VMX Instructions - VMWRITE/VMREAD
*/
for (field_index = 0U; field_index < MAX_SHADOW_VMCS_FIELDS; field_index++) {
bit_pos = vmcs_shadowing_fields[field_index] % 64U;
array_index = vmcs_shadowing_fields[field_index] / 64U;
bitmap_clear_nolock(bit_pos, &vmcs_shadowing_bitmap[array_index]);
}
}
/* /*
* This is an array of offsets into a structure of type "struct acrn_vmcs12" * This is an array of offsets into a structure of type "struct acrn_vmcs12"
* 16 offsets for a total of 16 GROUPs. 4 "field widths" by 4 "field types". * 16 offsets for a total of 16 GROUPs. 4 "field widths" by 4 "field types".
@ -848,5 +993,6 @@ void init_nested_vmx(__unused struct acrn_vm *vm)
/* Cache the value of physical MSR_IA32_VMX_BASIC */ /* Cache the value of physical MSR_IA32_VMX_BASIC */
vmx_basic = (uint32_t)msr_read(MSR_IA32_VMX_BASIC); vmx_basic = (uint32_t)msr_read(MSR_IA32_VMX_BASIC);
setup_vmcs_shadowing_bitmap();
} }
} }

View File

@ -20,6 +20,7 @@
#define VMX_GUEST_LDTR_SEL 0x0000080cU #define VMX_GUEST_LDTR_SEL 0x0000080cU
#define VMX_GUEST_TR_SEL 0x0000080eU #define VMX_GUEST_TR_SEL 0x0000080eU
#define VMX_GUEST_INTR_STATUS 0x00000810U #define VMX_GUEST_INTR_STATUS 0x00000810U
#define VMX_GUEST_PML_INDEX 0x00000812U
/* 16-bit host-state fields */ /* 16-bit host-state fields */
#define VMX_HOST_ES_SEL 0x00000c00U #define VMX_HOST_ES_SEL 0x00000c00U
#define VMX_HOST_CS_SEL 0x00000c02U #define VMX_HOST_CS_SEL 0x00000c02U
@ -43,6 +44,7 @@
#define VMX_ENTRY_MSR_LOAD_ADDR_HIGH 0x0000200bU #define VMX_ENTRY_MSR_LOAD_ADDR_HIGH 0x0000200bU
#define VMX_EXECUTIVE_VMCS_PTR_FULL 0x0000200cU #define VMX_EXECUTIVE_VMCS_PTR_FULL 0x0000200cU
#define VMX_EXECUTIVE_VMCS_PTR_HIGH 0x0000200dU #define VMX_EXECUTIVE_VMCS_PTR_HIGH 0x0000200dU
#define VMX_PML_ADDR_FULL 0x0000200EU
#define VMX_TSC_OFFSET_FULL 0x00002010U #define VMX_TSC_OFFSET_FULL 0x00002010U
#define VMX_TSC_OFFSET_HIGH 0x00002011U #define VMX_TSC_OFFSET_HIGH 0x00002011U
#define VMX_VIRTUAL_APIC_PAGE_ADDR_FULL 0x00002012U #define VMX_VIRTUAL_APIC_PAGE_ADDR_FULL 0x00002012U
@ -51,6 +53,7 @@
#define VMX_APIC_ACCESS_ADDR_HIGH 0x00002015U #define VMX_APIC_ACCESS_ADDR_HIGH 0x00002015U
#define VMX_PIR_DESC_ADDR_FULL 0x00002016U #define VMX_PIR_DESC_ADDR_FULL 0x00002016U
#define VMX_PIR_DESC_ADDR_HIGH 0x00002017U #define VMX_PIR_DESC_ADDR_HIGH 0x00002017U
#define VMX_VM_FUNCTION_CTL_FULL 0x00002018U
#define VMX_EPT_POINTER_FULL 0x0000201AU #define VMX_EPT_POINTER_FULL 0x0000201AU
#define VMX_EPT_POINTER_HIGH 0x0000201BU #define VMX_EPT_POINTER_HIGH 0x0000201BU
#define VMX_EOI_EXIT0_FULL 0x0000201CU #define VMX_EOI_EXIT0_FULL 0x0000201CU
@ -61,13 +64,16 @@
#define VMX_EOI_EXIT2_HIGH 0x00002021U #define VMX_EOI_EXIT2_HIGH 0x00002021U
#define VMX_EOI_EXIT3_FULL 0x00002022U #define VMX_EOI_EXIT3_FULL 0x00002022U
#define VMX_EOI_EXIT3_HIGH 0x00002023U #define VMX_EOI_EXIT3_HIGH 0x00002023U
#define VMX_EPT_LIST_ADDR_FULL 0x00002024U
#define VMX_VMREAD_BITMAP_FULL 0x00002026U #define VMX_VMREAD_BITMAP_FULL 0x00002026U
#define VMX_VMREAD_BITMAP_HIGH 0x00002027U #define VMX_VMREAD_BITMAP_HIGH 0x00002027U
#define VMX_VMWRITE_BITMAP_FULL 0x00002028U #define VMX_VMWRITE_BITMAP_FULL 0x00002028U
#define VMX_VMWRITE_BITMAP_HIGH 0x00002029U #define VMX_VMWRITE_BITMAP_HIGH 0x00002029U
#define VMX_VIR_EXCEPTION_INFO_FULL 0x0000202AU
#define VMX_XSS_EXITING_BITMAP_FULL 0x0000202CU #define VMX_XSS_EXITING_BITMAP_FULL 0x0000202CU
#define VMX_XSS_EXITING_BITMAP_HIGH 0x0000202DU #define VMX_XSS_EXITING_BITMAP_HIGH 0x0000202DU
#define VMX_TSC_MULTIPLIER_FULL 0x00002032U
#define VMX_PROC_VM_EXEC_CONTROLS3_FULL 0x00002034U #define VMX_PROC_VM_EXEC_CONTROLS3_FULL 0x00002034U
#define VMX_PROC_VM_EXEC_CONTROLS3_HIGH 0x00002035U #define VMX_PROC_VM_EXEC_CONTROLS3_HIGH 0x00002035U
@ -94,6 +100,9 @@
#define VMX_GUEST_PDPTE2_HIGH 0x0000280FU #define VMX_GUEST_PDPTE2_HIGH 0x0000280FU
#define VMX_GUEST_PDPTE3_FULL 0x00002810U #define VMX_GUEST_PDPTE3_FULL 0x00002810U
#define VMX_GUEST_PDPTE3_HIGH 0x00002811U #define VMX_GUEST_PDPTE3_HIGH 0x00002811U
#define VMX_GUEST_IA32_BNDCFGS_FULL 0x00002812U
#define VMX_GUEST_IA32_BNDCFGS_HIGH 0x00002813U
/* 64-bit host-state fields */ /* 64-bit host-state fields */
#define VMX_HOST_IA32_PAT_FULL 0x00002C00U #define VMX_HOST_IA32_PAT_FULL 0x00002C00U
#define VMX_HOST_IA32_PAT_HIGH 0x00002C01U #define VMX_HOST_IA32_PAT_HIGH 0x00002C01U
@ -167,7 +176,9 @@
/* natural-width read-only data fields */ /* natural-width read-only data fields */
#define VMX_EXIT_QUALIFICATION 0x00006400U #define VMX_EXIT_QUALIFICATION 0x00006400U
#define VMX_IO_RCX 0x00006402U #define VMX_IO_RCX 0x00006402U
#define VMX_IO_RSI 0x00006404U
#define VMX_IO_RDI 0x00006406U #define VMX_IO_RDI 0x00006406U
#define VMX_IO_RIP 0x00006408U
#define VMX_GUEST_LINEAR_ADDR 0x0000640aU #define VMX_GUEST_LINEAR_ADDR 0x0000640aU
/* natural-width guest-state fields */ /* natural-width guest-state fields */
#define VMX_GUEST_CR0 0x00006800U #define VMX_GUEST_CR0 0x00006800U