From 51a747d9c822434a7f12ddb22389aa067151092c Mon Sep 17 00:00:00 2001 From: Shiqing Gao Date: Tue, 24 Aug 2021 14:46:59 +0800 Subject: [PATCH] hv: check the capability of XSAVES/XRSTORS instructions before execution For platforms that do not support XSAVES/XRSTORS instructions, like QEMU, executing these instructions causes #UD. This patch adds the check before the execution of XSAVES/XRSTORS instructions. It also refines the logic inside rstore_xsave_area for the following reason: If XSAVES/XRSTORS instructions are supported, restore XSAVE area if any of the following conditions is met: 1. "vcpu->launched" is false (state initialization for guest) 2. "vcpu->arch.xsave_enabled" is true (state restoring for guest) * Before vCPU is launched, condition 1 is satisfied. * After vCPU is launched, condition 2 is satisfied because is_valid_xsave_combination() guarantees that "vcpu->arch.xsave_enabled" is consistent with pcpu_has_cap(X86_FEATURE_XSAVES). Therefore, the check against "vcpu->launched" and "vcpu->arch.xsave_enabled" can be eliminated here. Tracked-On: #6481 Signed-off-by: Shiqing Gao Acked-by: Eddie Dong --- hypervisor/arch/x86/guest/vcpu.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpu.c b/hypervisor/arch/x86/guest/vcpu.c index d349e202d..0addb1054 100644 --- a/hypervisor/arch/x86/guest/vcpu.c +++ b/hypervisor/arch/x86/guest/vcpu.c @@ -832,9 +832,9 @@ void zombie_vcpu(struct acrn_vcpu *vcpu, enum vcpu_state new_state) } } -void save_xsave_area(struct acrn_vcpu *vcpu, struct ext_context *ectx) +void save_xsave_area(__unused struct acrn_vcpu *vcpu, struct ext_context *ectx) { - if (vcpu->arch.xsave_enabled) { + if (pcpu_has_cap(X86_FEATURE_XSAVES)) { ectx->xcr0 = read_xcr(0); write_xcr(0, ectx->xcr0 | XSAVE_SSE); xsaves(&ectx->xs_area, UINT64_MAX); @@ -843,7 +843,18 @@ void save_xsave_area(struct acrn_vcpu *vcpu, struct ext_context *ectx) void rstore_xsave_area(const struct acrn_vcpu *vcpu, const struct ext_context *ectx) { - if ((!vcpu->launched) || (vcpu->arch.xsave_enabled)) { + if (pcpu_has_cap(X86_FEATURE_XSAVES)) { + /* + * Restore XSAVE area if any of the following conditions is met: + * 1. "vcpu->launched" is false (state initialization for guest) + * 2. "vcpu->arch.xsave_enabled" is true (state restoring for guest) + * + * Before vCPU is launched, condition 1 is satisfied. + * After vCPU is launched, condition 2 is satisfied because is_valid_xsave_combination() guarantees + * that "vcpu->arch.xsave_enabled" is consistent with pcpu_has_cap(X86_FEATURE_XSAVES). + * + * Therefore, the check against "vcpu->launched" and "vcpu->arch.xsave_enabled" can be eliminated here. + */ write_xcr(0, ectx->xcr0 | XSAVE_SSE); msr_write(MSR_IA32_XSS, vcpu_get_guest_msr(vcpu, MSR_IA32_XSS)); xrstors(&ectx->xs_area, UINT64_MAX);