Commit 1d07316b authored by Chang S. Bae's avatar Chang S. Bae Committed by Thomas Gleixner
Browse files

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: default avatarChang S. Bae <chang.seok.bae@intel.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: "H . Peter Anvin" <hpa@zytor.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ravi Shankar <ravi.v.shankar@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Link: https://lkml.kernel.org/r/1557309753-24073-11-git-send-email-chang.seok.bae@intel.com
parent f60a83df
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -1173,13 +1173,6 @@ ENTRY(paranoid_entry)
	cld
	PUSH_AND_CLEAR_REGS save_ret=1
	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:
	/*
@@ -1191,9 +1184,30 @@ 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.
	 *
	 * 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

	/* 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
	/* EBX = 0 -> SWAPGS required on exit */
	xorl	%ebx, %ebx
	ret
END(paranoid_entry)

@@ -1213,7 +1227,8 @@ ENTRY(paranoid_exit)
	UNWIND_HINT_REGS
	DISABLE_INTERRUPTS(CLBR_ANY)
	TRACE_IRQS_OFF_DEBUG
	testl	%ebx, %ebx			/* swapgs needed? */
	/* If EBX is 0, SWAPGS is required */
	testl	%ebx, %ebx
	jnz	.Lparanoid_exit_no_swapgs
	TRACE_IRQS_IRETQ
	/* Always restore stashed CR3 value (see paranoid_entry) */