x86/entry/64: Switch CR3 before SWAPGS in paranoid entry

When FSGSBASE is enabled, the GSBASE handling in paranoid entry will need
to retrieve the kernel GSBASE which requires that the kernel page table is
active.

As the CR3 switch to the kernel page tables (PTI is active) does not depend
on kernel GSBASE, move the CR3 switch in front of the GSBASE handling.

Comment the EBX content while at it.

No functional change.

[ tglx: Rewrote changelog and comments ]

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/1557309753-24073-11-git-send-email-chang.seok.bae@intel.com
Link: https://lkml.kernel.org/r/20200528201402.1708239-10-sashal@kernel.org
This commit is contained in:
Chang S. Bae 2020-05-28 16:13:55 -04:00 коммит произвёл Thomas Gleixner
Родитель 978e1342c3
Коммит 96b2371413
1 изменённых файлов: 24 добавлений и 8 удалений

Просмотреть файл

@ -807,13 +807,6 @@ SYM_CODE_START_LOCAL(paranoid_entry)
cld cld
PUSH_AND_CLEAR_REGS save_ret=1 PUSH_AND_CLEAR_REGS save_ret=1
ENCODE_FRAME_POINTER 8 ENCODE_FRAME_POINTER 8
movl $1, %ebx
movl $MSR_GS_BASE, %ecx
rdmsr
testl %edx, %edx
js 1f /* negative -> in kernel */
SWAPGS
xorl %ebx, %ebx
1: 1:
/* /*
@ -825,9 +818,29 @@ SYM_CODE_START_LOCAL(paranoid_entry)
* This is also why CS (stashed in the "iret frame" by the * This is also why CS (stashed in the "iret frame" by the
* hardware at entry) can not be used: this may be a return * hardware at entry) can not be used: this may be a return
* to kernel code, but with a user CR3 value. * to kernel code, but with a user CR3 value.
*
* Switching CR3 does not depend on kernel GSBASE so it can
* be done before switching to the kernel GSBASE. This is
* required for FSGSBASE because the kernel GSBASE has to
* be retrieved from a kernel internal table.
*/ */
SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14 SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
/* EBX = 1 -> kernel GSBASE active, no restore required */
movl $1, %ebx
/*
* The kernel-enforced convention is a negative GSBASE indicates
* a kernel value. No SWAPGS needed on entry and exit.
*/
movl $MSR_GS_BASE, %ecx
rdmsr
testl %edx, %edx
jns .Lparanoid_entry_swapgs
ret
.Lparanoid_entry_swapgs:
SWAPGS
/* /*
* The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an
* unconditional CR3 write, even in the PTI case. So do an lfence * unconditional CR3 write, even in the PTI case. So do an lfence
@ -835,6 +848,8 @@ SYM_CODE_START_LOCAL(paranoid_entry)
*/ */
FENCE_SWAPGS_KERNEL_ENTRY FENCE_SWAPGS_KERNEL_ENTRY
/* EBX = 0 -> SWAPGS required on exit */
xorl %ebx, %ebx
ret ret
SYM_CODE_END(paranoid_entry) SYM_CODE_END(paranoid_entry)
@ -852,7 +867,8 @@ SYM_CODE_END(paranoid_entry)
*/ */
SYM_CODE_START_LOCAL(paranoid_exit) SYM_CODE_START_LOCAL(paranoid_exit)
UNWIND_HINT_REGS UNWIND_HINT_REGS
testl %ebx, %ebx /* swapgs needed? */ /* If EBX is 0, SWAPGS is required */
testl %ebx, %ebx
jnz .Lparanoid_exit_no_swapgs jnz .Lparanoid_exit_no_swapgs
/* Always restore stashed CR3 value (see paranoid_entry) */ /* Always restore stashed CR3 value (see paranoid_entry) */
RESTORE_CR3 scratch_reg=%rbx save_reg=%r14 RESTORE_CR3 scratch_reg=%rbx save_reg=%r14