[PATCH v7 10/18] x86/entry/64: Switch CR3 before SWAPGS on the paranoid entry

From: Chang S. Bae
Date: Wed May 08 2019 - 13:05:04 EST


When FSGSBASE is enabled, GSBASE handling on the paranoid entry will
need to retrieve the kernel GSBASE. Thus, the kernel page table should
be in. As a preparation, the CR3 switching is moved to happen at
first, before the SWAPGS.

Current GSBASE switching mechanism is possible without the kernel
page table in. No functional change is expected.

Signed-off-by: Chang S. Bae <chang.seok.bae@xxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Cc: Andy Lutomirski <luto@xxxxxxxxxx>
Cc: H. Peter Anvin <hpa@xxxxxxxxx>
Cc: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
---
arch/x86/entry/entry_64.S | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 568a491..034d8f8 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -1160,18 +1160,6 @@ ENTRY(paranoid_entry)
PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER 8

- movl $1, %ebx
- /*
- * The kernel-enforced convention is a negative GSBASE indicates
- * a kernel value.
- */
- READ_MSR_GSBASE save_reg=%edx
- testl %edx, %edx /* Negative -> in kernel */
- js 1f
- SWAPGS
- xorl %ebx, %ebx
-
-1:
/*
* Always stash CR3 in %r14. This value will be restored,
* verbatim, at exit. Needed if paranoid_entry interrupted
@@ -1181,9 +1169,26 @@ ENTRY(paranoid_entry)
* This is also why CS (stashed in the "iret frame" by the
* hardware at entry) can not be used: this may be a return
* to kernel code, but with a user CR3 value.
+ *
+ * This PTI macro doesn't depend on kernel GSBASE and, with
+ * FSGSBASE, the GSBASE handling requires the kernel page
+ * tables switched in. So, do it early here.
*/
SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14

+ movl $1, %ebx
+ /*
+ * The kernel-enforced convention is a negative GSBASE indicates
+ * a kernel value.
+ */
+ READ_MSR_GSBASE save_reg=%edx
+ testl %edx, %edx /* Negative -> in kernel */
+ jns .Lparanoid_entry_swapgs
+ ret
+
+.Lparanoid_entry_swapgs:
+ SWAPGS
+ xorl %ebx, %ebx
ret
END(paranoid_entry)

--
2.7.4