linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: guang.zeng@intel.com, jing2.liu@intel.com, kevin.tian@intel.com,
	seanjc@google.com, tglx@linutronix.de, wei.w.wang@intel.com,
	yang.zhong@intel.com
Subject: [PATCH v6 21/21] kvm: x86: Disable interception for IA32_XFD on demand
Date: Fri,  7 Jan 2022 13:55:12 -0500	[thread overview]
Message-ID: <20220107185512.25321-22-pbonzini@redhat.com> (raw)
In-Reply-To: <20220107185512.25321-1-pbonzini@redhat.com>

From: Kevin Tian <kevin.tian@intel.com>

Always intercepting IA32_XFD causes non-negligible overhead when this
register is updated frequently in the guest.

Disable r/w emulation after intercepting the first WRMSR(IA32_XFD)
with a non-zero value.

Disable WRMSR emulation implies that IA32_XFD becomes out-of-sync
with the software states in fpstate and the per-cpu xfd cache. This
leads to two additional changes accordingly:

  - Call fpu_sync_guest_vmexit_xfd_state() after vm-exit to bring
    software states back in-sync with the MSR, before handle_exit_irqoff()
    is called.

  - Always trap #NM once write interception is disabled for IA32_XFD.
    The #NM exception is rare if the guest doesn't use dynamic
    features. Otherwise, there is at most one exception per guest
    task given a dynamic feature.

p.s. We have confirmed that SDM is being revised to say that
when setting IA32_XFD[18] the AMX register state is not guaranteed
to be preserved. This clarification avoids adding mess for a creative
guest which sets IA32_XFD[18]=1 before saving active AMX state to
its own storage.

Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jing Liu <jing2.liu@intel.com>
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Message-Id: <20220105123532.12586-22-yang.zhong@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx/vmx.c          | 24 +++++++++++++++++++-----
 arch/x86/kvm/vmx/vmx.h          |  2 +-
 arch/x86/kvm/x86.c              |  8 ++++++++
 4 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 6cbf97a2ebc4..89d1fdb39c46 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -647,6 +647,7 @@ struct kvm_vcpu_arch {
 	u64 smi_count;
 	bool tpr_access_reporting;
 	bool xsaves_enabled;
+	bool xfd_no_write_intercept;
 	u64 ia32_xss;
 	u64 microcode_version;
 	u64 arch_capabilities;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index b8b7f5c7b3df..15e30602782b 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -162,6 +162,7 @@ static u32 vmx_possible_passthrough_msrs[MAX_POSSIBLE_PASSTHROUGH_MSRS] = {
 	MSR_FS_BASE,
 	MSR_GS_BASE,
 	MSR_KERNEL_GS_BASE,
+	MSR_IA32_XFD,
 	MSR_IA32_XFD_ERR,
 #endif
 	MSR_IA32_SYSENTER_CS,
@@ -764,10 +765,11 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu)
 	}
 
 	/*
-	 * Trap #NM if guest xfd contains a non-zero value so guest XFD_ERR
-	 * can be saved timely.
+	 * Disabling xfd interception indicates that dynamic xfeatures
+	 * might be used in the guest. Always trap #NM in this case
+	 * to save guest xfd_err timely.
 	 */
-	if (vcpu->arch.guest_fpu.fpstate->xfd)
+	if (vcpu->arch.xfd_no_write_intercept)
 		eb |= (1u << NM_VECTOR);
 
 	vmcs_write32(EXCEPTION_BITMAP, eb);
@@ -1978,9 +1980,21 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		break;
 	case MSR_IA32_XFD:
 		ret = kvm_set_msr_common(vcpu, msr_info);
-		/* Update #NM interception according to guest xfd */
-		if (!ret)
+		/*
+		 * Always intercepting WRMSR could incur non-negligible
+		 * overhead given xfd might be changed frequently in
+		 * guest context switch. Disable write interception
+		 * upon the first write with a non-zero value (indicating
+		 * potential usage on dynamic xfeatures). Also update
+		 * exception bitmap to trap #NM for proper virtualization
+		 * of guest xfd_err.
+		 */
+		if (!ret && data) {
+			vmx_disable_intercept_for_msr(vcpu, MSR_IA32_XFD,
+						      MSR_TYPE_RW);
+			vcpu->arch.xfd_no_write_intercept = true;
 			vmx_update_exception_bitmap(vcpu);
+		}
 		break;
 #endif
 	case MSR_IA32_SYSENTER_CS:
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 69dd2f85abdc..f8fc7441baea 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -349,7 +349,7 @@ struct vcpu_vmx {
 	struct lbr_desc lbr_desc;
 
 	/* Save desired MSR intercept (read: pass-through) state */
-#define MAX_POSSIBLE_PASSTHROUGH_MSRS	14
+#define MAX_POSSIBLE_PASSTHROUGH_MSRS	15
 	struct {
 		DECLARE_BITMAP(read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
 		DECLARE_BITMAP(write, MAX_POSSIBLE_PASSTHROUGH_MSRS);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bde18ca657db..60da2331ec32 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10083,6 +10083,14 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
 
+	/*
+	 * Sync xfd before calling handle_exit_irqoff() which may
+	 * rely on the fact that guest_fpu::xfd is up-to-date (e.g.
+	 * in #NM irqoff handler).
+	 */
+	if (vcpu->arch.xfd_no_write_intercept)
+		fpu_sync_guest_vmexit_xfd_state();
+
 	static_call(kvm_x86_handle_exit_irqoff)(vcpu);
 
 	if (vcpu->arch.guest_fpu.xfd_err)
-- 
2.31.1


      parent reply	other threads:[~2022-01-07 18:56 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-07 18:54 [PATCH v6 00/21] AMX support for KVM Paolo Bonzini
2022-01-07 18:54 ` [PATCH v6 01/21] x86/fpu: Extend fpu_xstate_prctl() with guest permissions Paolo Bonzini
2022-01-07 18:54 ` [PATCH v6 02/21] x86/fpu: Prepare guest FPU for dynamically enabled FPU features Paolo Bonzini
2022-01-07 18:54 ` [PATCH v6 03/21] kvm: x86: Fix xstate_required_size() to follow XSTATE alignment rule Paolo Bonzini
2022-01-07 18:54 ` [PATCH v6 04/21] kvm: x86: Exclude unpermitted xfeatures at KVM_GET_SUPPORTED_CPUID Paolo Bonzini
2022-01-23  6:22   ` Like Xu
2022-01-24  7:18     ` Tian, Kevin
2022-01-07 18:54 ` [PATCH v6 05/21] x86/fpu: Make XFD initialization in __fpstate_reset() a function argument Paolo Bonzini
2022-01-07 19:43   ` Borislav Petkov
2022-01-10  5:15     ` Tian, Kevin
2022-01-10  8:52       ` Borislav Petkov
2022-01-10 14:18         ` Paolo Bonzini
2022-01-10 15:25           ` Borislav Petkov
2022-01-10 15:55             ` Paolo Bonzini
2022-01-10 18:18               ` Borislav Petkov
2022-01-11  1:45                 ` Tian, Kevin
2022-01-07 18:54 ` [PATCH v6 06/21] x86/fpu: Add guest support to xfd_enable_feature() Paolo Bonzini
2022-01-07 18:54 ` [PATCH v6 07/21] x86/fpu: Provide fpu_enable_guest_xfd_features() for KVM Paolo Bonzini
2022-01-10  5:25   ` Tian, Kevin
2022-01-07 18:54 ` [PATCH v6 08/21] kvm: x86: Enable dynamic xfeatures at KVM_SET_CPUID2 Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 09/21] x86/fpu: Provide fpu_update_guest_xfd() for IA32_XFD emulation Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 10/21] kvm: x86: Add emulation for IA32_XFD Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 11/21] x86/fpu: Prepare xfd_err in struct fpu_guest Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 12/21] kvm: x86: Intercept #NM for saving IA32_XFD_ERR Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 13/21] kvm: x86: Emulate IA32_XFD_ERR for guest Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 14/21] kvm: x86: Disable RDMSR interception of IA32_XFD_ERR Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 15/21] kvm: x86: Add XCR0 support for Intel AMX Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 16/21] kvm: x86: Add CPUID " Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 17/21] x86/fpu: Add uabi_size to guest_fpu Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 18/21] kvm: x86: Add support for getting/setting expanded xstate buffer Paolo Bonzini
2022-01-07 18:55 ` [PATCH v6 19/21] kvm: selftests: Add support for KVM_CAP_XSAVE2 Paolo Bonzini
2022-01-17 16:51   ` Janis Schoetterl-Glausch
2022-01-18  2:06     ` Wang, Wei W
2022-01-07 18:55 ` [PATCH v6 20/21] x86/fpu: Provide fpu_sync_guest_vmexit_xfd_state() Paolo Bonzini
2022-01-07 18:55 ` Paolo Bonzini [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220107185512.25321-22-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=guang.zeng@intel.com \
    --cc=jing2.liu@intel.com \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=wei.w.wang@intel.com \
    --cc=yang.zhong@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).