]> www.infradead.org Git - users/willy/xarray.git/commitdiff
x86/xen: Drop USERGS_SYSRET64 paravirt call
authorJuergen Gross <jgross@suse.com>
Wed, 20 Jan 2021 13:55:45 +0000 (14:55 +0100)
committerBorislav Petkov <bp@suse.de>
Wed, 10 Feb 2021 11:32:07 +0000 (12:32 +0100)
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: Juergen Gross <jgross@suse.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20210120135555.32594-6-jgross@suse.com
arch/x86/entry/entry_64.S
arch/x86/include/asm/irqflags.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/kernel/asm-offsets_64.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/paravirt_patch.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/xen-asm.S
arch/x86/xen/xen-ops.h

index a876204a73e0bc1f07235a1c66b8b5ef35b70638..ce0464d630a23b08fc1db899427aaed3024c1b2b 100644 (file)
 .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)
 
 /*
index 8c86edefa11508ab3401ead3bcfd757b3834e015..e585a4705b8ddc298333cf4bf35f0471cacace93 100644 (file)
@@ -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
index f2ebe109a37e4d184a22350cdeed5dab1ab6603e..dd43b1100a871e4caaf9bf0de927aa6b15785167 100644 (file)
@@ -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),                       \
index 130f428b0cc8de830d337636134a4c5173f02c2c..0169365f140324b927951b772e7eab9e54ce65e9 100644 (file)
@@ -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);
index 1354bc30614d7e9411167093c6df09d784cdd090..b14533af7676253118e0b18cb31ca16289782e12 100644 (file)
@@ -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
index 5e5fcf5c376de76bd29a45bd5c452909351bfde2..18560b71e717ef0ee6a2bb6a31cda4a303001ccd 100644 (file)
@@ -135,8 +135,7 @@ unsigned paravirt_patch_default(u8 type, void *insn_buff,
        else if (opfunc == _paravirt_ident_64)
                ret = paravirt_patch_ident_64(insn_buff, len);
 
-       else if (type == PARAVIRT_PATCH(cpu.iret) ||
-                type == PARAVIRT_PATCH(cpu.usergs_sysret64))
+       else if (type == PARAVIRT_PATCH(cpu.iret))
                /* If operation requires a jmp, then jmp */
                ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len);
 #endif
@@ -170,7 +169,6 @@ static u64 native_steal_clock(int cpu)
 
 /* These are in entry.S */
 extern void native_iret(void);
-extern void native_usergs_sysret64(void);
 
 static struct resource reserve_ioports = {
        .start = 0,
@@ -310,7 +308,6 @@ struct paravirt_patch_template pv_ops = {
 
        .cpu.load_sp0           = native_load_sp0,
 
-       .cpu.usergs_sysret64    = native_usergs_sysret64,
        .cpu.iret               = native_iret,
 
 #ifdef CONFIG_X86_IOPL_IOPERM
index 7c518b08aa3c5c0fcd49fe89f1259e65c18cfd71..2fada2c347c98e6eae203cb8bee601db071674ac 100644 (file)
@@ -27,7 +27,6 @@ struct patch_xxl {
        const unsigned char     mmu_write_cr3[3];
        const unsigned char     irq_restore_fl[2];
        const unsigned char     cpu_wbinvd[2];
-       const unsigned char     cpu_usergs_sysret64[6];
        const unsigned char     mov64[3];
 };
 
@@ -40,8 +39,6 @@ static const struct patch_xxl patch_data_xxl = {
        .mmu_write_cr3          = { 0x0f, 0x22, 0xdf }, // mov %rdi, %cr3
        .irq_restore_fl         = { 0x57, 0x9d },       // push %rdi; popfq
        .cpu_wbinvd             = { 0x0f, 0x09 },       // wbinvd
-       .cpu_usergs_sysret64    = { 0x0f, 0x01, 0xf8,
-                                   0x48, 0x0f, 0x07 }, // swapgs; sysretq
        .mov64                  = { 0x48, 0x89, 0xf8 }, // mov %rdi, %rax
 };
 
@@ -83,7 +80,6 @@ unsigned int native_patch(u8 type, void *insn_buff, unsigned long addr,
        PATCH_CASE(mmu, read_cr3, xxl, insn_buff, len);
        PATCH_CASE(mmu, write_cr3, xxl, insn_buff, len);
 
-       PATCH_CASE(cpu, usergs_sysret64, xxl, insn_buff, len);
        PATCH_CASE(cpu, wbinvd, xxl, insn_buff, len);
 #endif
 
index 95f37996152adfb4998531b31ec4d39a885e7d11..6abf3f2481970e7b53e3760a120dc80c29ba0186 100644 (file)
@@ -1073,7 +1073,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .read_pmc = xen_read_pmc,
 
        .iret = xen_iret,
-       .usergs_sysret64 = xen_sysret64,
 
        .load_tr_desc = paravirt_nop,
        .set_ldt = xen_set_ldt,
index eac9dac3656ab88e34b9a67868da9e9c8224e4e2..1d738c5957f574a634510830f5bc3c9bbd5ed503 100644 (file)
@@ -215,26 +215,6 @@ SYM_CODE_START(xen_iret)
        jmp hypercall_iret
 SYM_CODE_END(xen_iret)
 
-SYM_CODE_START(xen_sysret64)
-       /*
-        * We're already on the usermode stack at this point, but
-        * still with the kernel gs, so we can easily switch back.
-        *
-        * tss.sp2 is scratch space.
-        */
-       movq %rsp, PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
-       movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
-
-       pushq $__USER_DS
-       pushq PER_CPU_VAR(cpu_tss_rw + TSS_sp2)
-       pushq %r11
-       pushq $__USER_CS
-       pushq %rcx
-
-       pushq $VGCF_in_syscall
-       jmp hypercall_iret
-SYM_CODE_END(xen_sysret64)
-
 /*
  * Xen handles syscall callbacks much like ordinary exceptions, which
  * means we have:
index 9546c3384c7597913383dc1ccdfa09494b338fe7..b2fd80a01a36b300fa3c0f480e722a9250a3351d 100644 (file)
@@ -138,8 +138,6 @@ __visible unsigned long xen_read_cr2_direct(void);
 
 /* These are not functions, and cannot be called normally */
 __visible void xen_iret(void);
-__visible void xen_sysret32(void);
-__visible void xen_sysret64(void);
 
 extern int xen_panic_handler_init(void);