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 <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: H. Peter Anvin <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Andi Kleen <[email protected]>
---
 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

Reply via email to