Commit afd30525 authored by Juergen Gross's avatar Juergen Gross Committed by Borislav Petkov
Browse files

x86/xen: Drop USERGS_SYSRET64 paravirt call



USERGS_SYSRET64 is used to return from a syscall via SYSRET, but
a Xen PV guest will nevertheless use the IRET hypercall, as there
is no sysret PV hypercall defined.

So instead of testing all the prerequisites for doing a sysret and
then mangling the stack for Xen PV again for doing an iret just use
the iret exit from the beginning.

This can easily be done via an ALTERNATIVE like it is done for the
sysenter compat case already.

It should be noted that this drops the optimization in Xen for not
restoring a few registers when returning to user mode, but it seems
as if the saved instructions in the kernel more than compensate for
this drop (a kernel build in a Xen PV guest was slightly faster with
this patch applied).

While at it remove the stale sysret32 remnants.

Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210120135555.32594-6-jgross@suse.com
parent 53c9d924
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -46,14 +46,6 @@
.code64
.section .entry.text, "ax"

#ifdef CONFIG_PARAVIRT_XXL
SYM_CODE_START(native_usergs_sysret64)
	UNWIND_HINT_EMPTY
	swapgs
	sysretq
SYM_CODE_END(native_usergs_sysret64)
#endif /* CONFIG_PARAVIRT_XXL */

/*
 * 64-bit SYSCALL instruction entry. Up to 6 arguments in registers.
 *
@@ -123,7 +115,12 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
	 * Try to use SYSRET instead of IRET if we're returning to
	 * a completely clean 64-bit userspace context.  If we're not,
	 * go to the slow exit path.
	 * In the Xen PV case we must use iret anyway.
	 */

	ALTERNATIVE "", "jmp	swapgs_restore_regs_and_return_to_usermode", \
		X86_FEATURE_XENPV

	movq	RCX(%rsp), %rcx
	movq	RIP(%rsp), %r11

@@ -215,7 +212,8 @@ syscall_return_via_sysret:

	popq	%rdi
	popq	%rsp
	USERGS_SYSRET64
	swapgs
	sysretq
SYM_CODE_END(entry_SYSCALL_64)

/*
+0 −6
Original line number Diff line number Diff line
@@ -132,12 +132,6 @@ static __always_inline unsigned long arch_local_irq_save(void)
#endif

#define INTERRUPT_RETURN	jmp native_iret
#define USERGS_SYSRET64				\
	swapgs;					\
	sysretq;
#define USERGS_SYSRET32				\
	swapgs;					\
	sysretl

#else
#define INTERRUPT_RETURN		iret
+0 −5
Original line number Diff line number Diff line
@@ -776,11 +776,6 @@ extern void default_banner(void);

#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT_XXL
#define USERGS_SYSRET64							\
	PARA_SITE(PARA_PATCH(PV_CPU_usergs_sysret64),			\
		  ANNOTATE_RETPOLINE_SAFE;				\
		  jmp PARA_INDIRECT(pv_ops+PV_CPU_usergs_sysret64);)

#ifdef CONFIG_DEBUG_ENTRY
#define SAVE_FLAGS(clobbers)                                        \
	PARA_SITE(PARA_PATCH(PV_IRQ_save_fl),			    \
+0 −8
Original line number Diff line number Diff line
@@ -156,14 +156,6 @@ struct pv_cpu_ops {

	u64 (*read_pmc)(int counter);

	/*
	 * Switch to usermode gs and return to 64-bit usermode using
	 * sysret.  Only used in 64-bit kernels to return to 64-bit
	 * processes.  Usermode register state, including %rsp, must
	 * already be restored.
	 */
	void (*usergs_sysret64)(void);

	/* Normal iret.  Jump to this with the standard iret stack
	   frame set up. */
	void (*iret)(void);
+0 −2
Original line number Diff line number Diff line
@@ -13,8 +13,6 @@ int main(void)
{
#ifdef CONFIG_PARAVIRT
#ifdef CONFIG_PARAVIRT_XXL
	OFFSET(PV_CPU_usergs_sysret64, paravirt_patch_template,
	       cpu.usergs_sysret64);
#ifdef CONFIG_DEBUG_ENTRY
	OFFSET(PV_IRQ_save_fl, paravirt_patch_template, irq.save_fl);
#endif
Loading