From: Greg Kroah-Hartman Date: Thu, 23 May 2024 06:34:30 +0000 (+0200) Subject: 5.10-stable patches X-Git-Tag: v4.19.315~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b8e2092cafeaff8737b43e0ed39dbacf367b1594;p=thirdparty%2Fkernel%2Fstable-queue.git 5.10-stable patches added patches: x86-xen-drop-usergs_sysret64-paravirt-call.patch --- diff --git a/queue-5.10/series b/queue-5.10/series index 37e0beb553d..ca44d55c23e 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 00000000000..2169ad160f4 --- /dev/null +++ b/queue-5.10/x86-xen-drop-usergs_sysret64-paravirt-call.patch @@ -0,0 +1,275 @@ +From afd30525a659ac0ae0904f0cb4a2ca75522c3123 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Wed, 20 Jan 2021 14:55:45 +0100 +Subject: x86/xen: Drop USERGS_SYSRET64 paravirt call + +From: Juergen Gross + +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 + 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 +Signed-off-by: Borislav Petkov +Signed-off-by: Pawan Gupta +Link: https://lkml.kernel.org/r/20210120135555.32594-6-jgross@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + 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); +