mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 00/19] x86, mpx updates for 4.2 (take 8)
@ 2015-05-29 22:34 Dave Hansen
  2015-05-29 22:34 ` [PATCH 01/19] x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions Dave Hansen
                   ` (5 more replies)
  0 siblings, 6 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, tglx, Dave Hansen


Changes from take 7 / v22:
 * Add Thomas's reviewed-by
 * merge with tip/x86/fpu changes
 * Fix tiny spelling nit

Changes from take 6 / v21:
 * Address a bunch of Thomas's review comments.

Changes from take 5 / v20:

 * Fix get_xsave_addr() to consult xstate_bv in anticipation
   of fixes to xsave code.
 * Bug fix for when an VMA being unmapped has neighbors which
   are bounds tables.
 * Rewrite unmapping code.  I didn't do this lightly. It was
   not originally my own code, and I resisted changing it
   because it worked.  But, I started bug chasing and decided
   it was unmaintainable.  The rewrite ended up removing
   about 20% of the unmapping code and made it much simpler.

Changes from take 4 / v19:

 * Do not pass a task_struct around when we are
   really just going to operate on current

Changes from take 3 / v18 (all minor):

 * use DECLARE_EVENT_CLASS()/DEFINE_EVENT() for
   the ranged tracepoints to save 10 lines of code.

Changes from take 2 / v17 (all minor):

 * fix a couple of whitespace borkages caught by checkpatch,
   and a spelling error or two.
 * replace printk with pr_info() for boot disable
 * change trace print format for address intervals
 * fix up variable name in tsk_get_xsave_addr() comment
 * remove tsk_get_xsave_field() GPL export
 * fix up Qiaowei's From:

--

Hi x86 maintainers,

There are a few basic things going on here:
1. Make FPU/xsave code preempt safe and work properly
2. Add trace points to make kernel and app debugging easier
3. Add a boot-time disable for mpx
4. Rewrite the unmapping code.
5. Support 32-bit binaries to run on 64-bit kernels

This set is also available against tip/x86/fpu (8c05f05edb) in git:

  git://git.kernel.org/pub/scm/linux/kernel/git/daveh/x86-mpx.git mpx-v23

Dave Hansen (19):
  x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions
  x86, fpu: Wrap get_xsave_addr() to make it safer
  x86, mpx: Use new get_xsave_field_ptr()
  x86, mpx: Cleanup: Do not pass task around when unnecessary
  x86, mpx: remove redundant MPX_BNDCFG_ADDR_MASK
  x86, mpx: Restrict mmap size check to bounds tables
  x86, mpx: boot-time disable
  x86, mpx: trace #BR exceptions
  x86, mpx: trace entry to bounds exception paths
  x86, mpx: Trace the attempts to find bounds tables
  x86, mpx: trace allocation of new bounds tables
  x86: make is_64bit_mm() widely available
  x86, mpx: Add temporary variable to reduce masking
  x86, mpx: new directory entry to addr helper
  x86, mpx: do 32-bit-only cmpxchg for 32-bit apps
  x86, mpx: support 32-bit binaries on 64-bit kernel
  x86, mpx: rewrite unmap code
  x86, mpx: do not count MPX VMAs as neighbors when unmapping
  x86, mpx: allow mixed binaries again

 Documentation/kernel-parameters.txt |   4 +
 arch/x86/include/asm/fpu/xstate.h   |   1 +
 arch/x86/include/asm/mmu_context.h  |  13 +
 arch/x86/include/asm/mpx.h          |  74 +++---
 arch/x86/include/asm/processor.h    |  12 +-
 arch/x86/include/asm/trace/mpx.h    | 131 ++++++++++
 arch/x86/kernel/cpu/common.c        |  16 ++
 arch/x86/kernel/fpu/xstate.c        |  78 +++++-
 arch/x86/kernel/traps.c             |  18 +-
 arch/x86/kernel/uprobes.c           |  10 +-
 arch/x86/mm/mpx.c                   | 508 ++++++++++++++++++++++--------------
 kernel/sys.c                        |   8 +-
 12 files changed, 606 insertions(+), 267 deletions(-)
 create mode 100644 arch/x86/include/asm/trace/mpx.h


^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 01/19] x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
@ 2015-05-29 22:34 ` Dave Hansen
  2015-05-29 22:34 ` [PATCH 03/19] x86, mpx: Use new get_xsave_field_ptr() Dave Hansen
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, tglx, Dave Hansen, dave.hansen


From: Dave Hansen <dave.hansen@linux.intel.com>

get_xsave_addr() assumes that if an xsave bit is present in the
hardware (pcntxt_mask) that it is present in a given xsave
buffer.  Due to an bug in the xsave code on all of the systems
that have MPX (and thus all the users of this code), that has
been a true assumption.

But, the bug is getting fixed, so our assumption is not going
to hold any more.

It's quite possible (and normal) for an enabled state to be
present on 'pcntxt_mask', but *not* in 'xstate_bv'.  We need
to consult 'xstate_bv'.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---

 b/arch/x86/kernel/fpu/xstate.c |   45 +++++++++++++++++++++++++++++++++--------
 1 file changed, 37 insertions(+), 8 deletions(-)

diff -puN arch/x86/kernel/fpu/xstate.c~consullt-xstate_bv arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~consullt-xstate_bv	2015-05-27 09:32:14.540445571 -0700
+++ b/arch/x86/kernel/fpu/xstate.c	2015-05-27 09:32:14.543445706 -0700
@@ -382,19 +382,48 @@ void fpu__resume_cpu(void)
  * This is the API that is called to get xstate address in either
  * standard format or compacted format of xsave area.
  *
+ * Note that if there is no data for the field in the xsave buffer
+ * this will return NULL.
+ *
  * Inputs:
- *	xsave: base address of the xsave area;
- *	xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
- *	etc.)
+ *	xstate: the thread's storage area for all FPU data
+ *	xstate_feature: state which is defined in xsave.h (e.g.
+ *	XSTATE_FP, XSTATE_SSE, etc...)
  * Output:
- *	address of the state in the xsave area.
+ *	address of the state in the xsave area, or NULL if the
+ *	field is not present in the xsave buffer.
  */
-void *get_xsave_addr(struct xregs_state *xsave, int xstate)
+void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
 {
-	int feature = fls64(xstate) - 1;
-	if (!test_bit(feature, (unsigned long *)&xfeatures_mask))
+	int feature_nr = fls64(xstate_feature) - 1;
+	/*
+	 * Do we even *have* xsave state?
+	 */
+	if (!boot_cpu_has(X86_FEATURE_XSAVE))
+		return NULL;
+
+	xsave = &current->thread.fpu.state.xsave;
+	/*
+	 * We should not ever be requesting features that we
+	 * have not enabled.  Remember that pcntxt_mask is
+	 * what we write to the XCR0 register.
+	 */
+	WARN_ONCE(!(xfeatures_mask & xstate_feature),
+		  "get of unsupported state");
+	/*
+	 * This assumes the last 'xsave*' instruction to
+	 * have requested that 'xstate_feature' be saved.
+	 * If it did not, we might be seeing and old value
+	 * of the field in the buffer.
+	 *
+	 * This can happen because the last 'xsave' did not
+	 * request that this feature be saved (unlikely)
+	 * or because the "init optimization" caused it
+	 * to not be saved.
+	 */
+	if (!(xsave->header.xfeatures & xstate_feature))
 		return NULL;
 
-	return (void *)xsave + xstate_comp_offsets[feature];
+	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
  2015-05-29 22:34 ` [PATCH 01/19] x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions Dave Hansen
  2015-05-29 22:34 ` [PATCH 03/19] x86, mpx: Use new get_xsave_field_ptr() Dave Hansen
@ 2015-05-29 22:34 ` Dave Hansen
  2015-05-29 22:34 ` [PATCH 05/19] x86, mpx: remove redundant MPX_BNDCFG_ADDR_MASK Dave Hansen
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code appears to be saving off the FPU in a potntially
unsafe way (if eagerfpu=off).  It does not disable preemption or
ensure that the FPU state has been allocated.  All of the
preemption safety comes from the unfortunatley-named
'unlazy_fpu()'.

This patch introduces a new helper which will do both of those
things internally.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>

---

Changes from v21:
 * add comments about preemption
 * rename helper to get_xsave_field_ptr()

Changes from "v19":
 * remove 'tsk' argument to get_xsave_addr() since the code
   can only realistically work on 'current', and fix up the
   comment a bit to match.

Changes from "v17":
 * fix s/xstate/xsave_field/ in the function comment
 * remove EXPORT_SYMBOL_GPL()

---

 b/arch/x86/include/asm/fpu/xstate.h |    1 +
 b/arch/x86/kernel/fpu/xstate.c      |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff -puN arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr arch/x86/include/asm/fpu/xstate.h
--- a/arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr	2015-05-28 08:49:45.191271502 -0700
+++ b/arch/x86/include/asm/fpu/xstate.h	2015-05-29 13:43:34.291184369 -0700
@@ -41,5 +41,6 @@ extern u64 xstate_fx_sw_bytes[USER_XSTAT
 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
 
 void *get_xsave_addr(struct xregs_state *xsave, int xstate);
+const void *get_xsave_field_ptr(int xstate_field);
 
 #endif
diff -puN arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr	2015-05-28 08:49:45.192271546 -0700
+++ b/arch/x86/kernel/fpu/xstate.c	2015-05-29 12:32:47.869662576 -0700
@@ -427,3 +427,35 @@ void *get_xsave_addr(struct xregs_state
 	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
+
+/*
+ * This wraps up the common operations that need to occur when retrieving
+ * data from xsave state.  It first ensures that the current task was
+ * using the FPU and retrieves the data in to a buffer.  It then calculates
+ * the offset of the requested field in the buffer.
+ *
+ * This function is safe to call whether the FPU is in use or not.
+ *
+ * Note that this only works on the current task.
+ *
+ * Inputs:
+ *	@xsave_state: state which is defined in xsave.h (e.g. XSTATE_FP,
+ *	XSTATE_SSE, etc...)
+ * Output:
+ *	address of the state in the xsave area or NULL if the state
+ *	is not present or is in its 'init state'.
+ */
+const void *get_xsave_field_ptr(int xsave_state)
+{
+	struct fpu *fpu = &current->thread.fpu;
+
+	if (!fpu->fpstate_active)
+		return NULL;
+	/*
+	 * fpu__save() takes the CPU's xstate registers
+	 * and saves them off to the 'fpu memory buffer.
+	 */
+	fpu__save(fpu);
+
+	return get_xsave_addr(&fpu->xstate->xsave, xsave_state);
+}
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 03/19] x86, mpx: Use new get_xsave_field_ptr()
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
  2015-05-29 22:34 ` [PATCH 01/19] x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions Dave Hansen
@ 2015-05-29 22:34 ` Dave Hansen
  2015-05-29 22:34 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX registers (bndcsr/bndcfgu/bndstatus) are not directly
accessible via normal instructions.  They essentially act as
if they were floating point registers and are saved/restored
along with those registers.

There are two main paths in the MPX code where we care about
the contents of these registers:
	1. #BR (bounds) faults
	2. the prctl() code where we are setting MPX up

Both of those paths _might_ be called without the FPU having
been used.  That means that 'tsk->thread.fpu.state' might
never be allocated.

Also, fpu_save_init() is not preempt-safe.  It was a bug to
call it without disabling preemption.  The new
get_xsave_addr() calls unlazy_fpu() instead and properly
disables preemption.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>
Cc: linux-kernel <linux-kernel@vger.kernel.org>

---

Changes from v21:
 * rename get_xsave_field() to get_xsave_field_ptr()
---

 b/arch/x86/include/asm/mpx.h |    8 ++++----
 b/arch/x86/kernel/traps.c    |   15 +++++++--------
 b/arch/x86/mm/mpx.c          |   24 ++++++++++++------------
 3 files changed, 23 insertions(+), 24 deletions(-)

diff -puN arch/x86/include/asm/mpx.h~use-new-tsk_get_xsave_addr arch/x86/include/asm/mpx.h
--- a/arch/x86/include/asm/mpx.h~use-new-tsk_get_xsave_addr	2015-05-27 09:32:15.346481924 -0700
+++ b/arch/x86/include/asm/mpx.h	2015-05-27 09:32:15.353482240 -0700
@@ -60,8 +60,8 @@
 
 #ifdef CONFIG_X86_INTEL_MPX
 siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-				struct xregs_state *xsave_buf);
-int mpx_handle_bd_fault(struct xregs_state *xsave_buf);
+				struct task_struct *tsk);
+int mpx_handle_bd_fault(struct task_struct *tsk);
 static inline int kernel_managing_mpx_tables(struct mm_struct *mm)
 {
 	return (mm->bd_addr != MPX_INVALID_BOUNDS_DIR);
@@ -78,11 +78,11 @@ void mpx_notify_unmap(struct mm_struct *
 		      unsigned long start, unsigned long end);
 #else
 static inline siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-					      struct xregs_state *xsave_buf)
+					      struct task_struct *tsk)
 {
 	return NULL;
 }
-static inline int mpx_handle_bd_fault(struct xregs_state *xsave_buf)
+static inline int mpx_handle_bd_fault(struct task_struct *tsk)
 {
 	return -EINVAL;
 }
diff -puN arch/x86/kernel/traps.c~use-new-tsk_get_xsave_addr arch/x86/kernel/traps.c
--- a/arch/x86/kernel/traps.c~use-new-tsk_get_xsave_addr	2015-05-27 09:32:15.348482015 -0700
+++ b/arch/x86/kernel/traps.c	2015-05-27 09:32:15.353482240 -0700
@@ -59,6 +59,7 @@
 #include <asm/fixmap.h>
 #include <asm/mach_traps.h>
 #include <asm/alternative.h>
+#include <asm/fpu/xstate.h>
 #include <asm/mpx.h>
 
 #ifdef CONFIG_X86_64
@@ -371,7 +372,6 @@ dotraplinkage void do_double_fault(struc
 dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
 {
 	struct task_struct *tsk = current;
-	struct xregs_state *xsave_buf;
 	enum ctx_state prev_state;
 	struct bndcsr *bndcsr;
 	siginfo_t *info;
@@ -392,12 +392,11 @@ dotraplinkage void do_bounds(struct pt_r
 
 	/*
 	 * We need to look at BNDSTATUS to resolve this exception.
-	 * It is not directly accessible, though, so we need to
-	 * do an xsave and then pull it out of the xsave buffer.
+	 * A NULL here might mean that it is in its 'init state',
+	 * which is all zeros which indicates MPX was not
+	 * responsible for the exception.
 	 */
-	copy_fpregs_to_fpstate(&tsk->thread.fpu);
-	xsave_buf = &(tsk->thread.fpu.state.xsave);
-	bndcsr = get_xsave_addr(xsave_buf, XSTATE_BNDCSR);
+	bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR);
 	if (!bndcsr)
 		goto exit_trap;
 
@@ -408,11 +407,11 @@ dotraplinkage void do_bounds(struct pt_r
 	 */
 	switch (bndcsr->bndstatus & MPX_BNDSTA_ERROR_CODE) {
 	case 2:	/* Bound directory has invalid entry. */
-		if (mpx_handle_bd_fault(xsave_buf))
+		if (mpx_handle_bd_fault(tsk))
 			goto exit_trap;
 		break; /* Success, it was handled */
 	case 1: /* Bound violation. */
-		info = mpx_generate_siginfo(regs, xsave_buf);
+		info = mpx_generate_siginfo(regs, tsk);
 		if (IS_ERR(info)) {
 			/*
 			 * We failed to decode the MPX instruction.  Act as if
diff -puN arch/x86/mm/mpx.c~use-new-tsk_get_xsave_addr arch/x86/mm/mpx.c
--- a/arch/x86/mm/mpx.c~use-new-tsk_get_xsave_addr	2015-05-27 09:32:15.349482059 -0700
+++ b/arch/x86/mm/mpx.c	2015-05-27 09:32:15.354482285 -0700
@@ -272,7 +272,7 @@ bad_opcode:
  * The caller is expected to kfree() the returned siginfo_t.
  */
 siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-				struct xregs_state *xsave_buf)
+				struct task_struct *tsk)
 {
 	struct bndreg *bndregs, *bndreg;
 	siginfo_t *info = NULL;
@@ -294,8 +294,8 @@ siginfo_t *mpx_generate_siginfo(struct p
 		err = -EINVAL;
 		goto err_out;
 	}
-	/* get the bndregs _area_ of the xsave structure */
-	bndregs = get_xsave_addr(xsave_buf, XSTATE_BNDREGS);
+	/* get bndregs field from current task's xsave area */
+	bndregs = get_xsave_field_ptr(XSTATE_BNDREGS);
 	if (!bndregs) {
 		err = -EINVAL;
 		goto err_out;
@@ -357,8 +357,7 @@ static __user void *task_get_bounds_dir(
 	 * The bounds directory pointer is stored in a register
 	 * only accessible if we first do an xsave.
 	 */
-	copy_fpregs_to_fpstate(&tsk->thread.fpu);
-	bndcsr = get_xsave_addr(&tsk->thread.fpu.state.xsave, XSTATE_BNDCSR);
+	bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR);
 	if (!bndcsr)
 		return MPX_INVALID_BOUNDS_DIR;
 
@@ -389,9 +388,10 @@ int mpx_enable_management(struct task_st
 	 * directory into XSAVE/XRSTOR Save Area and enable MPX through
 	 * XRSTOR instruction.
 	 *
-	 * copy_xregs_to_kernel() is expected to be very expensive. Storing the bounds
-	 * directory here means that we do not have to do xsave in the unmap
-	 * path; we can just use mm->bd_addr instead.
+	 * The copy_xregs_to_kernel() beneath get_xsave_field_ptr() is
+	 * expected to be relatively expensive. Storing the bounds
+	 * directory here means that we do not have to do xsave in the
+	 * unmap path; we can just use mm->bd_addr instead.
 	 */
 	bd_base = task_get_bounds_dir(tsk);
 	down_write(&mm->mmap_sem);
@@ -497,12 +497,12 @@ out_unmap:
  * bound table is 16KB. With 64-bit mode, the size of BD is 2GB,
  * and the size of each bound table is 4MB.
  */
-static int do_mpx_bt_fault(struct xregs_state *xsave_buf)
+static int do_mpx_bt_fault(struct task_struct *tsk)
 {
 	unsigned long bd_entry, bd_base;
 	struct bndcsr *bndcsr;
 
-	bndcsr = get_xsave_addr(xsave_buf, XSTATE_BNDCSR);
+	bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR);
 	if (!bndcsr)
 		return -EINVAL;
 	/*
@@ -525,7 +525,7 @@ static int do_mpx_bt_fault(struct xregs_
 	return allocate_bt((long __user *)bd_entry);
 }
 
-int mpx_handle_bd_fault(struct xregs_state *xsave_buf)
+int mpx_handle_bd_fault(struct task_struct *tsk)
 {
 	/*
 	 * Userspace never asked us to manage the bounds tables,
@@ -534,7 +534,7 @@ int mpx_handle_bd_fault(struct xregs_sta
 	if (!kernel_managing_mpx_tables(current->mm))
 		return -EINVAL;
 
-	if (do_mpx_bt_fault(xsave_buf)) {
+	if (do_mpx_bt_fault(tsk)) {
 		force_sig(SIGSEGV, current);
 		/*
 		 * The force_sig() is essentially "handling" this
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 05/19] x86, mpx: remove redundant MPX_BNDCFG_ADDR_MASK
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
                   ` (2 preceding siblings ...)
  2015-05-29 22:34 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
@ 2015-05-29 22:34 ` Dave Hansen
  2015-05-29 22:34 ` [PATCH 04/19] x86, mpx: Cleanup: Do not pass task around when unnecessary Dave Hansen
  2015-06-01 11:14 ` [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Ingo Molnar
  5 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, tglx, Dave Hansen, qiaowei.ren, dave.hansen


From: Qiaowei Ren <qiaowei.ren@intel.com>

MPX_BNDCFG_ADDR_MASK is defined two times, so this patch removes
redundant one.

Signed-off-by: Qiaowei Ren <qiaowei.ren@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
---

 b/arch/x86/include/asm/mpx.h |    1 -
 1 file changed, 1 deletion(-)

diff -puN arch/x86/include/asm/mpx.h~0001-x86-mpx-remove-redundant-MPX_BNDCFG_ADDR_MASK arch/x86/include/asm/mpx.h
--- a/arch/x86/include/asm/mpx.h~0001-x86-mpx-remove-redundant-MPX_BNDCFG_ADDR_MASK	2015-05-27 09:32:16.296524773 -0700
+++ b/arch/x86/include/asm/mpx.h	2015-05-27 09:32:16.299524908 -0700
@@ -45,7 +45,6 @@
 #define MPX_BNDSTA_TAIL		2
 #define MPX_BNDCFG_TAIL		12
 #define MPX_BNDSTA_ADDR_MASK	(~((1UL<<MPX_BNDSTA_TAIL)-1))
-#define MPX_BNDCFG_ADDR_MASK	(~((1UL<<MPX_BNDCFG_TAIL)-1))
 #define MPX_BT_ADDR_MASK	(~((1UL<<MPX_BD_ENTRY_TAIL)-1))
 
 #define MPX_BNDCFG_ADDR_MASK	(~((1UL<<MPX_BNDCFG_TAIL)-1))
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 04/19] x86, mpx: Cleanup: Do not pass task around when unnecessary
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
                   ` (3 preceding siblings ...)
  2015-05-29 22:34 ` [PATCH 05/19] x86, mpx: remove redundant MPX_BNDCFG_ADDR_MASK Dave Hansen
@ 2015-05-29 22:34 ` Dave Hansen
  2015-06-01 11:14 ` [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Ingo Molnar
  5 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 22:34 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code can only work on the current task.  You can not, for
instance, enable MPX management in another process or thread.
You can also not handle a fault for another process or thread.

Despite this, we pass a task_struct around prolifically.  This
patch removes all of the task struct passing for code paths where
the code can not deal with another task (which turns out to be
all of them).

This has no functional changes.  It's just a cleanup.

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: the arch/x86 maintainers <x86@kernel.org>
Cc: linux-kernel <linux-kernel@vger.kernel.org>
---

 b/arch/x86/include/asm/mpx.h       |   10 ++++------
 b/arch/x86/include/asm/processor.h |   12 ++++++------
 b/arch/x86/kernel/traps.c          |    5 ++---
 b/arch/x86/mm/mpx.c                |   19 +++++++++----------
 b/kernel/sys.c                     |    8 ++++----
 5 files changed, 25 insertions(+), 29 deletions(-)

diff -puN arch/x86/include/asm/mpx.h~x86-mpx-dont-pass-current-around arch/x86/include/asm/mpx.h
--- a/arch/x86/include/asm/mpx.h~x86-mpx-dont-pass-current-around	2015-05-27 09:32:15.793502086 -0700
+++ b/arch/x86/include/asm/mpx.h	2015-05-27 09:32:15.804502582 -0700
@@ -59,9 +59,8 @@
 		MPX_BT_ENTRY_MASK) << MPX_BT_ENTRY_SHIFT)
 
 #ifdef CONFIG_X86_INTEL_MPX
-siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-				struct task_struct *tsk);
-int mpx_handle_bd_fault(struct task_struct *tsk);
+siginfo_t *mpx_generate_siginfo(struct pt_regs *regs);
+int mpx_handle_bd_fault(void);
 static inline int kernel_managing_mpx_tables(struct mm_struct *mm)
 {
 	return (mm->bd_addr != MPX_INVALID_BOUNDS_DIR);
@@ -77,12 +76,11 @@ static inline void mpx_mm_init(struct mm
 void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma,
 		      unsigned long start, unsigned long end);
 #else
-static inline siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-					      struct task_struct *tsk)
+static inline siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
 {
 	return NULL;
 }
-static inline int mpx_handle_bd_fault(struct task_struct *tsk)
+static inline int mpx_handle_bd_fault(void)
 {
 	return -EINVAL;
 }
diff -puN arch/x86/include/asm/processor.h~x86-mpx-dont-pass-current-around arch/x86/include/asm/processor.h
--- a/arch/x86/include/asm/processor.h~x86-mpx-dont-pass-current-around	2015-05-27 09:32:15.795502176 -0700
+++ b/arch/x86/include/asm/processor.h	2015-05-27 09:32:15.804502582 -0700
@@ -802,18 +802,18 @@ extern int get_tsc_mode(unsigned long ad
 extern int set_tsc_mode(unsigned int val);
 
 /* Register/unregister a process' MPX related resource */
-#define MPX_ENABLE_MANAGEMENT(tsk)	mpx_enable_management((tsk))
-#define MPX_DISABLE_MANAGEMENT(tsk)	mpx_disable_management((tsk))
+#define MPX_ENABLE_MANAGEMENT()	mpx_enable_management()
+#define MPX_DISABLE_MANAGEMENT()	mpx_disable_management()
 
 #ifdef CONFIG_X86_INTEL_MPX
-extern int mpx_enable_management(struct task_struct *tsk);
-extern int mpx_disable_management(struct task_struct *tsk);
+extern int mpx_enable_management(void);
+extern int mpx_disable_management(void);
 #else
-static inline int mpx_enable_management(struct task_struct *tsk)
+static inline int mpx_enable_management(void)
 {
 	return -EINVAL;
 }
-static inline int mpx_disable_management(struct task_struct *tsk)
+static inline int mpx_disable_management(void)
 {
 	return -EINVAL;
 }
diff -puN arch/x86/kernel/traps.c~x86-mpx-dont-pass-current-around arch/x86/kernel/traps.c
--- a/arch/x86/kernel/traps.c~x86-mpx-dont-pass-current-around	2015-05-27 09:32:15.797502266 -0700
+++ b/arch/x86/kernel/traps.c	2015-05-27 09:32:15.805502627 -0700
@@ -371,7 +371,6 @@ dotraplinkage void do_double_fault(struc
 
 dotraplinkage void do_bounds(struct pt_regs *regs, long error_code)
 {
-	struct task_struct *tsk = current;
 	enum ctx_state prev_state;
 	struct bndcsr *bndcsr;
 	siginfo_t *info;
@@ -407,11 +406,11 @@ dotraplinkage void do_bounds(struct pt_r
 	 */
 	switch (bndcsr->bndstatus & MPX_BNDSTA_ERROR_CODE) {
 	case 2:	/* Bound directory has invalid entry. */
-		if (mpx_handle_bd_fault(tsk))
+		if (mpx_handle_bd_fault())
 			goto exit_trap;
 		break; /* Success, it was handled */
 	case 1: /* Bound violation. */
-		info = mpx_generate_siginfo(regs, tsk);
+		info = mpx_generate_siginfo(regs);
 		if (IS_ERR(info)) {
 			/*
 			 * We failed to decode the MPX instruction.  Act as if
diff -puN arch/x86/mm/mpx.c~x86-mpx-dont-pass-current-around arch/x86/mm/mpx.c
--- a/arch/x86/mm/mpx.c~x86-mpx-dont-pass-current-around	2015-05-27 09:32:15.799502356 -0700
+++ b/arch/x86/mm/mpx.c	2015-05-27 09:32:15.806502672 -0700
@@ -271,8 +271,7 @@ bad_opcode:
  *
  * The caller is expected to kfree() the returned siginfo_t.
  */
-siginfo_t *mpx_generate_siginfo(struct pt_regs *regs,
-				struct task_struct *tsk)
+siginfo_t *mpx_generate_siginfo(struct pt_regs *regs)
 {
 	struct bndreg *bndregs, *bndreg;
 	siginfo_t *info = NULL;
@@ -340,7 +339,7 @@ err_out:
 	return ERR_PTR(err);
 }
 
-static __user void *task_get_bounds_dir(struct task_struct *tsk)
+static __user void *mpx_get_bounds_dir(void)
 {
 	struct bndcsr *bndcsr;
 
@@ -376,10 +375,10 @@ static __user void *task_get_bounds_dir(
 		(bndcsr->bndcfgu & MPX_BNDCFG_ADDR_MASK);
 }
 
-int mpx_enable_management(struct task_struct *tsk)
+int mpx_enable_management(void)
 {
 	void __user *bd_base = MPX_INVALID_BOUNDS_DIR;
-	struct mm_struct *mm = tsk->mm;
+	struct mm_struct *mm = current->mm;
 	int ret = 0;
 
 	/*
@@ -393,7 +392,7 @@ int mpx_enable_management(struct task_st
 	 * directory here means that we do not have to do xsave in the
 	 * unmap path; we can just use mm->bd_addr instead.
 	 */
-	bd_base = task_get_bounds_dir(tsk);
+	bd_base = mpx_get_bounds_dir();
 	down_write(&mm->mmap_sem);
 	mm->bd_addr = bd_base;
 	if (mm->bd_addr == MPX_INVALID_BOUNDS_DIR)
@@ -403,7 +402,7 @@ int mpx_enable_management(struct task_st
 	return ret;
 }
 
-int mpx_disable_management(struct task_struct *tsk)
+int mpx_disable_management(void)
 {
 	struct mm_struct *mm = current->mm;
 
@@ -497,7 +496,7 @@ out_unmap:
  * bound table is 16KB. With 64-bit mode, the size of BD is 2GB,
  * and the size of each bound table is 4MB.
  */
-static int do_mpx_bt_fault(struct task_struct *tsk)
+static int do_mpx_bt_fault(void)
 {
 	unsigned long bd_entry, bd_base;
 	struct bndcsr *bndcsr;
@@ -525,7 +524,7 @@ static int do_mpx_bt_fault(struct task_s
 	return allocate_bt((long __user *)bd_entry);
 }
 
-int mpx_handle_bd_fault(struct task_struct *tsk)
+int mpx_handle_bd_fault(void)
 {
 	/*
 	 * Userspace never asked us to manage the bounds tables,
@@ -534,7 +533,7 @@ int mpx_handle_bd_fault(struct task_stru
 	if (!kernel_managing_mpx_tables(current->mm))
 		return -EINVAL;
 
-	if (do_mpx_bt_fault(tsk)) {
+	if (do_mpx_bt_fault()) {
 		force_sig(SIGSEGV, current);
 		/*
 		 * The force_sig() is essentially "handling" this
diff -puN kernel/sys.c~x86-mpx-dont-pass-current-around kernel/sys.c
--- a/kernel/sys.c~x86-mpx-dont-pass-current-around	2015-05-27 09:32:15.800502402 -0700
+++ b/kernel/sys.c	2015-05-27 09:32:15.806502672 -0700
@@ -92,10 +92,10 @@
 # define SET_TSC_CTL(a)		(-EINVAL)
 #endif
 #ifndef MPX_ENABLE_MANAGEMENT
-# define MPX_ENABLE_MANAGEMENT(a)	(-EINVAL)
+# define MPX_ENABLE_MANAGEMENT()	(-EINVAL)
 #endif
 #ifndef MPX_DISABLE_MANAGEMENT
-# define MPX_DISABLE_MANAGEMENT(a)	(-EINVAL)
+# define MPX_DISABLE_MANAGEMENT()	(-EINVAL)
 #endif
 #ifndef GET_FP_MODE
 # define GET_FP_MODE(a)		(-EINVAL)
@@ -2230,12 +2230,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
 	case PR_MPX_ENABLE_MANAGEMENT:
 		if (arg2 || arg3 || arg4 || arg5)
 			return -EINVAL;
-		error = MPX_ENABLE_MANAGEMENT(me);
+		error = MPX_ENABLE_MANAGEMENT();
 		break;
 	case PR_MPX_DISABLE_MANAGEMENT:
 		if (arg2 || arg3 || arg4 || arg5)
 			return -EINVAL;
-		error = MPX_DISABLE_MANAGEMENT(me);
+		error = MPX_DISABLE_MANAGEMENT();
 		break;
 	case PR_SET_FP_MODE:
 		error = SET_FP_MODE(me, arg2);
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 00/19] x86, mpx updates for 4.2 (take 8)
  2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
                   ` (4 preceding siblings ...)
  2015-05-29 22:34 ` [PATCH 04/19] x86, mpx: Cleanup: Do not pass task around when unnecessary Dave Hansen
@ 2015-06-01 11:14 ` Ingo Molnar
  2015-06-01 15:09   ` Dave Hansen
  5 siblings, 1 reply; 30+ messages in thread
From: Ingo Molnar @ 2015-06-01 11:14 UTC (permalink / raw)
  To: Dave Hansen; +Cc: linux-kernel, x86, tglx


* Dave Hansen <dave@sr71.net> wrote:

> 
> Changes from take 7 / v22:
>  * Add Thomas's reviewed-by
>  * merge with tip/x86/fpu changes
>  * Fix tiny spelling nit

So you already sent 'take 8', so it's unclear to me what changed in this series.

Also, only 1,3,4,5 made it to lkml it appears. (it's not in my spam box either.)

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 00/19] x86, mpx updates for 4.2 (take 8)
  2015-06-01 11:14 ` [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Ingo Molnar
@ 2015-06-01 15:09   ` Dave Hansen
  0 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-06-01 15:09 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: linux-kernel, x86, tglx

On 06/01/2015 04:14 AM, Ingo Molnar wrote:
> So you already sent 'take 8', so it's unclear to me what changed in this series.
> 
> Also, only 1,3,4,5 made it to lkml it appears. (it's not in my spam box either.)

I accidentally send that.  I'll send a real series with a proper
changelog shortly.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-06-07 18:37 [PATCH 00/19] x86, mpx updates for 4.2 (take 9) Dave Hansen
@ 2015-06-07 18:37 ` Dave Hansen
  0 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-06-07 18:37 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code appears is calling a low-level FPU function
(copy_fpregs_to_fpstate()).  This function is not able to
be called in all contexts, although it is safe to call
directly in some cases.

Although probably correct, the current code is ugly and
potentially error-prone.  So, add a wrapper that calls
the (slightly) higher-level fpu__save() (which is preempt-
safe) and also ensures that we even *have* an FPU context
(in the case that this was called when in lazy FPU mode).

Ingo had this to say about the details about when we need
preemption disabled:

> it's indeed generally unsafe to access/copy FPU registers with preemption enabled,
> for two reasons:
>
>   - on older systems that use FSAVE the instruction destroys FPU register
>     contents, which has to be handled carefully
>
>   - even on newer systems if we copy to FPU registers (which this code doesn't)
>     then we don't want a context switch to occur in the middle of it, because a
>     context switch will write to the fpstate, potentially overwriting our new data
>     with old FPU state.
>
> But it's safe to access FPU registers with preemption enabled in a couple of
> special cases:
>
>   - potentially destructively saving FPU registers: the signal handling code does
>     this in copy_fpstate_to_sigframe(), because it can rely on the signal restore
>     side to restore the original FPU state.
>
>   - reading FPU registers on modern systems: we don't do this anywhere at the
>     moment, mostly to keep symmetry with older systems where FSAVE is
>     destructive.
>
>   - initializing FPU registers on modern systems: fpu__clear() does this. Here
>     it's safe because we don't copy from the fpstate.
>
>   - directly writing FPU registers from user-space memory (!). We do this in
>     fpu__restore_sig(), and it's safe because neither context switches nor
>     irq-handler FPU use can corrupt the source context of the copy (which is
>     user-space memory).
>
> Note that the MPX code's current use of copy_fpregs_to_fpstate() was safe I think,
> because:
>
>  - MPX is predicated on eagerfpu, so the destructive F[N]SAVE instruction won't be
>    used.
>
>  - the code was only reading FPU registers, and was doing it only in places that
>    guaranteed that an FPU state was already active (i.e. didn't do it in
>    kthreads)

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>

---

Changes from take 8 / v23:
 * Add const specifier for get_xsave_field_ptr() return type
 * Add temporary 'fpu' variable to shorten up the code and
   make it look more consistent with the other FPU code.

Changes from v21:
 * add comments about preemption
 * rename helper to get_xsave_field_ptr()

Changes from "v19":
 * remove 'tsk' argument to get_xsave_addr() since the code
   can only realistically work on 'current', and fix up the
   comment a bit to match.

Changes from "v17":
 * fix s/xstate/xsave_field/ in the function comment
 * remove EXPORT_SYMBOL_GPL()

---

 b/arch/x86/include/asm/fpu/xstate.h |    1 +
 b/arch/x86/kernel/fpu/xstate.c      |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff -puN arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr arch/x86/include/asm/fpu/xstate.h
--- a/arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr	2015-06-01 10:24:03.427694831 -0700
+++ b/arch/x86/include/asm/fpu/xstate.h	2015-06-01 10:24:03.432695056 -0700
@@ -41,5 +41,6 @@ extern u64 xstate_fx_sw_bytes[USER_XSTAT
 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
 
 void *get_xsave_addr(struct xregs_state *xsave, int xstate);
+const void *get_xsave_field_ptr(int xstate_field);
 
 #endif
diff -puN arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr	2015-06-01 10:24:03.429694921 -0700
+++ b/arch/x86/kernel/fpu/xstate.c	2015-06-01 10:24:03.433695102 -0700
@@ -427,3 +427,35 @@ void *get_xsave_addr(struct xregs_state
 	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
+
+/*
+ * This wraps up the common operations that need to occur when retrieving
+ * data from xsave state.  It first ensures that the current task was
+ * using the FPU and retrieves the data in to a buffer.  It then calculates
+ * the offset of the requested field in the buffer.
+ *
+ * This function is safe to call whether the FPU is in use or not.
+ *
+ * Note that this only works on the current task.
+ *
+ * Inputs:
+ *	@xsave_state: state which is defined in xsave.h (e.g. XSTATE_FP,
+ *	XSTATE_SSE, etc...)
+ * Output:
+ *	address of the state in the xsave area or NULL if the state
+ *	is not present or is in its 'init state'.
+ */
+const void *get_xsave_field_ptr(int xsave_state)
+{
+	struct fpu *fpu = &current->thread.fpu;
+
+	if (!fpu->fpstate_active)
+		return NULL;
+	/*
+	 * fpu__save() takes the CPU's xstate registers
+	 * and saves them off to the 'fpu memory buffer.
+	 */
+	fpu__save(fpu);
+
+	return get_xsave_addr(&fpu->state.xsave, xsave_state);
+}
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29 16:10             ` Borislav Petkov
@ 2015-05-29 18:51               ` Ingo Molnar
  0 siblings, 0 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-29 18:51 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Andy Lutomirski, Dave Hansen, linux-kernel, X86 ML,
	Thomas Gleixner, Dave Hansen, Oleg Nesterov, Rik van Riel,
	Suresh Siddha, Ingo Molnar, H. Peter Anvin, Fenghua Yu,
	Linus Torvalds, Peter Zijlstra


* Borislav Petkov <bp@alien8.de> wrote:

> On Thu, May 28, 2015 at 06:05:33PM -0700, Andy Lutomirski wrote:
> > I would propose that we take the opposite approach and just ban
> > eagerfpu=off when MPX is enabled.  We could then take the next step
> > and default eagerfpu=on for everyone and, if nothing breaks, then just
> > delete lazy mode entirely.
> > 
> > I suspect we'd have to go back to Pentium 3 or earlier to find a CPU
> > on which lazy mode is actually a good idea.
> 
> Last time I checked (and ran some benchmarks) it was only a minute
> slowdown so I say we kill lazy mode if it means significant code
> complexity drop.
> 
> Can I also emulate Greg here and suggest that Pentium 3 people should
> buy newer hw? They should think about the environment, if nothing else.
> 
> :-P

I went back as far as Athon64 and the CR0 manipulation and CR0 faults are overly 
expensive there too.

Ok, you guys convinced me, I'll do a patch for this in tip:x86/fpu, and then 
people can benchmark it.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28 16:02         ` Dave Hansen
@ 2015-05-29 18:49           ` Ingo Molnar
  0 siblings, 0 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-29 18:49 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu, Linus Torvalds, Peter Zijlstra


* Dave Hansen <dave@sr71.net> wrote:

> On 05/28/2015 08:01 AM, Ingo Molnar wrote:
> > fpu__activate_fpstate_read() will only activate the fpstate for reads (as the name 
> > suggests it).
> 
> I've got no problem doing it this way.  But are you planning to push this 
> function in to 4.2?  Is there a tree you want me to merge this on top of?

Yes and yes, please use tip:x86/fpu (or tip:master) for all FPU related work.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29 16:47     ` Dave Hansen
@ 2015-05-29 18:48       ` Ingo Molnar
  0 siblings, 0 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-29 18:48 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


* Dave Hansen <dave@sr71.net> wrote:

> On 05/28/2015 01:41 AM, Ingo Molnar wrote:
> >> > +	union fpregs_state *xstate;
> >> > +
> >> > +	if (!current->thread.fpu.fpstate_active)
> >> > +		return NULL;
> >> > +	/*
> >> > +	 * fpu__save() takes the CPU's xstate registers
> >> > +	 * and saves them off to the 'fpu memory buffer.
> >> > +	 */
> >> > +	fpu__save(&current->thread.fpu);
> >> > +	xstate = &current->thread.fpu.state;
> >> > +
> >> > +	return get_xsave_addr(&xstate->xsave, xsave_state);
> > Small nit, this would become a lot shorter if you introduced a helper local 
> > variable:
> > 
> > 	struct fpu *fpu = &current->thread.fpu;
> > 
> > But more importantly, for a generic get_xsave_field_ptr() API, fpu__save() is 
> > not enough: fpu__save() will only save FPU registers into memory if necessary 
> > (i.e. if the FPU is already in use), and if you call it on a task with no FPU 
> > state then it will still have an !fpu->fpstate_active FPU state after the 
> > call, with random, invalid data in the xsave area.
> 
> But why does this matter?  We just did a !fpu.fpstate_active check, so we can't 
> have a !fpu.fpstate_active before or after the call.

Ah yes, you are right, I missed this:

> >> > +	if (!current->thread.fpu.fpstate_active)
> >> > +		return NULL;

because the usual pattern is:

		if (!fpu->fpstate_active)
			return NULL;

:-)

So your variant is fine too.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29 18:29               ` Andy Lutomirski
@ 2015-05-29 18:44                 ` Ingo Molnar
  0 siblings, 0 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-29 18:44 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, linux-kernel, X86 ML, Thomas Gleixner, Dave Hansen,
	Oleg Nesterov, Borislav Petkov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra


* Andy Lutomirski <luto@amacapital.net> wrote:

> > It's not that simple, because the decision is not 'lazy versus eager', but 
> > 'mixed lazy/eager versus eager-only':
> >
> > Even on modern machines, if a task is not using the FPU (it's doing integer 
> > only work, with short sleeps just shuffling around requests, etc.) then 
> > context switches get up to 5-10% faster with lazy FPU restores.
> 
> That's only sort of true.  I'd believe that a context switch between two lazy 
> tasks is 5-10% faster than a context switch between two eager tasks.  I bet that 
> a context switch between a lazy task and an eager task is a whole lot slower 
> than a context switch between two eager tasks because manipulating CR0.TS is 
> incredibly slow on all modern CPUs AFAICT.  It's even worse in a VM guest.
> 
> In other words, with lazy restore, we save the XRSTOR(S) and possibly a 
> subsequent XSAVEOPT/XSAVES, but the cost is a MOV to CR0 and possibly a CLTS, 
> and the MOV to CR0 is much, much slower than even a worst-case XRSTOR(S).  In 
> the worst lazy-restore case, we also pay a full exception roundtrip, and 
> everything pales in comparison.  If we're a guest, then there's probably a 
> handful of exits thrown in for good measure.
> 
> For true integer-only tasks, I think we should instead convince glibc to add 
> things like vzeroall in convenient places to force as much xstate as possible to 
> the init state, thus speeding up the optimized save/restore variants.
> 
> I think the fundamental issue here is that CPU designers care about xstate 
> save/restore/optimize performance, but they don't care at all about TS 
> performance, so TS manipulations are probably microcoded and serializing.

That's definitely true.

Btw., potentially being able to get rid of lazy restores was why I wrote the 
FPU-benchmarking code, and it gives these results on reasonably recent Intel CPUs:

CR0 reads are reasonably fast:

 [    0.519287] x86/fpu: Cost of: CR0                         read          :     4 cycles

but we can cache that so it doesn't help us.

writes are bad:

 [    0.528643] x86/fpu: Cost of: CR0                         write         :   208 cycles

and we cannot cache it, so that hurts us.

and a CR0::TS fault cost is horrible:

 [    0.538042] x86/fpu: Cost of: CR0::TS                     fault         :  1156 cycles

and this is hurting us too.

Since the first version I have extended the benchmark with a cache-cold column as 
well - in the cache cold case the difference is even more striking, and in may 
cases context switches are cache cold.

Interestingly, this kind of high cost of CR0 related accesses is true even on 
pretty old, 10+ years old x86 CPUs, per my measurements, so it's not limited to 
modern x86 microarchitectures.

So yes, it would be nice to standardize on synchronous context switching of all 
CPU state.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29 18:17             ` Ingo Molnar
@ 2015-05-29 18:29               ` Andy Lutomirski
  2015-05-29 18:44                 ` Ingo Molnar
  0 siblings, 1 reply; 30+ messages in thread
From: Andy Lutomirski @ 2015-05-29 18:29 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Dave Hansen, linux-kernel, X86 ML, Thomas Gleixner, Dave Hansen,
	Oleg Nesterov, Borislav Petkov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra

On Fri, May 29, 2015 at 11:17 AM, Ingo Molnar <mingo@kernel.org> wrote:
>
> * Andy Lutomirski <luto@amacapital.net> wrote:
>
>> On Thu, May 28, 2015 at 9:24 AM, Dave Hansen <dave@sr71.net> wrote:
>> > On 05/28/2015 08:01 AM, Ingo Molnar wrote:
>> >> But the real question is: can we support in-use MPX with asynchronous lazy
>> >> restore, while it's still semantically correct? I don't think so, unless you add
>> >> MPX specific synchronous restore to the context switch path, which isn't such a
>> >> good idea IMHO.
>> >
>> > Right now, we assume that the first use of the FPU gets an #ND exception to
>> > tell us that someone is using the FPU.  MPX doesn't generate #ND, thus the
>> > need to do it eagerly.
>
> Basically MPX is not really a vector operation, it just uses the xstate (as in
> 'extended CPU state') context area to do easy saves/restores on context switches.
> MPX is an MMU-ish feature.
>
> That's an entirely sensible design approach, which reduces the support code needed
> for MPX, and it's not surprising that MPX accesses were not made conditional on
> CR0::TS.
>
>> > On CPUs that support it we could, instead, do an xgetbv during the context
>> > switch to ensure that all things having an xstate/xfeature but that do not
>> > generate #ND exceptions are in their init state.  If they are not in their
>> > init state, we exit lazy mode.
>
> Yeah, no, we don't need to do anything complex here.
>
> This property is something we know when MPX gets enabled, so for MPX tasks we
> should either simply set _TIF_WORK_CTXSW and let __switch_to_xtra() handle it, or
> should slightly modify the eagerfpu choice code to always do eager restores when
> switching to an MPX task.
>

Do we actually know which tasks use MPX, or do we merely know which
tasks use kernel-assisted MPX?

> Nothing complex is needed to support the mixed lazy/eager model, the current FPU
> code handles it just fine, because it's already a mixed lazy/eager model :-)
>
>> > We could theoretically use the same kind of thing with the compacted xsave
>> > format to ensure that we only allocate enough space for what we *need* in the
>> > xsave buffer and not allocate for the worst-case.  AVX512 has 32x512-bit
>> > registers (2kbytes) and it would be a bit of a shame to need to allocate ~3k
>> > of space.
>>
>> I understand the point of this type of optimization (except that I really don't
>> like the idea of sending SIGBUS or whatever if we fail an allocation at context
>> switch time), but why are we even considering trying to support MPX and lazy fpu
>> at the same time?  Judging from all the bug reports, it seems like it's a giant
>> mess, and the code to support lazy restore is not exactly pretty.
>>
>> I would propose that we take the opposite approach and just ban eagerfpu=off
>> when MPX is enabled.  We could then take the next step and default eagerfpu=on
>> for everyone and, if nothing breaks, then just delete lazy mode entirely.
>>
>> I suspect we'd have to go back to Pentium 3 or earlier to find a CPU on which
>> lazy mode is actually a good idea.  Fiddling with CR0 and handling exceptions is
>> really slow, and I think we should trust CPUs with XSAVEOPT support to do their
>> job and let the older CPUs take the small performance hit, if it even is a
>> performance hit.
>
> It's not that simple, because the decision is not 'lazy versus eager', but 'mixed
> lazy/eager versus eager-only':
>
> Even on modern machines, if a task is not using the FPU (it's doing integer only
> work, with short sleeps just shuffling around requests, etc.) then context
> switches get up to 5-10% faster with lazy FPU restores.

That's only sort of true.  I'd believe that a context switch between
two lazy tasks is 5-10% faster than a context switch between two eager
tasks.  I bet that a context switch between a lazy task and an eager
task is a whole lot slower than a context switch between two eager
tasks because manipulating CR0.TS is incredibly slow on all modern
CPUs AFAICT.  It's even worse in a VM guest.

In other words, with lazy restore, we save the XRSTOR(S) and possibly
a subsequent XSAVEOPT/XSAVES, but the cost is a MOV to CR0 and
possibly a CLTS, and the MOV to CR0 is much, much slower than even a
worst-case XRSTOR(S).  In the worst lazy-restore case, we also pay a
full exception roundtrip, and everything pales in comparison.  If
we're a guest, then there's probably a handful of exits thrown in for
good measure.

For true integer-only tasks, I think we should instead convince glibc
to add things like vzeroall in convenient places to force as much
xstate as possible to the init state, thus speeding up the optimized
save/restore variants.

I think the fundamental issue here is that CPU designers care about
xstate save/restore/optimize performance, but they don't care at all
about TS performance, so TS manipulations are probably microcoded and
serializing.

>
> So we have this dynamic measurement code in place in the lazy case that
> opportunistically enables eagerfpu handling on a per task basis, and that method
> works pretty efficiently and has a good hit rate in isolating FPU-users from
> integer-users.
>
> So it's not 'lazy restores versus eager restores', but:
>
>   - optimized, mixed lazy and eager use
>   vs.
>   - eager-only use
>
> Which is a lot less clear-cut choice.
>
> It's true that right now we forcibly use eagerfpu on all modern CPUs (XSAVE
> supporting ones - in essence modern Intel CPUs) which hides all this - but if you
> re-enable it it's measurable even on Intel systems. On AMD systems it's the
> current state of affairs right now.
>
> Also, I'd like to point out that the FPU code is a lot less of a mess in the
> latest x86/fpu tree! ;-)

That part's certainly true.

>
> I'd not give up on lazy restores just yet - or at least not without much better
> measurements backing it all up...

Fair enough.  I suspect that the only workloads on which it will win
are old 32-bit distros, though -- even integer-only 64-bit workloads
are likely to use SSE2 for things like memcpy.

--Andy

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29  1:05           ` Andy Lutomirski
  2015-05-29 15:31             ` Dave Hansen
  2015-05-29 16:10             ` Borislav Petkov
@ 2015-05-29 18:17             ` Ingo Molnar
  2015-05-29 18:29               ` Andy Lutomirski
  2 siblings, 1 reply; 30+ messages in thread
From: Ingo Molnar @ 2015-05-29 18:17 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, linux-kernel, X86 ML, Thomas Gleixner, Dave Hansen,
	Oleg Nesterov, Borislav Petkov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra


* Andy Lutomirski <luto@amacapital.net> wrote:

> On Thu, May 28, 2015 at 9:24 AM, Dave Hansen <dave@sr71.net> wrote:
> > On 05/28/2015 08:01 AM, Ingo Molnar wrote:
> >> But the real question is: can we support in-use MPX with asynchronous lazy
> >> restore, while it's still semantically correct? I don't think so, unless you add
> >> MPX specific synchronous restore to the context switch path, which isn't such a
> >> good idea IMHO.
> >
> > Right now, we assume that the first use of the FPU gets an #ND exception to 
> > tell us that someone is using the FPU.  MPX doesn't generate #ND, thus the 
> > need to do it eagerly.

Basically MPX is not really a vector operation, it just uses the xstate (as in 
'extended CPU state') context area to do easy saves/restores on context switches. 
MPX is an MMU-ish feature.

That's an entirely sensible design approach, which reduces the support code needed 
for MPX, and it's not surprising that MPX accesses were not made conditional on 
CR0::TS.

> > On CPUs that support it we could, instead, do an xgetbv during the context 
> > switch to ensure that all things having an xstate/xfeature but that do not 
> > generate #ND exceptions are in their init state.  If they are not in their 
> > init state, we exit lazy mode.

Yeah, no, we don't need to do anything complex here.

This property is something we know when MPX gets enabled, so for MPX tasks we 
should either simply set _TIF_WORK_CTXSW and let __switch_to_xtra() handle it, or 
should slightly modify the eagerfpu choice code to always do eager restores when 
switching to an MPX task.

Nothing complex is needed to support the mixed lazy/eager model, the current FPU 
code handles it just fine, because it's already a mixed lazy/eager model :-)

> > We could theoretically use the same kind of thing with the compacted xsave 
> > format to ensure that we only allocate enough space for what we *need* in the 
> > xsave buffer and not allocate for the worst-case.  AVX512 has 32x512-bit 
> > registers (2kbytes) and it would be a bit of a shame to need to allocate ~3k 
> > of space.
> 
> I understand the point of this type of optimization (except that I really don't 
> like the idea of sending SIGBUS or whatever if we fail an allocation at context 
> switch time), but why are we even considering trying to support MPX and lazy fpu 
> at the same time?  Judging from all the bug reports, it seems like it's a giant 
> mess, and the code to support lazy restore is not exactly pretty.
> 
> I would propose that we take the opposite approach and just ban eagerfpu=off 
> when MPX is enabled.  We could then take the next step and default eagerfpu=on 
> for everyone and, if nothing breaks, then just delete lazy mode entirely.
> 
> I suspect we'd have to go back to Pentium 3 or earlier to find a CPU on which 
> lazy mode is actually a good idea.  Fiddling with CR0 and handling exceptions is 
> really slow, and I think we should trust CPUs with XSAVEOPT support to do their 
> job and let the older CPUs take the small performance hit, if it even is a 
> performance hit.

It's not that simple, because the decision is not 'lazy versus eager', but 'mixed 
lazy/eager versus eager-only':

Even on modern machines, if a task is not using the FPU (it's doing integer only 
work, with short sleeps just shuffling around requests, etc.) then context 
switches get up to 5-10% faster with lazy FPU restores.

So we have this dynamic measurement code in place in the lazy case that 
opportunistically enables eagerfpu handling on a per task basis, and that method 
works pretty efficiently and has a good hit rate in isolating FPU-users from 
integer-users.

So it's not 'lazy restores versus eager restores', but:

  - optimized, mixed lazy and eager use
  vs.
  - eager-only use

Which is a lot less clear-cut choice.

It's true that right now we forcibly use eagerfpu on all modern CPUs (XSAVE 
supporting ones - in essence modern Intel CPUs) which hides all this - but if you 
re-enable it it's measurable even on Intel systems. On AMD systems it's the 
current state of affairs right now.

Also, I'd like to point out that the FPU code is a lot less of a mess in the 
latest x86/fpu tree! ;-)

I'd not give up on lazy restores just yet - or at least not without much better 
measurements backing it all up...

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28  8:41   ` Ingo Molnar
  2015-05-28 14:45     ` Dave Hansen
@ 2015-05-29 16:47     ` Dave Hansen
  2015-05-29 18:48       ` Ingo Molnar
  1 sibling, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 16:47 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu

On 05/28/2015 01:41 AM, Ingo Molnar wrote:
>> > +	union fpregs_state *xstate;
>> > +
>> > +	if (!current->thread.fpu.fpstate_active)
>> > +		return NULL;
>> > +	/*
>> > +	 * fpu__save() takes the CPU's xstate registers
>> > +	 * and saves them off to the 'fpu memory buffer.
>> > +	 */
>> > +	fpu__save(&current->thread.fpu);
>> > +	xstate = &current->thread.fpu.state;
>> > +
>> > +	return get_xsave_addr(&xstate->xsave, xsave_state);
> Small nit, this would become a lot shorter if you introduced a helper local 
> variable:
> 
> 	struct fpu *fpu = &current->thread.fpu;
> 
> But more importantly, for a generic get_xsave_field_ptr() API, fpu__save() is not 
> enough: fpu__save() will only save FPU registers into memory if necessary (i.e. if 
> the FPU is already in use), and if you call it on a task with no FPU state then it 
> will still have an !fpu->fpstate_active FPU state after the call, with random, 
> invalid data in the xsave area.

But why does this matter?  We just did a !fpu.fpstate_active check, so
we can't have a !fpu.fpstate_active before or after the call.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29  1:05           ` Andy Lutomirski
  2015-05-29 15:31             ` Dave Hansen
@ 2015-05-29 16:10             ` Borislav Petkov
  2015-05-29 18:51               ` Ingo Molnar
  2015-05-29 18:17             ` Ingo Molnar
  2 siblings, 1 reply; 30+ messages in thread
From: Borislav Petkov @ 2015-05-29 16:10 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Dave Hansen, Ingo Molnar, linux-kernel, X86 ML, Thomas Gleixner,
	Dave Hansen, Oleg Nesterov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra

On Thu, May 28, 2015 at 06:05:33PM -0700, Andy Lutomirski wrote:
> I would propose that we take the opposite approach and just ban
> eagerfpu=off when MPX is enabled.  We could then take the next step
> and default eagerfpu=on for everyone and, if nothing breaks, then just
> delete lazy mode entirely.
> 
> I suspect we'd have to go back to Pentium 3 or earlier to find a CPU
> on which lazy mode is actually a good idea.

Last time I checked (and ran some benchmarks) it was only a minute
slowdown so I say we kill lazy mode if it means significant code
complexity drop.

Can I also emulate Greg here and suggest that Pentium 3 people should
buy newer hw? They should think about the environment, if nothing else.

:-P

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-29  1:05           ` Andy Lutomirski
@ 2015-05-29 15:31             ` Dave Hansen
  2015-05-29 16:10             ` Borislav Petkov
  2015-05-29 18:17             ` Ingo Molnar
  2 siblings, 0 replies; 30+ messages in thread
From: Dave Hansen @ 2015-05-29 15:31 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Ingo Molnar, linux-kernel, X86 ML, Thomas Gleixner, Dave Hansen,
	Oleg Nesterov, Borislav Petkov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra

On 05/28/2015 06:05 PM, Andy Lutomirski wrote:
> I would propose that we take the opposite approach and just ban
> eagerfpu=off when MPX is enabled.  We could then take the next step
> and default eagerfpu=on for everyone and, if nothing breaks, then just
> delete lazy mode entirely.

No objections from me on this.

It's definitely the simplest thing to do, and it's one less potential
delta that enabling MPX could impose on someone, so it makes me happy on
that front.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28 16:24         ` Dave Hansen
@ 2015-05-29  1:05           ` Andy Lutomirski
  2015-05-29 15:31             ` Dave Hansen
                               ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Andy Lutomirski @ 2015-05-29  1:05 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Ingo Molnar, linux-kernel, X86 ML, Thomas Gleixner, Dave Hansen,
	Oleg Nesterov, Borislav Petkov, Rik van Riel, Suresh Siddha,
	Ingo Molnar, H. Peter Anvin, Fenghua Yu, Linus Torvalds,
	Peter Zijlstra

On Thu, May 28, 2015 at 9:24 AM, Dave Hansen <dave@sr71.net> wrote:
> On 05/28/2015 08:01 AM, Ingo Molnar wrote:
>> But the real question is: can we support in-use MPX with asynchronous lazy
>> restore, while it's still semantically correct? I don't think so, unless you add
>> MPX specific synchronous restore to the context switch path, which isn't such a
>> good idea IMHO.
>
> Right now, we assume that the first use of the FPU gets an #ND exception
> to tell us that someone is using the FPU.  MPX doesn't generate #ND,
> thus the need to do it eagerly.
>
> On CPUs that support it we could, instead, do an xgetbv during the
> context switch to ensure that all things having an xstate/xfeature but
> that do not generate #ND exceptions are in their init state.  If they
> are not in their init state, we exit lazy mode.
>
> We could theoretically use the same kind of thing with the compacted
> xsave format to ensure that we only allocate enough space for what we
> *need* in the xsave buffer and not allocate for the worst-case.  AVX512
> has 32x512-bit registers (2kbytes) and it would be a bit of a shame to
> need to allocate ~3k of space.

I understand the point of this type of optimization (except that I
really don't like the idea of sending SIGBUS or whatever if we fail an
allocation at context switch time), but why are we even considering
trying to support MPX and lazy fpu at the same time?  Judging from all
the bug reports, it seems like it's a giant mess, and the code to
support lazy restore is not exactly pretty.

I would propose that we take the opposite approach and just ban
eagerfpu=off when MPX is enabled.  We could then take the next step
and default eagerfpu=on for everyone and, if nothing breaks, then just
delete lazy mode entirely.

I suspect we'd have to go back to Pentium 3 or earlier to find a CPU
on which lazy mode is actually a good idea.  Fiddling with CR0 and
handling exceptions is really slow, and I think we should trust CPUs
with XSAVEOPT support to do their job and let the older CPUs take the
small performance hit, if it even is a performance hit.

--Andy

-- 
Andy Lutomirski
AMA Capital Management, LLC

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28 15:01       ` Ingo Molnar
  2015-05-28 16:02         ` Dave Hansen
@ 2015-05-28 16:24         ` Dave Hansen
  2015-05-29  1:05           ` Andy Lutomirski
  1 sibling, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-28 16:24 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu, Linus Torvalds, Peter Zijlstra

On 05/28/2015 08:01 AM, Ingo Molnar wrote:
> But the real question is: can we support in-use MPX with asynchronous lazy 
> restore, while it's still semantically correct? I don't think so, unless you add 
> MPX specific synchronous restore to the context switch path, which isn't such a 
> good idea IMHO.

Right now, we assume that the first use of the FPU gets an #ND exception
to tell us that someone is using the FPU.  MPX doesn't generate #ND,
thus the need to do it eagerly.

On CPUs that support it we could, instead, do an xgetbv during the
context switch to ensure that all things having an xstate/xfeature but
that do not generate #ND exceptions are in their init state.  If they
are not in their init state, we exit lazy mode.

We could theoretically use the same kind of thing with the compacted
xsave format to ensure that we only allocate enough space for what we
*need* in the xsave buffer and not allocate for the worst-case.  AVX512
has 32x512-bit registers (2kbytes) and it would be a bit of a shame to
need to allocate ~3k of space.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28 15:01       ` Ingo Molnar
@ 2015-05-28 16:02         ` Dave Hansen
  2015-05-29 18:49           ` Ingo Molnar
  2015-05-28 16:24         ` Dave Hansen
  1 sibling, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-28 16:02 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu, Linus Torvalds, Peter Zijlstra

On 05/28/2015 08:01 AM, Ingo Molnar wrote:
> fpu__activate_fpstate_read() will only activate the fpstate for reads (as the name 
> suggests it).

I've got no problem doing it this way.  But are you planning to push
this function in to 4.2?  Is there a tree you want me to merge this on
top of?

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28 14:45     ` Dave Hansen
@ 2015-05-28 15:01       ` Ingo Molnar
  2015-05-28 16:02         ` Dave Hansen
  2015-05-28 16:24         ` Dave Hansen
  0 siblings, 2 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-28 15:01 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu, Linus Torvalds, Peter Zijlstra


* Dave Hansen <dave@sr71.net> wrote:

> On 05/28/2015 01:41 AM, Ingo Molnar wrote:
>
> > What you want here is to make the (in-memory) FPU state valid and current, 
> > before reading it, and the function to use for that is 
> > fpu__activate_fpstate_read() (available in the latest tip:x86/fpu tree).
> 
> Do we really want to unconditionally activate the FPU?
>
> Let's say supporting MPX didn't require eager mode and someone called 
> get_xsave_addr().  We would ideally want to keep the FPU inactive and just 
> return NULL.  Right?

So there's two distinct types of 'active' here:

  - active fpstate (in-kernel memory context buffer)
  - active fpregs  (in-FPU hardware registers)

fpu__activate_fpstate_read() will only activate the fpstate for reads (as the name 
suggests it).

In your hypothetical case, if it's called with lazy FPU state then the fpstate is 
active already, and the fpstate represents the 'real' FPU state of the current 
task - while the FPU's contents are still some previous task's FPU state. So we 
can return the contents of this task's fpstate just fine even if the registers 
themselves are not (yet) loaded with them.

But the real question is: can we support in-use MPX with asynchronous lazy 
restore, while it's still semantically correct? I don't think so, unless you add 
MPX specific synchronous restore to the context switch path, which isn't such a 
good idea IMHO.

Furthermore, I don't think we want to extend lazy FPU use, in fact I'm considering 
getting rid of it altogether, even on old CPUs: the CR0 fault costs are horrible 
all across the CPU spectrum (even for legacy CPUs), and modern user-space makes 
use of the FPU all the time.

Yes, on older CPUs, if user-space does not use the FPU but context switches 
frequently, then the cost of always doing FPU save/restore is measurable, but the 
worst-case I've measured was something like a 10% increase in context switching 
cost.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-28  8:41   ` Ingo Molnar
@ 2015-05-28 14:45     ` Dave Hansen
  2015-05-28 15:01       ` Ingo Molnar
  2015-05-29 16:47     ` Dave Hansen
  1 sibling, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-28 14:45 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu

On 05/28/2015 01:41 AM, Ingo Molnar wrote:
> What you want here is to make the (in-memory) FPU state valid and current, before 
> reading it, and the function to use for that is fpu__activate_fpstate_read() 
> (available in the latest tip:x86/fpu tree).

Do we really want to unconditionally activate the FPU?

Let's say supporting MPX didn't require eager mode and someone called
get_xsave_addr().  We would ideally want to keep the FPU inactive and
just return NULL.  Right?

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-27 18:36 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
@ 2015-05-28  8:41   ` Ingo Molnar
  2015-05-28 14:45     ` Dave Hansen
  2015-05-29 16:47     ` Dave Hansen
  0 siblings, 2 replies; 30+ messages in thread
From: Ingo Molnar @ 2015-05-28  8:41 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, tglx, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


* Dave Hansen <dave@sr71.net> wrote:

> 
> From: Dave Hansen <dave.hansen@linux.intel.com>
> 
> The MPX code appears to be saving off the FPU in an unsafe
> way.  It does not disable preemption or ensure that the
> FPU state has been allocated.  All of the preemption safety
> comes from the unfortunatley-named 'unlazy_fpu()'.

Btw., with the new FPU code these functions are named differently, and the bug in 
the MPX code became a lot more obvious:

     copy_fpregs_to_fpstate(&tsk->thread.fpu);
     xsave_buf = &(tsk->thread.fpu.state.xsave);
     bndcsr = get_xsave_addr(xsave_buf, XSTATE_BNDCSR);

it's indeed generally unsafe to access/copy FPU registers with preemption enabled, 
for two reasons:

  - on older systems that use FSAVE the instruction destroys FPU register
    contents, which has to be handled carefully

  - even on newer systems if we copy to FPU registers (which this code doesn't) 
    then we don't want a context switch to occur in the middle of it, because a 
    context switch will write to the fpstate, potentially overwriting our new data 
    with old FPU state.

But it's safe to access FPU registers with preemption enabled in a couple of 
special cases:

  - potentially destructively saving FPU registers: the signal handling code does
    this in copy_fpstate_to_sigframe(), because it can rely on the signal restore
    side to restore the original FPU state.

  - reading FPU registers on modern systems: we don't do this anywhere at the
    moment, mostly to keep symmetry with older systems where FSAVE is
    destructive.

  - initializing FPU registers on modern systems: fpu__clear() does this. Here
    it's safe because we don't copy from the fpstate.

  - directly writing FPU registers from user-space memory (!). We do this in
    fpu__restore_sig(), and it's safe because neither context switches nor
    irq-handler FPU use can corrupt the source context of the copy (which is
    user-space memory).

Note that the MPX code's current use of copy_fpregs_to_fpstate() was safe I think, 
because:

 - MPX is predicated on eagerfpu, so the destructive F[N]SAVE instruction won't be 
   used.

 - the code was only reading FPU registers, and was doing it only in places that
   guaranteed that an FPU state was already active (i.e. didn't do it in
   kthreads)

But ... I agree that a more robust API should be used to access FPU registers:

> @@ -427,3 +427,36 @@ void *get_xsave_addr(struct xregs_state
>  	return (void *)xsave + xstate_comp_offsets[feature_nr];
>  }
>  EXPORT_SYMBOL_GPL(get_xsave_addr);
>
> +/*
> + * This wraps up the common operations that need to occur when retrieving
> + * data from xsave state.  It first ensures that the current task was
> + * using the FPU and retrieves the data in to a buffer.  It then calculates
> + * the offset of the requested field in the buffer.
> + *
> + * This function is safe to call whether the FPU is in use or not.
> + *
> + * Note that this only works on the current task.
> + *
> + * Inputs:
> + *	@xsave_state: state which is defined in xsave.h (e.g. XSTATE_FP,
> + *	XSTATE_SSE, etc...)
> + * Output:
> + *	address of the state in the xsave area or NULL if the state
> + *	is not present or is in its 'init state'.
> + */
> +void *get_xsave_field_ptr(int xsave_state)

So this is retrieving (reading) data from FPU registers, but returns a writable 
'void *'. So the return pointer from this interface should be constified, to make 
sure no modifications may occur over them (which modificiations would be unsafe).

> +	union fpregs_state *xstate;
> +
> +	if (!current->thread.fpu.fpstate_active)
> +		return NULL;
> +	/*
> +	 * fpu__save() takes the CPU's xstate registers
> +	 * and saves them off to the 'fpu memory buffer.
> +	 */
> +	fpu__save(&current->thread.fpu);
> +	xstate = &current->thread.fpu.state;
> +
> +	return get_xsave_addr(&xstate->xsave, xsave_state);

Small nit, this would become a lot shorter if you introduced a helper local 
variable:

	struct fpu *fpu = &current->thread.fpu;

But more importantly, for a generic get_xsave_field_ptr() API, fpu__save() is not 
enough: fpu__save() will only save FPU registers into memory if necessary (i.e. if 
the FPU is already in use), and if you call it on a task with no FPU state then it 
will still have an !fpu->fpstate_active FPU state after the call, with random, 
invalid data in the xsave area.

What you want here is to make the (in-memory) FPU state valid and current, before 
reading it, and the function to use for that is fpu__activate_fpstate_read() 
(available in the latest tip:x86/fpu tree).

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-27 18:36 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
@ 2015-05-27 18:36 ` Dave Hansen
  2015-05-28  8:41   ` Ingo Molnar
  0 siblings, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-27 18:36 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code appears to be saving off the FPU in an unsafe
way.  It does not disable preemption or ensure that the
FPU state has been allocated.  All of the preemption safety
comes from the unfortunatley-named 'unlazy_fpu()'.

This patch introduces a new helper which will do both of
those things internally.

Note that this requires a patch from Oleg in order to work
properly.  It is currently in tip/x86/fpu.

> commit f893959b0898bd876673adbeb6798bdf25c034d7
> Author: Oleg Nesterov <oleg@redhat.com>
> Date:   Fri Mar 13 18:30:30 2015 +0100
>
>    x86/fpu: Don't abuse drop_init_fpu() in flush_thread()

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>

---

Changes from v21:
 * add comments about preemption
 * rename helper to get_xsave_field_ptr()

Changes from "v19":
 * remove 'tsk' argument to get_xsave_addr() since the code
   can only realistically work on 'current', and fix up the
   comment a bit to match.

Changes from "v17":
 * fix s/xstate/xsave_field/ in the function comment
 * remove EXPORT_SYMBOL_GPL()

---

 b/arch/x86/include/asm/fpu/xstate.h |    1 +
 b/arch/x86/kernel/fpu/xstate.c      |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff -puN arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr arch/x86/include/asm/fpu/xstate.h
--- a/arch/x86/include/asm/fpu/xstate.h~tsk_get_xsave_addr	2015-05-27 09:32:14.928463071 -0700
+++ b/arch/x86/include/asm/fpu/xstate.h	2015-05-27 09:32:14.934463342 -0700
@@ -41,5 +41,6 @@ extern u64 xstate_fx_sw_bytes[USER_XSTAT
 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
 
 void *get_xsave_addr(struct xregs_state *xsave, int xstate);
+void *get_xsave_field_ptr(int xstate_field);
 
 #endif
diff -puN arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~tsk_get_xsave_addr	2015-05-27 09:32:14.930463161 -0700
+++ b/arch/x86/kernel/fpu/xstate.c	2015-05-27 09:32:14.934463342 -0700
@@ -427,3 +427,36 @@ void *get_xsave_addr(struct xregs_state
 	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
+
+/*
+ * This wraps up the common operations that need to occur when retrieving
+ * data from xsave state.  It first ensures that the current task was
+ * using the FPU and retrieves the data in to a buffer.  It then calculates
+ * the offset of the requested field in the buffer.
+ *
+ * This function is safe to call whether the FPU is in use or not.
+ *
+ * Note that this only works on the current task.
+ *
+ * Inputs:
+ *	@xsave_state: state which is defined in xsave.h (e.g. XSTATE_FP,
+ *	XSTATE_SSE, etc...)
+ * Output:
+ *	address of the state in the xsave area or NULL if the state
+ *	is not present or is in its 'init state'.
+ */
+void *get_xsave_field_ptr(int xsave_state)
+{
+	union fpregs_state *xstate;
+
+	if (!current->thread.fpu.fpstate_active)
+		return NULL;
+	/*
+	 * fpu__save() takes the CPU's xstate registers
+	 * and saves them off to the 'fpu memory buffer.
+	 */
+	fpu__save(&current->thread.fpu);
+	xstate = &current->thread.fpu.state;
+
+	return get_xsave_addr(&xstate->xsave, xsave_state);
+}
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-19  6:25 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
@ 2015-05-19  8:15   ` Thomas Gleixner
  0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2015-05-19  8:15 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, dave.hansen, oleg, bp, riel, sbsiddha, luto,
	mingo, hpa, fenghua.yu

On Mon, 18 May 2015, Dave Hansen wrote:
> From: Dave Hansen <dave.hansen@linux.intel.com>
> 
> The MPX code appears to be saving off the FPU in an unsafe
> way.  It does not disable preemption or ensure that the
> FPU state has been allocated.  All of the preemption safety
> comes from the unfortunatley-named 'unlazy_fpu()'.
> 
> This patch introduces a new helper which will do both of
> those things internally.
> 
> Note that this requires a patch from Oleg in order to work
> properly.  It is currently in tip/x86/fpu.
> 
> > commit f893959b0898bd876673adbeb6798bdf25c034d7
> > Author: Oleg Nesterov <oleg@redhat.com>
> > Date:   Fri Mar 13 18:30:30 2015 +0100
> >
> >    x86/fpu: Don't abuse drop_init_fpu() in flush_thread()
> 
> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Cc: bp@alien8.de
> Cc: Rik van Riel <riel@redhat.com>
> Cc: Suresh Siddha <sbsiddha@gmail.com>
> Cc: Andy Lutomirski <luto@amacapital.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: the arch/x86 maintainers <x86@kernel.org>

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer
  2015-05-19  6:25 [PATCH 00/19] x86, mpx updates for 4.2 (take 7) Dave Hansen
@ 2015-05-19  6:25 ` Dave Hansen
  2015-05-19  8:15   ` Thomas Gleixner
  0 siblings, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-19  6:25 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code appears to be saving off the FPU in an unsafe
way.  It does not disable preemption or ensure that the
FPU state has been allocated.  All of the preemption safety
comes from the unfortunatley-named 'unlazy_fpu()'.

This patch introduces a new helper which will do both of
those things internally.

Note that this requires a patch from Oleg in order to work
properly.  It is currently in tip/x86/fpu.

> commit f893959b0898bd876673adbeb6798bdf25c034d7
> Author: Oleg Nesterov <oleg@redhat.com>
> Date:   Fri Mar 13 18:30:30 2015 +0100
>
>    x86/fpu: Don't abuse drop_init_fpu() in flush_thread()

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>

---

Changes from v21:
 * add comments about preemption
 * rename helper to get_xsave_field_ptr()

Changes from "v19":
 * remove 'tsk' argument to get_xsave_addr() since the code
   can only realistically work on 'current', and fix up the
   comment a bit to match.

Changes from "v17":
 * fix s/xstate/xsave_field/ in the function comment
 * remove EXPORT_SYMBOL_GPL()

---

 b/arch/x86/include/asm/xsave.h |    1 +
 b/arch/x86/kernel/xsave.c      |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff -puN arch/x86/include/asm/xsave.h~tsk_get_xsave_addr arch/x86/include/asm/xsave.h
--- a/arch/x86/include/asm/xsave.h~tsk_get_xsave_addr	2015-05-18 17:48:58.222390639 -0700
+++ b/arch/x86/include/asm/xsave.h	2015-05-18 17:48:58.227390864 -0700
@@ -252,6 +252,7 @@ static inline int xrestore_user(struct x
 }
 
 void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
+void *get_xsave_field_ptr(int xstate_field);
 void setup_xstate_comp(void);
 
 #endif
diff -puN arch/x86/kernel/xsave.c~tsk_get_xsave_addr arch/x86/kernel/xsave.c
--- a/arch/x86/kernel/xsave.c~tsk_get_xsave_addr	2015-05-18 17:48:58.224390729 -0700
+++ b/arch/x86/kernel/xsave.c	2015-05-18 17:48:58.227390864 -0700
@@ -750,3 +750,36 @@ void *get_xsave_addr(struct xsave_struct
 	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
+
+/*
+ * This wraps up the common operations that need to occur when retrieving
+ * data from xsave state.  It first ensures that the current task was
+ * using the FPU and retrieves the data in to a buffer.  It then calculates
+ * the offset of the requested field in the buffer.
+ *
+ * This function is safe to call whether the FPU is in use or not.
+ *
+ * Note that this only works on the current task.
+ *
+ * Inputs:
+ *	@xsave_field: state which is defined in xsave.h (e.g. XSTATE_FP,
+ *	XSTATE_SSE, etc...)
+ * Output:
+ *	address of the state in the xsave area or NULL if the field
+ *	is not present or is in its 'init state'.
+ */
+void *get_xsave_field_ptr(int xsave_field)
+{
+	union thread_xstate *xstate;
+
+	if (!tsk_used_math(current))
+		return NULL;
+	/*
+	 * unlazy_fpu() is poorly named and will actually
+	 * save the xstate off in to the memory buffer.
+	 */
+	unlazy_fpu(current);
+	xstate = current->thread.fpu.state;
+
+	return get_xsave_addr(&xstate->xsave, xsave_field);
+}
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: wrap get_xsave_addr() to make it safer
  2015-05-18 19:38   ` Thomas Gleixner
@ 2015-05-18 19:42     ` Thomas Gleixner
  0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2015-05-18 19:42 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, dave.hansen, oleg, bp, riel, sbsiddha, luto,
	mingo, hpa, fenghua.yu



On Mon, 18 May 2015, Thomas Gleixner wrote:

> On Fri, 8 May 2015, Dave Hansen wrote:
> > The MPX code appears to be saving off the FPU in an unsafe
> > way.   It does not disable preemption or ensure that the
> > FPU state has been allocated.
> > 
> > This patch introduces a new helper which will do both of
> > those things internally.
> 
> This changelog does not really match the implementation. Unless I'm
> missing something I can't find anything preemption related.

Gah. Hit send before finishing the mail.

It's unlazy_fpu (which I agree is a horrible name) which does the
right thing.

> > +
> > +/*
> > + * This wraps up the common operations that need to occur when retrieving
> > + * data from xsave state.  It first ensures that the current task was
> > + * using the FPU and retrieves the data in to a buffer.  It then calculates
> > + * the offset of the requested field in the buffer.
> > + *
> > + * This function is safe to call whether the FPU is in use or not.
> > + *
> > + * Note that this only works on the current task.
> > + *
> > + * Inputs:
> > + *	@xsave_field: state which is defined in xsave.h (e.g. XSTATE_FP,
> > + *	XSTATE_SSE, etc...)
> > + * Output:
> > + *	address of the state in the xsave area.
> 
>   or NULL in case of .....
> 
> > + */
> > +void *get_xsave_field(int xsave_field)
> > +{
> > +	union thread_xstate *xstate;
> > +
> > +	if (!tsk_used_math(current))
> > +		return NULL;
> > +	/*
> > +	 * unlazy_fpu() is poorly named and will actually
> > +	 * save the xstate off in to the memory buffer.
> > +	 */
> > +	unlazy_fpu(current);
> > +	xstate = current->thread.fpu.state;
> > +
> > +	return get_xsave_addr(&xstate->xsave, xsave_field);
> > +}
> 
> Thanks,
> 
> 	tglx
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH 02/19] x86, fpu: wrap get_xsave_addr() to make it safer
  2015-05-08 18:59 ` [PATCH 02/19] x86, fpu: wrap get_xsave_addr() to make it safer Dave Hansen
@ 2015-05-18 19:38   ` Thomas Gleixner
  2015-05-18 19:42     ` Thomas Gleixner
  0 siblings, 1 reply; 30+ messages in thread
From: Thomas Gleixner @ 2015-05-18 19:38 UTC (permalink / raw)
  To: Dave Hansen
  Cc: linux-kernel, x86, dave.hansen, oleg, bp, riel, sbsiddha, luto,
	mingo, hpa, fenghua.yu

On Fri, 8 May 2015, Dave Hansen wrote:
> The MPX code appears to be saving off the FPU in an unsafe
> way.   It does not disable preemption or ensure that the
> FPU state has been allocated.
> 
> This patch introduces a new helper which will do both of
> those things internally.

This changelog does not really match the implementation. Unless I'm
missing something I can't find anything preemption related.

> +
> +/*
> + * This wraps up the common operations that need to occur when retrieving
> + * data from xsave state.  It first ensures that the current task was
> + * using the FPU and retrieves the data in to a buffer.  It then calculates
> + * the offset of the requested field in the buffer.
> + *
> + * This function is safe to call whether the FPU is in use or not.
> + *
> + * Note that this only works on the current task.
> + *
> + * Inputs:
> + *	@xsave_field: state which is defined in xsave.h (e.g. XSTATE_FP,
> + *	XSTATE_SSE, etc...)
> + * Output:
> + *	address of the state in the xsave area.

  or NULL in case of .....

> + */
> +void *get_xsave_field(int xsave_field)
> +{
> +	union thread_xstate *xstate;
> +
> +	if (!tsk_used_math(current))
> +		return NULL;
> +	/*
> +	 * unlazy_fpu() is poorly named and will actually
> +	 * save the xstate off in to the memory buffer.
> +	 */
> +	unlazy_fpu(current);
> +	xstate = current->thread.fpu.state;
> +
> +	return get_xsave_addr(&xstate->xsave, xsave_field);
> +}

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH 02/19] x86, fpu: wrap get_xsave_addr() to make it safer
  2015-05-08 18:59 [PATCH 00/19] x86, mpx updates for 4.2 (take 6) Dave Hansen
@ 2015-05-08 18:59 ` Dave Hansen
  2015-05-18 19:38   ` Thomas Gleixner
  0 siblings, 1 reply; 30+ messages in thread
From: Dave Hansen @ 2015-05-08 18:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, tglx, Dave Hansen, dave.hansen, oleg, bp, riel, sbsiddha,
	luto, mingo, hpa, fenghua.yu


From: Dave Hansen <dave.hansen@linux.intel.com>

Changes from "v19":
 * remove 'tsk' argument to get_xsave_addr() since the code
   can only realistically work on 'current', and fix up the
   comment a bit to match.

Changes from "v17":
 * fix s/xstate/xsave_field/ in the function comment
 * remove EXPORT_SYMBOL_GPL()

---
From: Dave Hansen <dave.hansen@linux.intel.com>

The MPX code appears to be saving off the FPU in an unsafe
way.   It does not disable preemption or ensure that the
FPU state has been allocated.

This patch introduces a new helper which will do both of
those things internally.

Note that this requires a patch from Oleg in order to work
properly.  It is currently in tip/x86/fpu.

> commit f893959b0898bd876673adbeb6798bdf25c034d7
> Author: Oleg Nesterov <oleg@redhat.com>
> Date:   Fri Mar 13 18:30:30 2015 +0100
>
>    x86/fpu: Don't abuse drop_init_fpu() in flush_thread()

Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: bp@alien8.de
Cc: Rik van Riel <riel@redhat.com>
Cc: Suresh Siddha <sbsiddha@gmail.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: the arch/x86 maintainers <x86@kernel.org>
---

 b/arch/x86/include/asm/xsave.h |    1 +
 b/arch/x86/kernel/xsave.c      |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff -puN arch/x86/include/asm/xsave.h~tsk_get_xsave_addr arch/x86/include/asm/xsave.h
--- a/arch/x86/include/asm/xsave.h~tsk_get_xsave_addr	2015-05-08 11:46:10.973580863 -0700
+++ b/arch/x86/include/asm/xsave.h	2015-05-08 11:46:10.978581089 -0700
@@ -252,6 +252,7 @@ static inline int xrestore_user(struct x
 }
 
 void *get_xsave_addr(struct xsave_struct *xsave, int xstate);
+void *get_xsave_field(int xstate_field);
 void setup_xstate_comp(void);
 
 #endif
diff -puN arch/x86/kernel/xsave.c~tsk_get_xsave_addr arch/x86/kernel/xsave.c
--- a/arch/x86/kernel/xsave.c~tsk_get_xsave_addr	2015-05-08 11:46:10.975580953 -0700
+++ b/arch/x86/kernel/xsave.c	2015-05-08 11:46:10.978581089 -0700
@@ -749,3 +749,35 @@ void *get_xsave_addr(struct xsave_struct
 	return (void *)xsave + xstate_comp_offsets[feature_nr];
 }
 EXPORT_SYMBOL_GPL(get_xsave_addr);
+
+/*
+ * This wraps up the common operations that need to occur when retrieving
+ * data from xsave state.  It first ensures that the current task was
+ * using the FPU and retrieves the data in to a buffer.  It then calculates
+ * the offset of the requested field in the buffer.
+ *
+ * This function is safe to call whether the FPU is in use or not.
+ *
+ * Note that this only works on the current task.
+ *
+ * Inputs:
+ *	@xsave_field: state which is defined in xsave.h (e.g. XSTATE_FP,
+ *	XSTATE_SSE, etc...)
+ * Output:
+ *	address of the state in the xsave area.
+ */
+void *get_xsave_field(int xsave_field)
+{
+	union thread_xstate *xstate;
+
+	if (!tsk_used_math(current))
+		return NULL;
+	/*
+	 * unlazy_fpu() is poorly named and will actually
+	 * save the xstate off in to the memory buffer.
+	 */
+	unlazy_fpu(current);
+	xstate = current->thread.fpu.state;
+
+	return get_xsave_addr(&xstate->xsave, xsave_field);
+}
_

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2015-06-07 18:37 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-29 22:34 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
2015-05-29 22:34 ` [PATCH 01/19] x86, mpx, xsave: Fix up bad get_xsave_addr() assumptions Dave Hansen
2015-05-29 22:34 ` [PATCH 03/19] x86, mpx: Use new get_xsave_field_ptr() Dave Hansen
2015-05-29 22:34 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
2015-05-29 22:34 ` [PATCH 05/19] x86, mpx: remove redundant MPX_BNDCFG_ADDR_MASK Dave Hansen
2015-05-29 22:34 ` [PATCH 04/19] x86, mpx: Cleanup: Do not pass task around when unnecessary Dave Hansen
2015-06-01 11:14 ` [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Ingo Molnar
2015-06-01 15:09   ` Dave Hansen
  -- strict thread matches above, loose matches on Subject: below --
2015-06-07 18:37 [PATCH 00/19] x86, mpx updates for 4.2 (take 9) Dave Hansen
2015-06-07 18:37 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
2015-05-27 18:36 [PATCH 00/19] x86, mpx updates for 4.2 (take 8) Dave Hansen
2015-05-27 18:36 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
2015-05-28  8:41   ` Ingo Molnar
2015-05-28 14:45     ` Dave Hansen
2015-05-28 15:01       ` Ingo Molnar
2015-05-28 16:02         ` Dave Hansen
2015-05-29 18:49           ` Ingo Molnar
2015-05-28 16:24         ` Dave Hansen
2015-05-29  1:05           ` Andy Lutomirski
2015-05-29 15:31             ` Dave Hansen
2015-05-29 16:10             ` Borislav Petkov
2015-05-29 18:51               ` Ingo Molnar
2015-05-29 18:17             ` Ingo Molnar
2015-05-29 18:29               ` Andy Lutomirski
2015-05-29 18:44                 ` Ingo Molnar
2015-05-29 16:47     ` Dave Hansen
2015-05-29 18:48       ` Ingo Molnar
2015-05-19  6:25 [PATCH 00/19] x86, mpx updates for 4.2 (take 7) Dave Hansen
2015-05-19  6:25 ` [PATCH 02/19] x86, fpu: Wrap get_xsave_addr() to make it safer Dave Hansen
2015-05-19  8:15   ` Thomas Gleixner
2015-05-08 18:59 [PATCH 00/19] x86, mpx updates for 4.2 (take 6) Dave Hansen
2015-05-08 18:59 ` [PATCH 02/19] x86, fpu: wrap get_xsave_addr() to make it safer Dave Hansen
2015-05-18 19:38   ` Thomas Gleixner
2015-05-18 19:42     ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®