public inbox for kvm@vger.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 4/6] x86/fpu: Add guest support to xfd_enable_feature()
Date: Tue, 14 Dec 2021 03:50:25 +0100 (CET)	[thread overview]
Message-ID: <20211214024947.991506193@linutronix.de> (raw)
In-Reply-To: 20211214022825.563892248@linutronix.de

Guest support for dynamically enabling FPU features requires a few
modifications to the enablement function which is currently invoked from
the #NM handler:

  1) Use guest permissions and sizes for the update

  2) Update fpu_guest state accordingly

  3) Take into account that the enabling can be triggered either from a
     running guest via XSETBV and MSR_IA32_XFD write emulation and from
     a guest restore. In the latter case the guests fpstate is not the
     current tasks active fpstate.

Split the function and implement the guest mechanics throughout the
callchain.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
Split out from combo patch. Add fpstate.in_use initialization.
---
 arch/x86/kernel/fpu/xstate.c |   73 ++++++++++++++++++++++---------------------
 arch/x86/kernel/fpu/xstate.h |    2 +
 2 files changed, 41 insertions(+), 34 deletions(-)

--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -1500,35 +1500,13 @@ void fpstate_free(struct fpu *fpu)
 }
 
 /**
- * fpu_install_fpstate - Update the active fpstate in the FPU
- *
- * @fpu:	A struct fpu * pointer
- * @newfps:	A struct fpstate * pointer
- *
- * Returns:	A null pointer if the last active fpstate is the embedded
- *		one or the new fpstate is already installed;
- *		otherwise, a pointer to the old fpstate which has to
- *		be freed by the caller.
- */
-static struct fpstate *fpu_install_fpstate(struct fpu *fpu,
-					   struct fpstate *newfps)
-{
-	struct fpstate *oldfps = fpu->fpstate;
-
-	if (fpu->fpstate == newfps)
-		return NULL;
-
-	fpu->fpstate = newfps;
-	return oldfps != &fpu->__fpstate ? oldfps : NULL;
-}
-
-/**
  * fpstate_realloc - Reallocate struct fpstate for the requested new features
  *
  * @xfeatures:	A bitmap of xstate features which extend the enabled features
  *		of that task
  * @ksize:	The required size for the kernel buffer
  * @usize:	The required size for user space buffers
+ * @guest_fpu:	Pointer to a guest FPU container. NULL for host allocations
  *
  * Note vs. vmalloc(): If the task with a vzalloc()-allocated buffer
  * terminates quickly, vfree()-induced IPIs may be a concern, but tasks
@@ -1537,7 +1515,7 @@ static struct fpstate *fpu_install_fpsta
  * Returns: 0 on success, -ENOMEM on allocation error.
  */
 static int fpstate_realloc(u64 xfeatures, unsigned int ksize,
-			   unsigned int usize)
+			   unsigned int usize, struct fpu_guest *guest_fpu)
 {
 	struct fpu *fpu = &current->thread.fpu;
 	struct fpstate *curfps, *newfps = NULL;
@@ -1553,6 +1531,13 @@ static int fpstate_realloc(u64 xfeatures
 	newfps->user_size = usize;
 	newfps->is_valloc = true;
 
+	if (guest_fpu) {
+		newfps->is_guest = true;
+		newfps->is_confidential = curfps->is_confidential;
+		newfps->in_use = curfps->in_use;
+		guest_fpu->xfeatures |= xfeatures;
+	}
+
 	fpregs_lock();
 	/*
 	 * Ensure that the current state is in the registers before
@@ -1566,15 +1551,25 @@ static int fpstate_realloc(u64 xfeatures
 	newfps->user_xfeatures = curfps->user_xfeatures | xfeatures;
 	newfps->xfd = curfps->xfd & ~xfeatures;
 
-	curfps = fpu_install_fpstate(fpu, newfps);
-
 	/* Do the final updates within the locked region */
 	xstate_init_xcomp_bv(&newfps->regs.xsave, newfps->xfeatures);
-	xfd_update_state(newfps);
 
+	if (guest_fpu) {
+		curfps = xchg(&guest_fpu->fpstate, newfps);
+		/* If curfps is active, update the FPU fpstate pointer */
+		if (fpu->fpstate == curfps)
+			fpu->fpstate = newfps;
+	} else {
+		curfps = xchg(&fpu->fpstate, newfps);
+	}
+
+	xfd_update_state(fpu->fpstate);
 	fpregs_unlock();
 
-	vfree(curfps);
+	/* Only free valloc'ed state */
+	if (curfps && curfps->is_valloc)
+		vfree(curfps);
+
 	return 0;
 }
 
@@ -1682,14 +1677,16 @@ static int xstate_request_perm(unsigned
 	return ret;
 }
 
-int xfd_enable_feature(u64 xfd_err)
+int __xfd_enable_feature(u64 xfd_err, struct fpu_guest *guest_fpu)
 {
 	u64 xfd_event = xfd_err & XFEATURE_MASK_USER_DYNAMIC;
+	struct fpu_state_perm *perm;
 	unsigned int ksize, usize;
 	struct fpu *fpu;
 
 	if (!xfd_event) {
-		pr_err_once("XFD: Invalid xfd error: %016llx\n", xfd_err);
+		if (!guest_fpu)
+			pr_err_once("XFD: Invalid xfd error: %016llx\n", xfd_err);
 		return 0;
 	}
 
@@ -1697,14 +1694,16 @@ int xfd_enable_feature(u64 xfd_err)
 	spin_lock_irq(&current->sighand->siglock);
 
 	/* If not permitted let it die */
-	if ((xstate_get_host_group_perm() & xfd_event) != xfd_event) {
+	if ((xstate_get_group_perm(!!guest_fpu) & xfd_event) != xfd_event) {
 		spin_unlock_irq(&current->sighand->siglock);
 		return -EPERM;
 	}
 
 	fpu = &current->group_leader->thread.fpu;
-	ksize = fpu->perm.__state_size;
-	usize = fpu->perm.__user_state_size;
+	perm = guest_fpu ? &fpu->guest_perm : &fpu->perm;
+	ksize = perm->__state_size;
+	usize = perm->__user_state_size;
+
 	/*
 	 * The feature is permitted. State size is sufficient.  Dropping
 	 * the lock is safe here even if more features are added from
@@ -1717,10 +1716,16 @@ int xfd_enable_feature(u64 xfd_err)
 	 * Try to allocate a new fpstate. If that fails there is no way
 	 * out.
 	 */
-	if (fpstate_realloc(xfd_event, ksize, usize))
+	if (fpstate_realloc(xfd_event, ksize, usize, guest_fpu))
 		return -EFAULT;
 	return 0;
 }
+
+int xfd_enable_feature(u64 xfd_err)
+{
+	return __xfd_enable_feature(xfd_err, NULL);
+}
+
 #else /* CONFIG_X86_64 */
 static inline int xstate_request_perm(unsigned long idx, bool guest)
 {
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -60,6 +60,8 @@ extern void fpu__init_system_xstate(unsi
 
 extern void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
 
+extern int __xfd_enable_feature(u64 which, struct fpu_guest *guest_fpu);
+
 static inline u64 xfeatures_mask_supervisor(void)
 {
 	return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED;


  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 ` Thomas Gleixner [this message]
2021-12-14  6:05   ` [patch 4/6] x86/fpu: Add guest support to xfd_enable_feature() 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 ` [patch 5/6] x86/fpu: Provide fpu_update_guest_xcr0/xfd() Thomas Gleixner
2021-12-14  6:25   ` 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=20211214024947.991506193@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox