All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Jing Liu <jing2.liu@linux.intel.com>,
	Yang Zhong <yang.zhong@intel.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	x86@kernel.org, kvm@vger.kernel.org,
	Sean Christoperson <seanjc@google.com>,
	Jin Nakajima <jun.nakajima@intel.com>,
	Kevin Tian <kevin.tian@intel.com>
Subject: [patch 5/6] x86/fpu: Provide fpu_update_guest_xcr0/xfd()
Date: Tue, 14 Dec 2021 03:50:27 +0100 (CET)	[thread overview]
Message-ID: <20211214024948.048572883@linutronix.de> (raw)
In-Reply-To: 20211214022825.563892248@linutronix.de

KVM can require fpstate expansion due to updates to XCR0 and to the XFD
MSR. In both cases it is required to check whether:

  - the requested values are correct or permitted

  - the resulting xfeature mask which is relevant for XSAVES is a subset of
    the guests fpstate xfeature mask for which the register buffer is sized.

    If the feature mask does not fit into the guests fpstate then
    reallocation is required.

Provide a common update function which utilizes the existing XFD enablement
mechanics and two wrapper functions, one for XCR0 and one for XFD.

These wrappers have to be invoked from XSETBV emulation and the XFD MSR
write emulation.

XCR0 modification can only proceed when fpu_update_guest_xcr0() returns
success.

XFD modification is done by the FPU core code as it requires to update the
software state as well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
New version to handle the restore case and XCR0 updates correctly.
---
 arch/x86/include/asm/fpu/api.h |   57 +++++++++++++++++++++++++++++++++++++++++
 arch/x86/kernel/fpu/core.c     |   57 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)

--- a/arch/x86/include/asm/fpu/api.h
+++ b/arch/x86/include/asm/fpu/api.h
@@ -136,6 +136,63 @@ extern void fpstate_clear_xstate_compone
 extern bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu);
 extern void fpu_free_guest_fpstate(struct fpu_guest *gfpu);
 extern int fpu_swap_kvm_fpstate(struct fpu_guest *gfpu, bool enter_guest);
+extern int __fpu_update_guest_features(struct fpu_guest *guest_fpu, u64 xcr0, u64 xfd);
+
+/**
+ * fpu_update_guest_xcr0 - Update guest XCR0 from XSETBV emulation
+ * @guest_fpu:	Pointer to the guest FPU container
+ * @xcr0:	Requested guest XCR0
+ *
+ * Has to be invoked before making the guest XCR0 update effective. The
+ * function validates that the requested features are permitted and ensures
+ * that @guest_fpu->fpstate is properly sized taking @guest_fpu->fpstate->xfd
+ * into account.
+ *
+ * If @guest_fpu->fpstate is not the current tasks active fpstate then the
+ * caller has to ensure that @guest_fpu->fpstate cannot be concurrently in
+ * use, i.e. the guest restore case.
+ *
+ * Return:
+ * 0		- Success
+ * -EPERM	- Feature(s) not permitted
+ * -EFAULT	- Resizing of fpstate failed
+ */
+static inline int fpu_update_guest_xcr0(struct fpu_guest *guest_fpu, u64 xcr0)
+{
+	return __fpu_update_guest_features(guest_fpu, xcr0, guest_fpu->fpstate->xfd);
+}
+
+/**
+ * fpu_update_guest_xfd - Update guest XFD from MSR write emulation
+ * @guest_fpu:	Pointer to the guest FPU container
+ * @xcr0:	Current guest XCR0
+ * @xfd:	Requested XFD value
+ *
+ * Has to be invoked to make the guest XFD update effective. The function
+ * validates the XFD value and ensures that @guest_fpu->fpstate is properly
+ * sized by taking @xcr0 into account.
+ *
+ * The caller must not modify @guest_fpu->fpstate->xfd or the XFD MSR
+ * directly.
+ *
+ * If @guest_fpu->fpstate is not the current tasks active fpstate then the
+ * caller has to ensure that @guest_fpu->fpstate cannot be concurrently in
+ * use, i.e. the guest restore case.
+ *
+ * On success the buffer size is valid, @guest_fpu->fpstate.xfd == @xfd and
+ * if the guest fpstate is active then MSR_IA32_XFD == @xfd.
+ *
+ * On failure the previous state is retained.
+ *
+ * Return:
+ * 0		- Success
+ * -ENOTSUPP	- XFD value not supported
+ * -EFAULT	- Resizing of fpstate failed
+ */
+static inline int fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xcr0, u64 xfd)
+{
+	return __fpu_update_guest_features(guest_fpu, xcr0, xfd);
+}
 
 extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, unsigned int size, u32 pkru);
 extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru);
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -261,6 +261,63 @@ void fpu_free_guest_fpstate(struct fpu_g
 }
 EXPORT_SYMBOL_GPL(fpu_free_guest_fpstate);
 
+/**
+ * __fpu_update_guest_features - Validate and enable guest XCR0 and XFD updates
+ * @guest_fpu:	Pointer to the guest FPU container
+ * @xcr0:	Guest XCR0
+ * @xfd:	Guest XFD
+ *
+ * Note: @xcr0 and @xfd must either be the already validated values or the
+ * requested values (guest emulation or host write on restore).
+ *
+ * Do not invoke directly. Use the provided wrappers fpu_validate_guest_xcr0()
+ * and fpu_update_guest_xfd() instead.
+ *
+ * Return: 0 on success, error code otherwise
+ */
+int __fpu_update_guest_features(struct fpu_guest *guest_fpu, u64 xcr0, u64 xfd)
+{
+	u64 expand, requested;
+
+	lockdep_assert_preemption_enabled();
+
+	/* Only permitted features are allowed in XCR0 */
+	if (xcr0 & ~guest_fpu->perm)
+		return -EPERM;
+
+	/* Check for unsupported XFD values */
+	if (xfd & ~XFEATURE_MASK_USER_DYNAMIC || xfd & ~fpu_user_cfg.max_features)
+		return -ENOTSUPP;
+
+	if (!IS_ENABLED(CONFIG_X86_64))
+		return 0;
+
+	/*
+	 * The requested features are set in XCR0 and not set in XFD.
+	 * Feature expansion is required when the requested features are
+	 * not a subset of the xfeatures for which @guest_fpu->fpstate
+	 * is sized.
+	 */
+	requested = xcr0 & ~xfd;
+	expand = requested & ~guest_fpu->xfeatures;
+	if (!expand) {
+		/*
+		 * fpstate size is correct, update the XFD value in fpstate
+		 * and if @guest_fpu->fpstate is active also the per CPU
+		 * cache and the MSR.
+		 */
+		fpregs_lock();
+		guest_fpu->fpstate->xfd = xfd;
+		if (guest_fpu->fpstate->in_use)
+			xfd_update_state(guest_fpu->fpstate);
+		fpregs_unlock();
+		return 0;
+	}
+
+	return __xfd_enable_feature(expand, guest_fpu);
+}
+EXPORT_SYMBOL_GPL(__fpu_update_guest_features);
+
 int fpu_swap_kvm_fpstate(struct fpu_guest *guest_fpu, bool enter_guest)
 {
 	struct fpstate *guest_fps = guest_fpu->fpstate;


  parent reply	other threads:[~2021-12-14  2:50 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-14  2:50 [patch 0/6] x86/fpu: Preparatory changes for guest AMX support Thomas Gleixner
2021-12-14  2:50 ` [patch 1/6] x86/fpu: Extend fpu_xstate_prctl() with guest permissions Thomas Gleixner
2021-12-14  5:13   ` Tian, Kevin
2021-12-14 10:37     ` Paolo Bonzini
2021-12-14  2:50 ` [patch 2/6] x86/fpu: Prepare guest FPU for dynamically enabled FPU features Thomas Gleixner
2021-12-14  2:50 ` [patch 3/6] x86/fpu: Make XFD initialization in __fpstate_reset() a function argument Thomas Gleixner
2021-12-14  2:50 ` [patch 4/6] x86/fpu: Add guest support to xfd_enable_feature() Thomas Gleixner
2021-12-14  6:05   ` Tian, Kevin
2021-12-14 10:21     ` Paolo Bonzini
2021-12-14 13:15       ` Thomas Gleixner
2021-12-15  5:46         ` Tian, Kevin
2021-12-15  9:53           ` Thomas Gleixner
2021-12-15 10:02             ` Tian, Kevin
2021-12-14  2:50 ` Thomas Gleixner [this message]
2021-12-14  6:25   ` [patch 5/6] x86/fpu: Provide fpu_update_guest_xcr0/xfd() Tian, Kevin
2021-12-14 15:09   ` Wang, Wei W
2021-12-14 15:40     ` Thomas Gleixner
2021-12-14 16:11       ` Wang, Wei W
2021-12-14 18:04         ` Thomas Gleixner
2021-12-14 19:07           ` Juan Quintela
2021-12-14 20:28             ` Thomas Gleixner
2021-12-14 21:35               ` Juan Quintela
2021-12-15  2:17                 ` Wang, Wei W
2021-12-15 10:09                   ` Thomas Gleixner
2021-12-15 10:27                     ` Paolo Bonzini
2021-12-15 10:41                       ` Paolo Bonzini
2021-12-16  1:00                         ` Tian, Kevin
2021-12-16  5:36                         ` Tian, Kevin
2021-12-16 21:07                           ` Paolo Bonzini
2021-12-16 10:21                         ` Tian, Kevin
2021-12-16 10:24                           ` Paolo Bonzini
2021-12-16 10:26                           ` Paolo Bonzini
2021-12-16 13:00                         ` Tian, Kevin
2021-12-16  1:04                       ` Tian, Kevin
2021-12-16  9:34                         ` Thomas Gleixner
2021-12-16  9:59                           ` Tian, Kevin
2021-12-16 14:12                             ` Thomas Gleixner
2021-12-17 15:33                               ` Tian, Kevin
2021-12-15  6:14   ` Tian, Kevin
2021-12-14  2:50 ` [patch 6/6] x86/fpu: Provide kvm_sync_guest_vmexit_xfd_state() Thomas Gleixner
2021-12-15  6:35   ` Liu, Jing2
2021-12-15  9:49     ` Thomas Gleixner
2021-12-14  6:50 ` [patch 0/6] x86/fpu: Preparatory changes for guest AMX support Tian, Kevin
2021-12-14  6:52 ` Liu, Jing2
2021-12-14  7:54   ` Tian, Kevin
2021-12-14 10:42 ` Paolo Bonzini
2021-12-14 13:24   ` 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=20211214024948.048572883@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=jing2.liu@linux.intel.com \
    --cc=jun.nakajima@intel.com \
    --cc=kevin.tian@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=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 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.