From: Dave Hansen <dave@sr71.net>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, Dave Hansen <dave@sr71.net>, dave.hansen@linux.intel.com
Subject: [PATCH 33/37] x86, fpu: allow setting of XSAVE state
Date: Mon, 16 Nov 2015 19:35:57 -0800 [thread overview]
Message-ID: <20151117033557.81D8BA6C@viggo.jf.intel.com> (raw)
In-Reply-To: <20151117033511.BFFA1440@viggo.jf.intel.com>
From: Dave Hansen <dave.hansen@linux.intel.com>
We want to modify the Protection Key rights inside the kernel, so
we need to change PKRU's contents. But, if we do a plain
'wrpkru', when we return to userspace we might do an XRSTOR and
wipe out the kernel's 'wrpkru'. So, we need to go after PKRU in
the xsave buffer.
We do this by looking up the location of a given state in the
XSAVE buffer, filling in the state, and then ensuring that the
hardware knows that state is present there (basically that the
'init optimization' is not in place).
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
---
b/arch/x86/kernel/fpu/xstate.c | 109 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 107 insertions(+), 2 deletions(-)
diff -puN arch/x86/kernel/fpu/xstate.c~pkey-xsave-set arch/x86/kernel/fpu/xstate.c
--- a/arch/x86/kernel/fpu/xstate.c~pkey-xsave-set 2015-11-16 12:35:50.714869761 -0800
+++ b/arch/x86/kernel/fpu/xstate.c 2015-11-16 12:35:50.717869897 -0800
@@ -679,6 +679,19 @@ void fpu__resume_cpu(void)
}
/*
+ * Given an xstate feature mask, calculate where in the xsave
+ * buffer the state is. Callers should ensure that the buffer
+ * is valid.
+ *
+ * Note: does not work for compacted buffers.
+ */
+void *__raw_xsave_addr(struct xregs_state *xsave, int xstate_feature_mask)
+{
+ int feature_nr = fls64(xstate_feature_mask) - 1;
+
+ return (void *)xsave + xstate_comp_offsets[feature_nr];
+}
+/*
* Given the xsave area and a state inside, this function returns the
* address of the state.
*
@@ -698,7 +711,6 @@ void fpu__resume_cpu(void)
*/
void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
{
- int feature_nr = fls64(xstate_feature) - 1;
/*
* Do we even *have* xsave state?
*/
@@ -727,7 +739,7 @@ void *get_xsave_addr(struct xregs_state
if (!(xsave->header.xfeatures & xstate_feature))
return NULL;
- return (void *)xsave + xstate_comp_offsets[feature_nr];
+ return __raw_xsave_addr(xsave, xstate_feature);
}
EXPORT_SYMBOL_GPL(get_xsave_addr);
@@ -762,3 +774,96 @@ const void *get_xsave_field_ptr(int xsav
return get_xsave_addr(&fpu->state.xsave, xsave_state);
}
+
+
+/*
+ * Set xfeatures (aka XSTATE_BV) bit for a feature that we want
+ * to take out of its "init state". This will ensure that an
+ * XRSTOR actually restores the state.
+ */
+static void fpu__xfeature_set_non_init(struct xregs_state *xsave,
+ int xstate_feature_mask)
+{
+ xsave->header.xfeatures |= xstate_feature_mask;
+}
+
+/*
+ * 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. XFEATURE_MASK_FP,
+ * XFEATURE_MASK_SSE, etc...)
+ * @xsave_state_ptr: a pointer to a copy of the state that you would
+ * like written in to the current task's FPU xsave state. This pointer
+ * must not be located in the current tasks's xsave area.
+ * Output:
+ * address of the state in the xsave area or NULL if the state
+ * is not present or is in its 'init state'.
+ */
+static void fpu__xfeature_set_state(int xstate_feature_mask,
+ void *xstate_feature_src, size_t len)
+{
+ struct xregs_state *xsave = ¤t->thread.fpu.state.xsave;
+ struct fpu *fpu = ¤t->thread.fpu;
+ void *dst;
+
+ if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
+ WARN_ONCE(1, "%s() attempted with no xsave support", __func__);
+ return;
+ }
+ /*
+ * Move the CPU FPU state in to the buffer at 'fpu'.
+ * Activate it if not active. Now we can get the old
+ * pkru state out of the buffer.
+ */
+ fpu__activate_fpstate_read(fpu);
+ /*
+ * Move the CPU FPU state in to the buffer at 'fpu'. Now
+ * we can modify the buffer.
+ */
+ fpu__save(fpu);
+ /*
+ * This method *WILL* *NOT* work for compact-format
+ * buffers. If the 'xstate_feature_mask' is unset in
+ * xcomp_bv then we may need to move other feature state
+ * "up" in the buffer.
+ */
+ if (xsave->header.xcomp_bv & xstate_feature_mask) {
+ WARN_ON_ONCE(1);
+ return;
+ }
+
+ /* find the location in the xsave buffer of the desired state */
+ dst = __raw_xsave_addr(&fpu->state.xsave, xstate_feature_mask);
+
+ /*
+ * Make sure that the pointer being passed in did not
+ * come from the xsave buffer itself.
+ */
+ WARN_ONCE(xstate_feature_src == dst, "set from xsave buffer itself");
+
+ /* tell the FPU code that we are writing to the FPU state */
+ fpu__activate_fpstate_write(fpu);
+
+ /* put the caller-requested data in the location */
+ memcpy(dst, xstate_feature_src, len);
+
+ /*
+ * Mark the xfeature so that the CPU knows there is state
+ * in the buffer now.
+ */
+ fpu__xfeature_set_non_init(xsave, xstate_feature_mask);
+
+ /*
+ * The fpu state now has an updated copy of the state,
+ * but the registers may still be out of date. Update
+ * them with an XRSTOR.
+ */
+ preempt_disable();
+ fpu__restore(fpu);
+ preempt_enable();
+
+ return 0;
+}
_
next prev parent reply other threads:[~2015-11-17 3:36 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-11-17 3:35 [PATCH 00/37] x86: Memory Protection Keys Dave Hansen
2015-11-17 3:35 ` [PATCH 01/37] uprobes: dont pass around current->mm Dave Hansen
2015-11-17 3:35 ` [PATCH 02/37] mm, frame_vector: do not use get_user_pages_locked() Dave Hansen
2015-11-18 12:29 ` Jan Kara
2015-11-18 17:04 ` Andrea Arcangeli
2015-11-17 3:35 ` [PATCH 03/37] mm: kill get_user_pages_locked() Dave Hansen
2015-11-17 3:35 ` [PATCH 04/37] mm: simplify __get_user_pages() Dave Hansen
2015-11-17 3:35 ` [PATCH 05/37] mm, gup: introduce concept of "foreign" get_user_pages() Dave Hansen
2015-11-17 3:35 ` [PATCH 06/37] x86, fpu: add placeholder for Processor Trace XSAVE state Dave Hansen
2015-11-17 3:35 ` [PATCH 07/37] x86, pkeys: Add Kconfig option Dave Hansen
2015-11-17 3:35 ` [PATCH 08/37] x86, pkeys: cpuid bit definition Dave Hansen
2015-11-17 3:35 ` [PATCH 09/37] x86, pkeys: define new CR4 bit Dave Hansen
2015-11-17 3:35 ` [PATCH 10/37] x86, pkeys: add PKRU xsave fields and data structure(s) Dave Hansen
2015-11-27 9:23 ` Thomas Gleixner
2015-11-17 3:35 ` [PATCH 11/37] x86, pkeys: PTE bits for storing protection key Dave Hansen
2015-11-17 3:35 ` [PATCH 12/37] x86, pkeys: new page fault error code bit: PF_PK Dave Hansen
2015-11-17 3:35 ` [PATCH 13/37] x86, pkeys: store protection in high VMA flags Dave Hansen
2015-11-17 3:35 ` [PATCH 14/37] x86, pkeys: arch-specific protection bits Dave Hansen
2015-11-17 3:35 ` [PATCH 15/37] x86, pkeys: pass VMA down in to fault signal generation code Dave Hansen
2015-11-27 9:30 ` Thomas Gleixner
2015-11-17 3:35 ` [PATCH 16/37] x86, pkeys: notify userspace about protection key faults Dave Hansen
2015-11-27 9:49 ` Thomas Gleixner
2015-11-17 3:35 ` [PATCH 17/37] x86, pkeys: add functions to fetch PKRU Dave Hansen
2015-11-27 9:51 ` Thomas Gleixner
2015-11-30 15:51 ` Dave Hansen
2015-11-17 3:35 ` [PATCH 18/37] mm: factor out VMA fault permission checking Dave Hansen
2015-11-27 9:53 ` Thomas Gleixner
2015-11-17 3:35 ` [PATCH 19/37] x86, mm: simplify get_user_pages() PTE bit handling Dave Hansen
2015-11-27 10:12 ` Thomas Gleixner
2015-11-30 16:25 ` Dave Hansen
2015-11-17 3:35 ` [PATCH 20/37] x86, pkeys: check VMAs and PTEs for protection keys Dave Hansen
2015-11-17 3:35 ` [PATCH 21/37] mm: add gup flag to indicate "foreign" mm access Dave Hansen
2015-11-17 3:35 ` [PATCH 22/37] x86, pkeys: optimize fault handling in access_error() Dave Hansen
2015-11-17 3:35 ` [PATCH 23/37] x86, pkeys: differentiate instruction fetches Dave Hansen
2015-11-17 3:35 ` [PATCH 24/37] x86, pkeys: dump PKRU with other kernel registers Dave Hansen
2015-11-17 3:35 ` [PATCH 25/37] x86, pkeys: dump PTE pkey in /proc/pid/smaps Dave Hansen
2015-11-17 3:35 ` [PATCH 26/37] x86, pkeys: add Kconfig prompt to existing config option Dave Hansen
2015-11-17 3:35 ` [PATCH 27/37] mm, multi-arch: pass a protection key in to calc_vm_flag_bits() Dave Hansen
2015-11-17 3:35 ` [PATCH 28/37] x86, pkeys: add arch_validate_pkey() Dave Hansen
2015-11-17 3:35 ` [PATCH 29/37] mm: implement new mprotect_key() system call Dave Hansen
2015-11-17 3:35 ` [PATCH 30/37] x86, pkeys: make mprotect_key() mask off additional vm_flags Dave Hansen
2015-11-17 3:35 ` [PATCH 31/37] x86: wire up mprotect_key() system call Dave Hansen
2015-11-17 3:35 ` [PATCH 32/37] x86: separate out LDT init from context init Dave Hansen
2015-11-17 3:35 ` Dave Hansen [this message]
2015-11-17 3:35 ` [PATCH 34/37] x86, pkeys: allocation/free syscalls Dave Hansen
2015-11-17 3:36 ` [PATCH 35/37] x86, pkeys: add pkey set/get syscalls Dave Hansen
2015-11-17 3:36 ` [PATCH 36/37] x86, pkeys: actually enable Memory Protection Keys in CPU Dave Hansen
2015-11-17 3:36 ` [PATCH 37/37] x86, pkeys: Documentation Dave Hansen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151117033557.81D8BA6C@viggo.jf.intel.com \
--to=dave@sr71.net \
--cc=dave.hansen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox