diff mbox series

[19/27] x86/fpu: Update xstate's PKRU value on write_pkru()

Message ID 20190403164156.19645-20-bigeasy@linutronix.de (mailing list archive)
State New, archived
Headers show
Series [01/27] x86/fpu: Remove fpu->initialized usage in __fpu__restore_sig() | expand

Commit Message

Sebastian Andrzej Siewior April 3, 2019, 4:41 p.m. UTC
During the context switch the xstate is loaded which also includes the
PKRU value.
If xstate is restored on return to userland it is required that the
PKRU value in xstate is the same as the one in the CPU.

Save the PKRU in xstate during modification.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 arch/x86/include/asm/pgtable.h | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

Comments

Dave Hansen April 8, 2019, 6:14 p.m. UTC | #1
On 4/3/19 9:41 AM, Sebastian Andrzej Siewior wrote:
> During the context switch the xstate is loaded which also includes the
> PKRU value.
> If xstate is restored on return to userland it is required that the
> PKRU value in xstate is the same as the one in the CPU.

All of the protection keys bits in here look ok to me.  Thanks for the
sustained work to get all those into shape.  I know it's a special
snowflake.

Although I paid much closer attention to the PK bits, feel free to add:

Reviewed-by: Dave Hansen <dave.hansen@intel.com>

for the series.
Sebastian Andrzej Siewior April 8, 2019, 8:03 p.m. UTC | #2
On 2019-04-08 11:14:28 [-0700], Dave Hansen wrote:
> On 4/3/19 9:41 AM, Sebastian Andrzej Siewior wrote:
> > During the context switch the xstate is loaded which also includes the
> > PKRU value.
> > If xstate is restored on return to userland it is required that the
> > PKRU value in xstate is the same as the one in the CPU.
> 
> All of the protection keys bits in here look ok to me.  Thanks for the
> sustained work to get all those into shape.  I know it's a special
> snowflake.

> Although I paid much closer attention to the PK bits, feel free to add:
> 
> Reviewed-by: Dave Hansen <dave.hansen@intel.com>
> 
> for the series.

Thank you.

Sebastian
diff mbox series

Patch

diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 1df90feeea5c6..58a3a68e1f114 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -23,6 +23,8 @@ 
 
 #ifndef __ASSEMBLY__
 #include <asm/x86_init.h>
+#include <asm/fpu/xstate.h>
+#include <asm/fpu/api.h>
 
 extern pgd_t early_top_pgt[PTRS_PER_PGD];
 int __init __early_make_pgtable(unsigned long address, pmdval_t pmd);
@@ -133,8 +135,22 @@  static inline u32 read_pkru(void)
 
 static inline void write_pkru(u32 pkru)
 {
-	if (boot_cpu_has(X86_FEATURE_OSPKE))
-		__write_pkru(pkru);
+	struct pkru_state *pk;
+
+	if (!boot_cpu_has(X86_FEATURE_OSPKE))
+		return;
+
+	pk = get_xsave_addr(&current->thread.fpu.state.xsave, XFEATURE_PKRU);
+	/*
+	 * The PKRU value in xstate needs to be in sync with the value that is
+	 * written to the CPU. The FPU restore on return to userland would
+	 * otherwise load the previous value again.
+	 */
+	fpregs_lock();
+	if (pk)
+		pk->pkru = pkru;
+	__write_pkru(pkru);
+	fpregs_unlock();
 }
 
 static inline int pte_young(pte_t pte)