From ccfdf9cdd79a5acbbc2ecc10e9f3e57175d1e557 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Tue, 30 Mar 2021 20:19:21 -0700 Subject: [PATCH] hv: nested: enable nested virtualization Allow guest set CR4_VMXE if CONFIG_NVMX_ENABLED is set: - move CR4_VMXE from CR4_EMULATED_RESERVE_BITS to CR4_TRAP_AND_EMULATE_BITS so that CR4_VMXE is removed from cr4_reserved_bits_mask. - force CR4_VMXE to be removed from cr4_rsv_bits_guest_value so that CR4_VMXE is able to be set. Expose VMX feature (CPUID01.01H:ECX[5]) to L1 guests whose GUEST_FLAG_NVMX_ENABLED is set. Assuming guest hypervisor (L1) is KVM, and KVM uses EPT for L2 guests. Constraints on ACRN VM. - LAPIC passthrough should be enabled. - use SCHED_NOOP scheduler. Tracked-On: #5923 Signed-off-by: Sainath Grandhi Signed-off-by: Zide Chen Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vcpuid.c | 6 ++++-- hypervisor/arch/x86/guest/virtual_cr.c | 12 ++++++++++++ hypervisor/arch/x86/guest/vm.c | 10 ++++++++++ hypervisor/include/arch/x86/asm/guest/vm.h | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpuid.c b/hypervisor/arch/x86/guest/vcpuid.c index 24773435b..a776bccbd 100644 --- a/hypervisor/arch/x86/guest/vcpuid.c +++ b/hypervisor/arch/x86/guest/vcpuid.c @@ -460,8 +460,10 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx /* mask SDBG for silicon debug */ *ecx &= ~CPUID_ECX_SDBG; - /*mask vmx to guest os */ - *ecx &= ~CPUID_ECX_VMX; + /* mask VMX to guest OS */ + if (!is_nvmx_configured(vcpu->vm)) { + *ecx &= ~CPUID_ECX_VMX; + } /* set Hypervisor Present Bit */ *ecx |= CPUID_ECX_HV; diff --git a/hypervisor/arch/x86/guest/virtual_cr.c b/hypervisor/arch/x86/guest/virtual_cr.c index 9357c65cf..91085cf42 100644 --- a/hypervisor/arch/x86/guest/virtual_cr.c +++ b/hypervisor/arch/x86/guest/virtual_cr.c @@ -57,10 +57,18 @@ static uint64_t cr4_passthru_mask = CR4_PASSTHRU_BITS; /* bound to flexible bits #define CR4_TRAP_AND_PASSTHRU_BITS (CR4_PSE | CR4_PAE | CR4_SMEP | CR4_SMAP | CR4_PKE | CR4_PKS | CR4_KL) static uint64_t cr4_trap_and_passthru_mask = CR4_TRAP_AND_PASSTHRU_BITS; /* bound to flexible bits */ +#ifdef CONFIG_NVMX_ENABLED +#define CR4_TRAP_AND_EMULATE_BITS (CR4_VMXE | CR4_MCE) /* software emulated bits even if host is fixed */ +#else #define CR4_TRAP_AND_EMULATE_BITS CR4_MCE /* software emulated bits even if host is fixed */ +#endif /* Change of these bits should change vcpuid too */ +#ifdef CONFIG_NVMX_ENABLED +#define CR4_EMULATED_RESERVE_BITS (CR4_CET | CR4_SMXE) +#else #define CR4_EMULATED_RESERVE_BITS (CR4_VMXE | CR4_CET | CR4_SMXE) +#endif /* The physical CR4 value for bits of CR4_EMULATED_RESERVE_BITS */ #define CR4_EMRSV_BITS_PHYS_VALUE CR4_VMXE @@ -484,6 +492,10 @@ void init_cr0_cr4_flexible_bits(void) * Refer SDM Appendix A.8 */ cr4_rsv_bits_guest_value = (fixed0 & ~cr4_flexible_bits); + +#ifdef CONFIG_NVMX_ENABLED + cr4_rsv_bits_guest_value &= ~CR4_VMXE; +#endif initial_guest_cr4 = (cr4_rsv_bits_guest_value & ~CR4_EMULATED_RESERVE_BITS) | CR4_EMRSV_BITS_PHYS_VALUE; cr4_rsv_bits_guest_value = (cr4_rsv_bits_guest_value & ~CR4_EMULATED_RESERVE_BITS) | CR4_EMRSV_BITS_VIRT_VALUE; diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 7b2b6a217..3a79fc447 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -137,6 +137,16 @@ bool is_rt_vm(const struct acrn_vm *vm) return ((vm_config->guest_flags & GUEST_FLAG_RT) != 0U); } +/** + * @pre vm != NULL && vm_config != NULL && vm->vmid < CONFIG_MAX_VM_NUM + */ +bool is_nvmx_configured(const struct acrn_vm *vm) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + + return ((vm_config->guest_flags & GUEST_FLAG_NVMX_ENABLED) != 0U); +} + /** * @brief VT-d PI posted mode can possibly be used for PTDEVs assigned * to this VM if platform supports VT-d PI AND lapic passthru is not configured diff --git a/hypervisor/include/arch/x86/asm/guest/vm.h b/hypervisor/include/arch/x86/asm/guest/vm.h index 5bb4fd630..72197c1e6 100644 --- a/hypervisor/include/arch/x86/asm/guest/vm.h +++ b/hypervisor/include/arch/x86/asm/guest/vm.h @@ -255,6 +255,7 @@ void vrtc_init(struct acrn_vm *vm); bool is_lapic_pt_configured(const struct acrn_vm *vm); bool is_rt_vm(const struct acrn_vm *vm); +bool is_nvmx_configured(const struct acrn_vm *vm); bool is_pi_capable(const struct acrn_vm *vm); bool has_rt_vm(void); struct acrn_vm *get_highest_severity_vm(bool runtime);