]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 May 2024 06:34:30 +0000 (08:34 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 May 2024 06:34:30 +0000 (08:34 +0200)
added patches:
x86-xen-drop-usergs_sysret64-paravirt-call.patch

queue-5.10/series
queue-5.10/x86-xen-drop-usergs_sysret64-paravirt-call.patch [new file with mode: 0644]

index 37e0beb553df8054a5e39ea3870daa0c8fa38def..ca44d55c23e50ed83ac20f67ccd52178059646f2 100644 (file)
@@ -1 +1,2 @@
 pinctrl-core-handle-radix_tree_insert-errors-in-pinctrl_register_one_pin.patch
+x86-xen-drop-usergs_sysret64-paravirt-call.patch
diff --git a/queue-5.10/x86-xen-drop-usergs_sysret64-paravirt-call.patch b/queue-5.10/x86-xen-drop-usergs_sysret64-paravirt-call.patch
new file mode 100644 (file)
index 0000000..2169ad1
--- /dev/null
@@ -0,0 +1,275 @@
+From afd30525a659ac0ae0904f0cb4a2ca75522c3123 Mon Sep 17 00:00:00 2001
+From: Juergen Gross <jgross@suse.com>
+Date: Wed, 20 Jan 2021 14:55:45 +0100
+Subject: x86/xen: Drop USERGS_SYSRET64 paravirt call
+
+From: Juergen Gross <jgross@suse.com>
+
+commit afd30525a659ac0ae0904f0cb4a2ca75522c3123 upstream.
+
+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.
+
+  [ pawan: Brad Spengler and Salvatore Bonaccorso <carnil@debian.org>
+          reported a problem with the 5.10 backport commit edc702b4a820
+          ("x86/entry_64: Add VERW just before userspace transition").
+
+          When CONFIG_PARAVIRT_XXL=y, CLEAR_CPU_BUFFERS is not executed in
+          syscall_return_via_sysret path as USERGS_SYSRET64 is runtime
+          patched to:
+
+       .cpu_usergs_sysret64    = { 0x0f, 0x01, 0xf8,
+                                   0x48, 0x0f, 0x07 }, // swapgs; sysretq
+
+          which is missing CLEAR_CPU_BUFFERS. It turns out dropping
+          USERGS_SYSRET64 simplifies the code, allowing CLEAR_CPU_BUFFERS
+          to be explicitly added to syscall_return_via_sysret path. Below
+          is with CONFIG_PARAVIRT_XXL=y and this patch applied:
+
+          syscall_return_via_sysret:
+          ...
+          <+342>:   swapgs
+          <+345>:   xchg   %ax,%ax
+          <+347>:   verw   -0x1a2(%rip)  <------
+          <+354>:   sysretq
+  ]
+
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Link: https://lkml.kernel.org/r/20210120135555.32594-6-jgross@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/entry/entry_64.S             |   17 ++++++++---------
+ arch/x86/include/asm/irqflags.h       |    7 -------
+ arch/x86/include/asm/paravirt.h       |    5 -----
+ arch/x86/include/asm/paravirt_types.h |    8 --------
+ arch/x86/kernel/asm-offsets_64.c      |    2 --
+ arch/x86/kernel/paravirt.c            |    5 +----
+ arch/x86/kernel/paravirt_patch.c      |    4 ----
+ arch/x86/xen/enlighten_pv.c           |    1 -
+ arch/x86/xen/xen-asm.S                |   21 ---------------------
+ arch/x86/xen/xen-ops.h                |    2 --
+ 10 files changed, 9 insertions(+), 63 deletions(-)
+
+--- a/arch/x86/entry/entry_64.S
++++ b/arch/x86/entry/entry_64.S
+@@ -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.
+  *
+@@ -128,7 +120,12 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_h
+        * 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
+@@ -220,7 +217,9 @@ syscall_return_via_sysret:
+       popq    %rdi
+       popq    %rsp
+-      USERGS_SYSRET64
++      swapgs
++      CLEAR_CPU_BUFFERS
++      sysretq
+ SYM_CODE_END(entry_SYSCALL_64)
+ /*
+--- a/arch/x86/include/asm/irqflags.h
++++ b/arch/x86/include/asm/irqflags.h
+@@ -132,13 +132,6 @@ static __always_inline unsigned long arc
+ #endif
+ #define INTERRUPT_RETURN      jmp native_iret
+-#define USERGS_SYSRET64                               \
+-      swapgs;                                 \
+-      CLEAR_CPU_BUFFERS;                      \
+-      sysretq;
+-#define USERGS_SYSRET32                               \
+-      swapgs;                                 \
+-      sysretl
+ #else
+ #define INTERRUPT_RETURN              iret
+--- a/arch/x86/include/asm/paravirt.h
++++ b/arch/x86/include/asm/paravirt.h
+@@ -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),                       \
+--- a/arch/x86/include/asm/paravirt_types.h
++++ b/arch/x86/include/asm/paravirt_types.h
+@@ -157,14 +157,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);
+--- a/arch/x86/kernel/asm-offsets_64.c
++++ b/arch/x86/kernel/asm-offsets_64.c
+@@ -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
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -124,8 +124,7 @@ unsigned paravirt_patch_default(u8 type,
+       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
+@@ -159,7 +158,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,
+@@ -299,7 +297,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
+--- a/arch/x86/kernel/paravirt_patch.c
++++ b/arch/x86/kernel/paravirt_patch.c
+@@ -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
+       .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
+       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
+--- a/arch/x86/xen/enlighten_pv.c
++++ b/arch/x86/xen/enlighten_pv.c
+@@ -1059,7 +1059,6 @@ static const struct pv_cpu_ops xen_cpu_o
+       .read_pmc = xen_read_pmc,
+       .iret = xen_iret,
+-      .usergs_sysret64 = xen_sysret64,
+       .load_tr_desc = paravirt_nop,
+       .set_ldt = xen_set_ldt,
+--- a/arch/x86/xen/xen-asm.S
++++ b/arch/x86/xen/xen-asm.S
+@@ -220,27 +220,6 @@ SYM_CODE_START(xen_iret)
+       jmp hypercall_iret
+ SYM_CODE_END(xen_iret)
+-SYM_CODE_START(xen_sysret64)
+-      UNWIND_HINT_EMPTY
+-      /*
+-       * 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 pv doesn't use trampoline stack, PER_CPU_VAR(cpu_tss_rw + TSS_sp0) is
+  * also the kernel stack.  Reusing swapgs_restore_regs_and_return_to_usermode()
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -138,8 +138,6 @@ __visible unsigned long xen_read_cr2_dir
+ /* 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);