All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, "Chang S. Bae" <chang.seok.bae@intel.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Arjan van de Ven <arjan@linux.intel.com>,
	kvm@vger.kernel.org, Paolo Bonzini <pbonzini@redhat.com>,
	"Liu, Jing2" <jing2.liu@intel.com>,
	Sean Christopherson <seanjc@google.com>,
	Xiaoyao Li <xiaoyao.li@intel.com>
Subject: [patch V2 13/30] x86/fpu: Replace KVMs home brewed FPU copy from user
Date: Fri, 15 Oct 2021 03:16:13 +0200 (CEST)	[thread overview]
Message-ID: <20211015011539.134065207@linutronix.de> (raw)
In-Reply-To: 20211015011411.304289784@linutronix.de

Copying a user space buffer to the memory buffer is already available in
the FPU core. The copy mechanism in KVM lacks sanity checks and needs to
use cpuid() to lookup the offset of each component, while the FPU core has
this information cached.

Make the FPU core variant accessible for KVM and replace the home brewed
mechanism.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: kvm@vger.kernel.org
Cc: Paolo Bonzini <pbonzini@redhat.com>

---
 arch/x86/include/asm/fpu/api.h |  2 +-
 arch/x86/kernel/fpu/core.c     | 38 +++++++++++++++++++++-
 arch/x86/kernel/fpu/xstate.c   |  3 +--
 arch/x86/kvm/x86.c             | 74 +------------------------------------------
 4 files changed, 43 insertions(+), 74 deletions(-)
---
diff --git a/arch/x86/include/asm/fpu/api.h b/arch/x86/include/asm/fpu/api.h
index d2b8603a9c7e..77a732ea4cda 100644
--- a/arch/x86/include/asm/fpu/api.h
+++ b/arch/x86/include/asm/fpu/api.h
@@ -116,4 +116,6 @@ extern void fpu_init_fpstate_user(struct fpu *fpu);
 /* KVM specific functions */
 extern void fpu_swap_kvm_fpu(struct fpu *save, struct fpu *rstor, u64 restore_mask);
 
+extern int fpu_copy_kvm_uabi_to_fpstate(struct fpu *fpu, const void *buf, u64 xcr0, u32 *pkru);
+
 #endif /* _ASM_X86_FPU_API_H */
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 023bfe857907..65fc87760011 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -174,7 +174,43 @@ void fpu_swap_kvm_fpu(struct fpu *save, struct fpu *rstor, u64 restore_mask)
 	fpregs_unlock();
 }
 EXPORT_SYMBOL_GPL(fpu_swap_kvm_fpu);
-#endif
+
+int fpu_copy_kvm_uabi_to_fpstate(struct fpu *fpu, const void *buf, u64 xcr0,
+				 u32 *vpkru)
+{
+	union fpregs_state *kstate = &fpu->state;
+	const union fpregs_state *ustate = buf;
+	struct pkru_state *xpkru;
+	int ret;
+
+	if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) {
+		if (ustate->xsave.header.xfeatures & ~XFEATURE_MASK_FPSSE)
+			return -EINVAL;
+		if (ustate->fxsave.mxcsr & ~mxcsr_feature_mask)
+			return -EINVAL;
+		memcpy(&kstate->fxsave, &ustate->fxsave, sizeof(ustate->fxsave));
+		return 0;
+	}
+
+	if (ustate->xsave.header.xfeatures & ~xcr0)
+		return -EINVAL;
+
+	ret = copy_uabi_from_kernel_to_xstate(&kstate->xsave, ustate);
+	if (ret)
+		return ret;
+
+	/* Retrieve PKRU if not in init state */
+	if (kstate->xsave.header.xfeatures & XFEATURE_MASK_PKRU) {
+		xpkru = get_xsave_addr(&kstate->xsave, XFEATURE_PKRU);
+		*vpkru = xpkru->pkru;
+	}
+
+	/* Ensure that XCOMP_BV is set up for XSAVES */
+	xstate_init_xcomp_bv(&kstate->xsave, xfeatures_mask_uabi());
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpu_copy_kvm_uabi_to_fpstate);
+#endif /* CONFIG_KVM */
 
 void kernel_fpu_begin_mask(unsigned int kfpu_mask)
 {
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 68355605ca75..eeeb807b9717 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1134,8 +1134,7 @@ static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf,
 
 /*
  * Convert from a ptrace standard-format kernel buffer to kernel XSAVE[S]
- * format and copy to the target thread. This is called from
- * xstateregs_set().
+ * format and copy to the target thread. Used by ptrace and KVM.
  */
 int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf)
 {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b9fda03162bd..81dd70be631f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4695,8 +4695,6 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
-#define XSTATE_COMPACTION_ENABLED (1ULL << 63)
-
 static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
 {
 	struct xregs_state *xsave = &vcpu->arch.guest_fpu->state.xsave;
@@ -4740,50 +4738,6 @@ static void fill_xsave(u8 *dest, struct kvm_vcpu *vcpu)
 	}
 }
 
-static void load_xsave(struct kvm_vcpu *vcpu, u8 *src)
-{
-	struct xregs_state *xsave = &vcpu->arch.guest_fpu->state.xsave;
-	u64 xstate_bv = *(u64 *)(src + XSAVE_HDR_OFFSET);
-	u64 valid;
-
-	/*
-	 * Copy legacy XSAVE area, to avoid complications with CPUID
-	 * leaves 0 and 1 in the loop below.
-	 */
-	memcpy(xsave, src, XSAVE_HDR_OFFSET);
-
-	/* Set XSTATE_BV and possibly XCOMP_BV.  */
-	xsave->header.xfeatures = xstate_bv;
-	if (boot_cpu_has(X86_FEATURE_XSAVES))
-		xsave->header.xcomp_bv = host_xcr0 | XSTATE_COMPACTION_ENABLED;
-
-	/*
-	 * Copy each region from the non-compacted offset to the
-	 * possibly compacted offset.
-	 */
-	valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
-	while (valid) {
-		u32 size, offset, ecx, edx;
-		u64 xfeature_mask = valid & -valid;
-		int xfeature_nr = fls64(xfeature_mask) - 1;
-
-		cpuid_count(XSTATE_CPUID, xfeature_nr,
-			    &size, &offset, &ecx, &edx);
-
-		if (xfeature_nr == XFEATURE_PKRU) {
-			memcpy(&vcpu->arch.pkru, src + offset,
-			       sizeof(vcpu->arch.pkru));
-		} else {
-			void *dest = get_xsave_addr(xsave, xfeature_nr);
-
-			if (dest)
-				memcpy(dest, src + offset, size);
-		}
-
-		valid -= xfeature_mask;
-	}
-}
-
 static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
 					 struct kvm_xsave *guest_xsave)
 {
@@ -4802,37 +4756,15 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
 	}
 }
 
-#define XSAVE_MXCSR_OFFSET 24
-
 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
 					struct kvm_xsave *guest_xsave)
 {
-	u64 xstate_bv;
-	u32 mxcsr;
-
 	if (!vcpu->arch.guest_fpu)
 		return 0;
 
-	xstate_bv = *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
-	mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)];
-
-	if (boot_cpu_has(X86_FEATURE_XSAVE)) {
-		/*
-		 * Here we allow setting states that are not present in
-		 * CPUID leaf 0xD, index 0, EDX:EAX.  This is for compatibility
-		 * with old userspace.
-		 */
-		if (xstate_bv & ~supported_xcr0 || mxcsr & ~mxcsr_feature_mask)
-			return -EINVAL;
-		load_xsave(vcpu, (u8 *)guest_xsave->region);
-	} else {
-		if (xstate_bv & ~XFEATURE_MASK_FPSSE ||
-			mxcsr & ~mxcsr_feature_mask)
-			return -EINVAL;
-		memcpy(&vcpu->arch.guest_fpu->state.fxsave,
-			guest_xsave->region, sizeof(struct fxregs_state));
-	}
-	return 0;
+	return fpu_copy_kvm_uabi_to_fpstate(vcpu->arch.guest_fpu,
+					    guest_xsave->region,
+					    supported_xcr0, &vcpu->arch.pkru);
 }
 
 static void kvm_vcpu_ioctl_x86_get_xcrs(struct kvm_vcpu *vcpu,


  parent reply	other threads:[~2021-10-15  1:16 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-15  1:15 [patch V2 00/30] x86/fpu: Preparatory cleanups for AMX support (part 1) Thomas Gleixner
2021-10-15  1:15 ` [patch V2 01/30] x86/fpu: Remove pointless argument from switch_fpu_finish() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:15 ` [patch V2 02/30] x86/fpu: Update stale comments Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:15 ` [patch V2 03/30] x86/pkru: Remove useless include Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:15 ` [patch V2 04/30] x86/fpu: Restrict xsaves()/xrstors() to independent states Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 05/30] x86/fpu: Cleanup the on_boot_cpu clutter Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 06/30] x86/fpu: Remove pointless memset in fpu_clone() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 07/30] x86/process: Clone FPU in copy_thread() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 08/30] x86/fpu: Do not inherit FPU context for kernel and IO worker threads Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 09/30] x86/fpu: Cleanup xstate xcomp_bv initialization Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 10/30] x86/fpu/xstate: Provide and use for_each_xfeature() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 11/30] x86/fpu/xstate: Mark all init only functions __init Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 12/30] x86/fpu: Move KVMs FPU swapping to FPU core Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` Thomas Gleixner [this message]
2021-10-20 13:44   ` [tip: x86/fpu] x86/fpu: Replace KVMs home brewed FPU copy from user tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 14/30] x86/fpu: Rework copy_xstate_to_uabi_buf() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 15/30] x86/fpu: Replace KVMs home brewed FPU copy to user Thomas Gleixner
2021-10-21 15:12   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 16/30] x86/fpu: Mark fpu__init_prepare_fx_sw_frame() as __init Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 17/30] x86/fpu: Move context switch and exit to user inlines into sched.h Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 18/30] x86/fpu: Clean up cpu feature tests Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] x86/fpu: Clean up CPU " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 19/30] x86/fpu: Make os_xrstor_booting() private Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 20/30] x86/fpu: Move os_xsave() and os_xrstor() to core Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 21/30] x86/fpu: Move legacy ASM wrappers " Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 22/30] x86/fpu: Make WARN_ON_FPU() private Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 23/30] x86/fpu: Move fpregs_restore_userregs() to core Thomas Gleixner
2021-10-19 18:11   ` Borislav Petkov
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 24/30] x86/fpu: Move mxcsr related code " Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 25/30] x86/fpu: Move fpstate functions to api.h Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 26/30] x86/fpu: Remove internal.h dependency from fpu/signal.h Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 27/30] x86/sev: Include fpu/xcr.h Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 28/30] x86/fpu: Mop up the internal.h leftovers Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 29/30] x86/fpu: Replace the includes of fpu/internal.h Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner
2021-10-15  1:16 ` [patch V2 30/30] x86/fpu: Provide a proper function for ex_handler_fprestore() Thomas Gleixner
2021-10-20 13:44   ` [tip: x86/fpu] " tip-bot2 for Thomas Gleixner

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=20211015011539.134065207@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=arjan@linux.intel.com \
    --cc=chang.seok.bae@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=jing2.liu@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=x86@kernel.org \
    --cc=xiaoyao.li@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.