diff --git a/hypervisor/arch/x86/guest/vmexit.c b/hypervisor/arch/x86/guest/vmexit.c index 4f0201e04..24b1b9c2d 100644 --- a/hypervisor/arch/x86/guest/vmexit.c +++ b/hypervisor/arch/x86/guest/vmexit.c @@ -283,6 +283,14 @@ int32_t cpuid_vmexit_handler(struct acrn_vcpu *vcpu) /* * XSETBV instruction set's the XCR0 that is used to tell for which * components states can be saved on a context switch using xsave. + * + * According to SDM vol3 25.1.1: + * Invalid-opcode exception (UD) and faults based on privilege level (include + * virtual-8086 mode previleged instructions are not recognized) have higher + * priority than VM exit. + * + * We don't need to handle those case here because we depends on VMX to handle + * them. */ static int32_t xsetbv_vmexit_handler(struct acrn_vcpu *vcpu) { @@ -308,6 +316,8 @@ static int32_t xsetbv_vmexit_handler(struct acrn_vcpu *vcpu) /* bit 0(x87 state) of XCR0 can't be cleared */ if ((val64 & 0x01UL) == 0UL) { vcpu_inject_gp(vcpu, 0U); + } else if ((val64 & XCR0_RESERVED_BITS) != 0UL) { + vcpu_inject_gp(vcpu, 0U); } else { /* * XCR0[2:1] (SSE state & AVX state) can't not be diff --git a/hypervisor/include/arch/x86/cpu.h b/hypervisor/include/arch/x86/cpu.h index 7054e753b..489cc1cfb 100644 --- a/hypervisor/include/arch/x86/cpu.h +++ b/hypervisor/include/arch/x86/cpu.h @@ -85,13 +85,20 @@ #define CR4_PKE (1UL<<22U) /* Protect-key-enable */ /* XCR0_SSE */ -#define XCR0_SSE (1U<<1U) +#define XCR0_SSE (1UL<<1U) /* XCR0_AVX */ -#define XCR0_AVX (1U<<2U) +#define XCR0_AVX (1UL<<2U) /* XCR0_BNDREGS */ -#define XCR0_BNDREGS (1U<<3U) +#define XCR0_BNDREGS (1UL<<3U) /* XCR0_BNDCSR */ -#define XCR0_BNDCSR (1U<<4U) +#define XCR0_BNDCSR (1UL<<4U) +/* According to SDM Vol1 13.3: + * XCR0[63:10] and XCR0[8] are reserved. Executing the XSETBV instruction causes + * a general-protection fault if ECX = 0 and any corresponding bit in EDX:EAX + * is not 0. + */ +#define XCR0_RESERVED_BITS ((~((1UL << 10U) - 1UL)) | (1UL << 8U)) + /* * Entries in the Interrupt Descriptor Table (IDT)