]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Feb 2024 18:44:23 +0000 (19:44 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Feb 2024 18:44:23 +0000 (19:44 +0100)
added patches:
series
update-workarounds-for-gcc-asm-goto-issue.patch
work-around-gcc-bugs-with-asm-goto-with-outputs.patch

queue-6.6/series [new file with mode: 0644]
queue-6.6/update-workarounds-for-gcc-asm-goto-issue.patch [new file with mode: 0644]
queue-6.6/work-around-gcc-bugs-with-asm-goto-with-outputs.patch [new file with mode: 0644]

diff --git a/queue-6.6/series b/queue-6.6/series
new file mode 100644 (file)
index 0000000..b8ea1fc
--- /dev/null
@@ -0,0 +1,2 @@
+work-around-gcc-bugs-with-asm-goto-with-outputs.patch
+update-workarounds-for-gcc-asm-goto-issue.patch
diff --git a/queue-6.6/update-workarounds-for-gcc-asm-goto-issue.patch b/queue-6.6/update-workarounds-for-gcc-asm-goto-issue.patch
new file mode 100644 (file)
index 0000000..f276ceb
--- /dev/null
@@ -0,0 +1,118 @@
+From 68fb3ca0e408e00db1c3f8fccdfa19e274c033be Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 15 Feb 2024 11:14:33 -0800
+Subject: update workarounds for gcc "asm goto" issue
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 68fb3ca0e408e00db1c3f8fccdfa19e274c033be upstream.
+
+In commit 4356e9f841f7 ("work around gcc bugs with 'asm goto' with
+outputs") I did the gcc workaround unconditionally, because the cause of
+the bad code generation wasn't entirely clear.
+
+In the meantime, Jakub Jelinek debugged the issue, and has come up with
+a fix in gcc [2], which also got backported to the still maintained
+branches of gcc-11, gcc-12 and gcc-13.
+
+Note that while the fix technically wasn't in the original gcc-14
+branch, Jakub says:
+
+ "while it is true that no GCC 14 snapshots until today (or whenever the
+  fix will be committed) have the fix, for GCC trunk it is up to the
+  distros to use the latest snapshot if they use it at all and would
+  allow better testing of the kernel code without the workaround, so
+  that if there are other issues they won't be discovered years later.
+  Most userland code doesn't actually use asm goto with outputs..."
+
+so we will consider gcc-14 to be fixed - if somebody is using gcc
+snapshots of the gcc-14 before the fix, they should upgrade.
+
+Note that while the bug goes back to gcc-11, in practice other gcc
+changes seem to have effectively hidden it since gcc-12.1 as per a
+bisect by Jakub.  So even a gcc-14 snapshot without the fix likely
+doesn't show actual problems.
+
+Also, make the default 'asm_goto_output()' macro mark the asm as
+volatile by hand, because of an unrelated gcc issue [1] where it doesn't
+match the documented behavior ("asm goto is always volatile").
+
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103979 [1]
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921 [2]
+Link: https://lore.kernel.org/all/20240208220604.140859-1-seanjc@google.com/
+Requested-by: Jakub Jelinek <jakub@redhat.com>
+Cc: Uros Bizjak <ubizjak@gmail.com>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Andrew Pinski <quic_apinski@quicinc.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/compiler-gcc.h   |    7 ++++---
+ include/linux/compiler_types.h |    9 ++++++++-
+ init/Kconfig                   |    9 +++++++++
+ 3 files changed, 21 insertions(+), 4 deletions(-)
+
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -69,10 +69,9 @@
+ /*
+  * GCC 'asm goto' with outputs miscompiles certain code sequences:
+  *
+- *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110420
+- *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110422
++ *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
+  *
+- * Work it around via the same compiler barrier quirk that we used
++ * Work around it via the same compiler barrier quirk that we used
+  * to use for the old 'asm goto' workaround.
+  *
+  * Also, always mark such 'asm goto' statements as volatile: all
+@@ -82,8 +81,10 @@
+  *
+  *    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98619
+  */
++#ifdef CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND
+ #define asm_goto_output(x...) \
+       do { asm volatile goto(x); asm (""); } while (0)
++#endif
+ #if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
+ #define __HAVE_BUILTIN_BSWAP32__
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -352,8 +352,15 @@ struct ftrace_likely_data {
+ # define __realloc_size(x, ...)
+ #endif
++/*
++ * Some versions of gcc do not mark 'asm goto' volatile:
++ *
++ *  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103979
++ *
++ * We do it here by hand, because it doesn't hurt.
++ */
+ #ifndef asm_goto_output
+-#define asm_goto_output(x...) asm goto(x)
++#define asm_goto_output(x...) asm volatile goto(x)
+ #endif
+ #ifdef CONFIG_CC_HAS_ASM_INLINE
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -89,6 +89,15 @@ config CC_HAS_ASM_GOTO_TIED_OUTPUT
+       # Detect buggy gcc and clang, fixed in gcc-11 clang-14.
+       def_bool $(success,echo 'int foo(int *x) { asm goto (".long (%l[bar]) - .": "+m"(*x) ::: bar); return *x; bar: return 0; }' | $CC -x c - -c -o /dev/null)
++config GCC_ASM_GOTO_OUTPUT_WORKAROUND
++      bool
++      depends on CC_IS_GCC && CC_HAS_ASM_GOTO_OUTPUT
++      # Fixed in GCC 14, 13.3, 12.4 and 11.5
++      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
++      default y if GCC_VERSION < 110500
++      default y if GCC_VERSION >= 120000 && GCC_VERSION < 120400
++      default y if GCC_VERSION >= 130000 && GCC_VERSION < 130300
++
+ config TOOLS_SUPPORT_RELR
+       def_bool $(success,env "CC=$(CC)" "LD=$(LD)" "NM=$(NM)" "OBJCOPY=$(OBJCOPY)" $(srctree)/scripts/tools-support-relr.sh)
diff --git a/queue-6.6/work-around-gcc-bugs-with-asm-goto-with-outputs.patch b/queue-6.6/work-around-gcc-bugs-with-asm-goto-with-outputs.patch
new file mode 100644 (file)
index 0000000..88141d7
--- /dev/null
@@ -0,0 +1,734 @@
+From 4356e9f841f7fbb945521cef3577ba394c65f3fc Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 9 Feb 2024 12:39:31 -0800
+Subject: work around gcc bugs with 'asm goto' with outputs
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 4356e9f841f7fbb945521cef3577ba394c65f3fc upstream.
+
+We've had issues with gcc and 'asm goto' before, and we created a
+'asm_volatile_goto()' macro for that in the past: see commits
+3f0116c3238a ("compiler/gcc4: Add quirk for 'asm goto' miscompilation
+bug") and a9f180345f53 ("compiler/gcc4: Make quirk for
+asm_volatile_goto() unconditional").
+
+Then, much later, we ended up removing the workaround in commit
+43c249ea0b1e ("compiler-gcc.h: remove ancient workaround for gcc PR
+58670") because we no longer supported building the kernel with the
+affected gcc versions, but we left the macro uses around.
+
+Now, Sean Christopherson reports a new version of a very similar
+problem, which is fixed by re-applying that ancient workaround.  But the
+problem in question is limited to only the 'asm goto with outputs'
+cases, so instead of re-introducing the old workaround as-is, let's
+rename and limit the workaround to just that much less common case.
+
+It looks like there are at least two separate issues that all hit in
+this area:
+
+ (a) some versions of gcc don't mark the asm goto as 'volatile' when it
+     has outputs:
+
+        https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98619
+        https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110420
+
+     which is easy to work around by just adding the 'volatile' by hand.
+
+ (b) Internal compiler errors:
+
+        https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110422
+
+     which are worked around by adding the extra empty 'asm' as a
+     barrier, as in the original workaround.
+
+but the problem Sean sees may be a third thing since it involves bad
+code generation (not an ICE) even with the manually added 'volatile'.
+
+but the same old workaround works for this case, even if this feels a
+bit like voodoo programming and may only be hiding the issue.
+
+Reported-and-tested-by: Sean Christopherson <seanjc@google.com>
+Link: https://lore.kernel.org/all/20240208220604.140859-1-seanjc@google.com/
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Uros Bizjak <ubizjak@gmail.com>
+Cc: Jakub Jelinek <jakub@redhat.com>
+Cc: Andrew Pinski <quic_apinski@quicinc.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arc/include/asm/jump_label.h           |    4 ++--
+ arch/arm/include/asm/jump_label.h           |    4 ++--
+ arch/arm64/include/asm/alternative-macros.h |    4 ++--
+ arch/arm64/include/asm/jump_label.h         |    4 ++--
+ arch/csky/include/asm/jump_label.h          |    4 ++--
+ arch/loongarch/include/asm/jump_label.h     |    4 ++--
+ arch/mips/include/asm/jump_label.h          |    4 ++--
+ arch/parisc/include/asm/jump_label.h        |    4 ++--
+ arch/powerpc/include/asm/jump_label.h       |    4 ++--
+ arch/powerpc/include/asm/uaccess.h          |   12 ++++++------
+ arch/powerpc/kernel/irq_64.c                |    2 +-
+ arch/riscv/include/asm/hwcap.h              |    4 ++--
+ arch/riscv/include/asm/jump_label.h         |    4 ++--
+ arch/s390/include/asm/jump_label.h          |    4 ++--
+ arch/sparc/include/asm/jump_label.h         |    4 ++--
+ arch/um/include/asm/cpufeature.h            |    2 +-
+ arch/x86/include/asm/cpufeature.h           |    2 +-
+ arch/x86/include/asm/jump_label.h           |    6 +++---
+ arch/x86/include/asm/rmwcc.h                |    2 +-
+ arch/x86/include/asm/special_insns.h        |    2 +-
+ arch/x86/include/asm/uaccess.h              |   10 +++++-----
+ arch/x86/kvm/svm/svm_ops.h                  |    6 +++---
+ arch/x86/kvm/vmx/vmx.c                      |    4 ++--
+ arch/x86/kvm/vmx/vmx_ops.h                  |    6 +++---
+ arch/xtensa/include/asm/jump_label.h        |    4 ++--
+ include/linux/compiler-gcc.h                |   19 +++++++++++++++++++
+ include/linux/compiler_types.h              |    4 ++--
+ net/netfilter/nft_set_pipapo_avx2.c         |    2 +-
+ samples/bpf/asm_goto_workaround.h           |    8 ++++----
+ tools/arch/x86/include/asm/rmwcc.h          |    2 +-
+ tools/include/linux/compiler_types.h        |    4 ++--
+ 31 files changed, 84 insertions(+), 65 deletions(-)
+
+--- a/arch/arc/include/asm/jump_label.h
++++ b/arch/arc/include/asm/jump_label.h
+@@ -31,7 +31,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key,
+                                              bool branch)
+ {
+-      asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"   \n"
++      asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"            \n"
+                "1:                                                    \n"
+                "nop                                                   \n"
+                ".pushsection __jump_table, \"aw\"                     \n"
+@@ -47,7 +47,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key,
+                                                   bool branch)
+ {
+-      asm_volatile_goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"   \n"
++      asm goto(".balign "__stringify(JUMP_LABEL_NOP_SIZE)"            \n"
+                "1:                                                    \n"
+                "b %l[l_yes]                                           \n"
+                ".pushsection __jump_table, \"aw\"                     \n"
+--- a/arch/arm/include/asm/jump_label.h
++++ b/arch/arm/include/asm/jump_label.h
+@@ -11,7 +11,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                WASM(nop) "\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".word 1b, %l[l_yes], %c0\n\t"
+@@ -25,7 +25,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                WASM(b) " %l[l_yes]\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".word 1b, %l[l_yes], %c0\n\t"
+--- a/arch/arm64/include/asm/alternative-macros.h
++++ b/arch/arm64/include/asm/alternative-macros.h
+@@ -229,7 +229,7 @@ alternative_has_cap_likely(const unsigne
+       compiletime_assert(cpucap < ARM64_NCAPS,
+                          "cpucap must be < ARM64_NCAPS");
+-      asm_volatile_goto(
++      asm goto(
+       ALTERNATIVE_CB("b       %l[l_no]", %[cpucap], alt_cb_patch_nops)
+       :
+       : [cpucap] "i" (cpucap)
+@@ -247,7 +247,7 @@ alternative_has_cap_unlikely(const unsig
+       compiletime_assert(cpucap < ARM64_NCAPS,
+                          "cpucap must be < ARM64_NCAPS");
+-      asm_volatile_goto(
++      asm goto(
+       ALTERNATIVE("nop", "b   %l[l_yes]", %[cpucap])
+       :
+       : [cpucap] "i" (cpucap)
+--- a/arch/arm64/include/asm/jump_label.h
++++ b/arch/arm64/include/asm/jump_label.h
+@@ -18,7 +18,7 @@
+ static __always_inline bool arch_static_branch(struct static_key * const key,
+                                              const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     nop                                     \n\t"
+                "      .pushsection    __jump_table, \"aw\"    \n\t"
+                "      .align          3                       \n\t"
+@@ -35,7 +35,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key * const key,
+                                                   const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     b               %l[l_yes]               \n\t"
+                "      .pushsection    __jump_table, \"aw\"    \n\t"
+                "      .align          3                       \n\t"
+--- a/arch/csky/include/asm/jump_label.h
++++ b/arch/csky/include/asm/jump_label.h
+@@ -12,7 +12,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key,
+                                              bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     nop32                                   \n"
+               "       .pushsection    __jump_table, \"aw\"    \n"
+               "       .align          2                       \n"
+@@ -29,7 +29,7 @@ label:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key,
+                                                   bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     bsr32           %l[label]               \n"
+               "       .pushsection    __jump_table, \"aw\"    \n"
+               "       .align          2                       \n"
+--- a/arch/loongarch/include/asm/jump_label.h
++++ b/arch/loongarch/include/asm/jump_label.h
+@@ -22,7 +22,7 @@
+ static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     nop                     \n\t"
+               JUMP_TABLE_ENTRY
+               :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+@@ -35,7 +35,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "1:     b       %l[l_yes]       \n\t"
+               JUMP_TABLE_ENTRY
+               :  :  "i"(&((char *)key)[branch]) :  : l_yes);
+--- a/arch/mips/include/asm/jump_label.h
++++ b/arch/mips/include/asm/jump_label.h
+@@ -36,7 +36,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\t" B_INSN " 2f\n\t"
++      asm goto("1:\t" B_INSN " 2f\n\t"
+               "2:\t.insn\n\t"
+               ".pushsection __jump_table,  \"aw\"\n\t"
+               WORD_INSN " 1b, %l[l_yes], %0\n\t"
+@@ -50,7 +50,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\t" J_INSN " %l[l_yes]\n\t"
++      asm goto("1:\t" J_INSN " %l[l_yes]\n\t"
+               ".pushsection __jump_table,  \"aw\"\n\t"
+               WORD_INSN " 1b, %l[l_yes], %0\n\t"
+               ".popsection\n\t"
+--- a/arch/parisc/include/asm/jump_label.h
++++ b/arch/parisc/include/asm/jump_label.h
+@@ -12,7 +12,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "nop\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".align %1\n\t"
+@@ -29,7 +29,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "b,n %l[l_yes]\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".align %1\n\t"
+--- a/arch/powerpc/include/asm/jump_label.h
++++ b/arch/powerpc/include/asm/jump_label.h
+@@ -17,7 +17,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "nop # arch_static_branch\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".long 1b - ., %l[l_yes] - .\n\t"
+@@ -32,7 +32,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "b %l[l_yes] # arch_static_branch_jump\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".long 1b - ., %l[l_yes] - .\n\t"
+--- a/arch/powerpc/include/asm/uaccess.h
++++ b/arch/powerpc/include/asm/uaccess.h
+@@ -74,7 +74,7 @@ __pu_failed:                                                 \
+ /* -mprefixed can generate offsets beyond range, fall back hack */
+ #ifdef CONFIG_PPC_KERNEL_PREFIXED
+ #define __put_user_asm_goto(x, addr, label, op)                       \
+-      asm_volatile_goto(                                      \
++      asm goto(                                       \
+               "1:     " op " %0,0(%1) # put_user\n"           \
+               EX_TABLE(1b, %l2)                               \
+               :                                               \
+@@ -83,7 +83,7 @@ __pu_failed:                                                 \
+               : label)
+ #else
+ #define __put_user_asm_goto(x, addr, label, op)                       \
+-      asm_volatile_goto(                                      \
++      asm goto(                                       \
+               "1:     " op "%U1%X1 %0,%1      # put_user\n"   \
+               EX_TABLE(1b, %l2)                               \
+               :                                               \
+@@ -97,7 +97,7 @@ __pu_failed:                                                 \
+       __put_user_asm_goto(x, ptr, label, "std")
+ #else /* __powerpc64__ */
+ #define __put_user_asm2_goto(x, addr, label)                  \
+-      asm_volatile_goto(                                      \
++      asm goto(                                       \
+               "1:     stw%X1 %0, %1\n"                        \
+               "2:     stw%X1 %L0, %L1\n"                      \
+               EX_TABLE(1b, %l2)                               \
+@@ -146,7 +146,7 @@ do {                                                               \
+ /* -mprefixed can generate offsets beyond range, fall back hack */
+ #ifdef CONFIG_PPC_KERNEL_PREFIXED
+ #define __get_user_asm_goto(x, addr, label, op)                       \
+-      asm_volatile_goto(                                      \
++      asm_goto_output(                                        \
+               "1:     "op" %0,0(%1)   # get_user\n"           \
+               EX_TABLE(1b, %l2)                               \
+               : "=r" (x)                                      \
+@@ -155,7 +155,7 @@ do {                                                               \
+               : label)
+ #else
+ #define __get_user_asm_goto(x, addr, label, op)                       \
+-      asm_volatile_goto(                                      \
++      asm_goto_output(                                        \
+               "1:     "op"%U1%X1 %0, %1       # get_user\n"   \
+               EX_TABLE(1b, %l2)                               \
+               : "=r" (x)                                      \
+@@ -169,7 +169,7 @@ do {                                                               \
+       __get_user_asm_goto(x, addr, label, "ld")
+ #else /* __powerpc64__ */
+ #define __get_user_asm2_goto(x, addr, label)                  \
+-      asm_volatile_goto(                                      \
++      asm_goto_output(                                        \
+               "1:     lwz%X1 %0, %1\n"                        \
+               "2:     lwz%X1 %L0, %L1\n"                      \
+               EX_TABLE(1b, %l2)                               \
+--- a/arch/powerpc/kernel/irq_64.c
++++ b/arch/powerpc/kernel/irq_64.c
+@@ -230,7 +230,7 @@ again:
+        * This allows interrupts to be unmasked without hard disabling, and
+        * also without new hard interrupts coming in ahead of pending ones.
+        */
+-      asm_volatile_goto(
++      asm goto(
+ "1:                                   \n"
+ "             lbz     9,%0(13)        \n"
+ "             cmpwi   9,0             \n"
+--- a/arch/riscv/include/asm/hwcap.h
++++ b/arch/riscv/include/asm/hwcap.h
+@@ -98,7 +98,7 @@ riscv_has_extension_likely(const unsigne
+                          "ext must be < RISCV_ISA_EXT_MAX");
+       if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+-              asm_volatile_goto(
++              asm goto(
+               ALTERNATIVE("j  %l[l_no]", "nop", 0, %[ext], 1)
+               :
+               : [ext] "i" (ext)
+@@ -121,7 +121,7 @@ riscv_has_extension_unlikely(const unsig
+                          "ext must be < RISCV_ISA_EXT_MAX");
+       if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
+-              asm_volatile_goto(
++              asm goto(
+               ALTERNATIVE("nop", "j   %l[l_yes]", 0, %[ext], 1)
+               :
+               : [ext] "i" (ext)
+--- a/arch/riscv/include/asm/jump_label.h
++++ b/arch/riscv/include/asm/jump_label.h
+@@ -17,7 +17,7 @@
+ static __always_inline bool arch_static_branch(struct static_key * const key,
+                                              const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "       .align          2                       \n\t"
+               "       .option push                            \n\t"
+               "       .option norelax                         \n\t"
+@@ -39,7 +39,7 @@ label:
+ static __always_inline bool arch_static_branch_jump(struct static_key * const key,
+                                                   const bool branch)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               "       .align          2                       \n\t"
+               "       .option push                            \n\t"
+               "       .option norelax                         \n\t"
+--- a/arch/s390/include/asm/jump_label.h
++++ b/arch/s390/include/asm/jump_label.h
+@@ -25,7 +25,7 @@
+  */
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("0:   brcl 0,%l[label]\n"
++      asm goto("0:    brcl 0,%l[label]\n"
+                         ".pushsection __jump_table,\"aw\"\n"
+                         ".balign      8\n"
+                         ".long        0b-.,%l[label]-.\n"
+@@ -39,7 +39,7 @@ label:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("0:   brcl 15,%l[label]\n"
++      asm goto("0:    brcl 15,%l[label]\n"
+                         ".pushsection __jump_table,\"aw\"\n"
+                         ".balign      8\n"
+                         ".long        0b-.,%l[label]-.\n"
+--- a/arch/sparc/include/asm/jump_label.h
++++ b/arch/sparc/include/asm/jump_label.h
+@@ -10,7 +10,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "nop\n\t"
+                "nop\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+@@ -26,7 +26,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                "b %l[l_yes]\n\t"
+                "nop\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+--- a/arch/um/include/asm/cpufeature.h
++++ b/arch/um/include/asm/cpufeature.h
+@@ -75,7 +75,7 @@ extern void setup_clear_cpu_cap(unsigned
+  */
+ static __always_inline bool _static_cpu_has(u16 bit)
+ {
+-      asm_volatile_goto("1: jmp 6f\n"
++      asm goto("1: jmp 6f\n"
+                "2:\n"
+                ".skip -(((5f-4f) - (2b-1b)) > 0) * "
+                        "((5f-4f) - (2b-1b)),0x90\n"
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -168,7 +168,7 @@ extern void clear_cpu_cap(struct cpuinfo
+  */
+ static __always_inline bool _static_cpu_has(u16 bit)
+ {
+-      asm_volatile_goto(
++      asm goto(
+               ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]")
+               ".pushsection .altinstr_aux,\"ax\"\n"
+               "6:\n"
+--- a/arch/x86/include/asm/jump_label.h
++++ b/arch/x86/include/asm/jump_label.h
+@@ -24,7 +24,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+ {
+-      asm_volatile_goto("1:"
++      asm goto("1:"
+               "jmp %l[l_yes] # objtool NOPs this \n\t"
+               JUMP_TABLE_ENTRY
+               : :  "i" (key), "i" (2 | branch) : : l_yes);
+@@ -38,7 +38,7 @@ l_yes:
+ static __always_inline bool arch_static_branch(struct static_key * const key, const bool branch)
+ {
+-      asm_volatile_goto("1:"
++      asm goto("1:"
+               ".byte " __stringify(BYTES_NOP5) "\n\t"
+               JUMP_TABLE_ENTRY
+               : :  "i" (key), "i" (branch) : : l_yes);
+@@ -52,7 +52,7 @@ l_yes:
+ static __always_inline bool arch_static_branch_jump(struct static_key * const key, const bool branch)
+ {
+-      asm_volatile_goto("1:"
++      asm goto("1:"
+               "jmp %l[l_yes]\n\t"
+               JUMP_TABLE_ENTRY
+               : :  "i" (key), "i" (branch) : : l_yes);
+--- a/arch/x86/include/asm/rmwcc.h
++++ b/arch/x86/include/asm/rmwcc.h
+@@ -13,7 +13,7 @@
+ #define __GEN_RMWcc(fullop, _var, cc, clobbers, ...)                  \
+ ({                                                                    \
+       bool c = false;                                                 \
+-      asm_volatile_goto (fullop "; j" #cc " %l[cc_label]"             \
++      asm goto (fullop "; j" #cc " %l[cc_label]"              \
+                       : : [var] "m" (_var), ## __VA_ARGS__            \
+                       : clobbers : cc_label);                         \
+       if (0) {                                                        \
+--- a/arch/x86/include/asm/special_insns.h
++++ b/arch/x86/include/asm/special_insns.h
+@@ -205,7 +205,7 @@ static inline void clwb(volatile void *_
+ #ifdef CONFIG_X86_USER_SHADOW_STACK
+ static inline int write_user_shstk_64(u64 __user *addr, u64 val)
+ {
+-      asm_volatile_goto("1: wrussq %[val], (%[addr])\n"
++      asm goto("1: wrussq %[val], (%[addr])\n"
+                         _ASM_EXTABLE(1b, %l[fail])
+                         :: [addr] "r" (addr), [val] "r" (val)
+                         :: fail);
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -133,7 +133,7 @@ extern int __get_user_bad(void);
+ #ifdef CONFIG_X86_32
+ #define __put_user_goto_u64(x, addr, label)                   \
+-      asm_volatile_goto("\n"                                  \
++      asm goto("\n"                                   \
+                    "1:        movl %%eax,0(%1)\n"             \
+                    "2:        movl %%edx,4(%1)\n"             \
+                    _ASM_EXTABLE_UA(1b, %l2)                   \
+@@ -295,7 +295,7 @@ do {                                                                       \
+ } while (0)
+ #define __get_user_asm(x, addr, itype, ltype, label)                  \
+-      asm_volatile_goto("\n"                                          \
++      asm_goto_output("\n"                                            \
+                    "1:        mov"itype" %[umem],%[output]\n"         \
+                    _ASM_EXTABLE_UA(1b, %l2)                           \
+                    : [output] ltype(x)                                \
+@@ -375,7 +375,7 @@ do {                                                                       \
+       __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
+       __typeof__(*(_ptr)) __old = *_old;                              \
+       __typeof__(*(_ptr)) __new = (_new);                             \
+-      asm_volatile_goto("\n"                                          \
++      asm_goto_output("\n"                                            \
+                    "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
+                    _ASM_EXTABLE_UA(1b, %l[label])                     \
+                    : CC_OUT(z) (success),                             \
+@@ -394,7 +394,7 @@ do {                                                                       \
+       __typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);              \
+       __typeof__(*(_ptr)) __old = *_old;                              \
+       __typeof__(*(_ptr)) __new = (_new);                             \
+-      asm_volatile_goto("\n"                                          \
++      asm_goto_output("\n"                                            \
+                    "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"             \
+                    _ASM_EXTABLE_UA(1b, %l[label])                     \
+                    : CC_OUT(z) (success),                             \
+@@ -477,7 +477,7 @@ struct __large_struct { unsigned long bu
+  * aliasing issues.
+  */
+ #define __put_user_goto(x, addr, itype, ltype, label)                 \
+-      asm_volatile_goto("\n"                                          \
++      asm goto("\n"                                                   \
+               "1:     mov"itype" %0,%1\n"                             \
+               _ASM_EXTABLE_UA(1b, %l2)                                \
+               : : ltype(x), "m" (__m(addr))                           \
+--- a/arch/x86/kvm/svm/svm_ops.h
++++ b/arch/x86/kvm/svm/svm_ops.h
+@@ -8,7 +8,7 @@
+ #define svm_asm(insn, clobber...)                             \
+ do {                                                          \
+-      asm_volatile_goto("1: " __stringify(insn) "\n\t"        \
++      asm goto("1: " __stringify(insn) "\n\t" \
+                         _ASM_EXTABLE(1b, %l[fault])           \
+                         ::: clobber : fault);                 \
+       return;                                                 \
+@@ -18,7 +18,7 @@ fault:                                                               \
+ #define svm_asm1(insn, op1, clobber...)                               \
+ do {                                                          \
+-      asm_volatile_goto("1: "  __stringify(insn) " %0\n\t"    \
++      asm goto("1: "  __stringify(insn) " %0\n\t"     \
+                         _ASM_EXTABLE(1b, %l[fault])           \
+                         :: op1 : clobber : fault);            \
+       return;                                                 \
+@@ -28,7 +28,7 @@ fault:                                                               \
+ #define svm_asm2(insn, op1, op2, clobber...)                          \
+ do {                                                                  \
+-      asm_volatile_goto("1: "  __stringify(insn) " %1, %0\n\t"        \
++      asm goto("1: "  __stringify(insn) " %1, %0\n\t" \
+                         _ASM_EXTABLE(1b, %l[fault])                   \
+                         :: op1, op2 : clobber : fault);               \
+       return;                                                         \
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -745,7 +745,7 @@ static int vmx_set_guest_uret_msr(struct
+  */
+ static int kvm_cpu_vmxoff(void)
+ {
+-      asm_volatile_goto("1: vmxoff\n\t"
++      asm goto("1: vmxoff\n\t"
+                         _ASM_EXTABLE(1b, %l[fault])
+                         ::: "cc", "memory" : fault);
+@@ -2789,7 +2789,7 @@ static int kvm_cpu_vmxon(u64 vmxon_point
+       cr4_set_bits(X86_CR4_VMXE);
+-      asm_volatile_goto("1: vmxon %[vmxon_pointer]\n\t"
++      asm goto("1: vmxon %[vmxon_pointer]\n\t"
+                         _ASM_EXTABLE(1b, %l[fault])
+                         : : [vmxon_pointer] "m"(vmxon_pointer)
+                         : : fault);
+--- a/arch/x86/kvm/vmx/vmx_ops.h
++++ b/arch/x86/kvm/vmx/vmx_ops.h
+@@ -94,7 +94,7 @@ static __always_inline unsigned long __v
+ #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+-      asm_volatile_goto("1: vmread %[field], %[output]\n\t"
++      asm_goto_output("1: vmread %[field], %[output]\n\t"
+                         "jna %l[do_fail]\n\t"
+                         _ASM_EXTABLE(1b, %l[do_exception])
+@@ -188,7 +188,7 @@ static __always_inline unsigned long vmc
+ #define vmx_asm1(insn, op1, error_args...)                            \
+ do {                                                                  \
+-      asm_volatile_goto("1: " __stringify(insn) " %0\n\t"             \
++      asm goto("1: " __stringify(insn) " %0\n\t"                      \
+                         ".byte 0x2e\n\t" /* branch not taken hint */  \
+                         "jna %l[error]\n\t"                           \
+                         _ASM_EXTABLE(1b, %l[fault])                   \
+@@ -205,7 +205,7 @@ fault:                                                                     \
+ #define vmx_asm2(insn, op1, op2, error_args...)                               \
+ do {                                                                  \
+-      asm_volatile_goto("1: "  __stringify(insn) " %1, %0\n\t"        \
++      asm goto("1: "  __stringify(insn) " %1, %0\n\t"                 \
+                         ".byte 0x2e\n\t" /* branch not taken hint */  \
+                         "jna %l[error]\n\t"                           \
+                         _ASM_EXTABLE(1b, %l[fault])                   \
+--- a/arch/xtensa/include/asm/jump_label.h
++++ b/arch/xtensa/include/asm/jump_label.h
+@@ -13,7 +13,7 @@
+ static __always_inline bool arch_static_branch(struct static_key *key,
+                                              bool branch)
+ {
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                         "_nop\n\t"
+                         ".pushsection __jump_table,  \"aw\"\n\t"
+                         ".word 1b, %l[l_yes], %c0\n\t"
+@@ -38,7 +38,7 @@ static __always_inline bool arch_static_
+        * make it reachable and wrap both into a no-transform block
+        * to avoid any assembler interference with this.
+        */
+-      asm_volatile_goto("1:\n\t"
++      asm goto("1:\n\t"
+                         ".begin no-transform\n\t"
+                         "_j %l[l_yes]\n\t"
+                         "2:\n\t"
+--- a/include/linux/compiler-gcc.h
++++ b/include/linux/compiler-gcc.h
+@@ -66,6 +66,25 @@
+               __builtin_unreachable();        \
+       } while (0)
++/*
++ * GCC 'asm goto' with outputs miscompiles certain code sequences:
++ *
++ *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110420
++ *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110422
++ *
++ * Work it around via the same compiler barrier quirk that we used
++ * to use for the old 'asm goto' workaround.
++ *
++ * Also, always mark such 'asm goto' statements as volatile: all
++ * asm goto statements are supposed to be volatile as per the
++ * documentation, but some versions of gcc didn't actually do
++ * that for asms with outputs:
++ *
++ *    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98619
++ */
++#define asm_goto_output(x...) \
++      do { asm volatile goto(x); asm (""); } while (0)
++
+ #if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP)
+ #define __HAVE_BUILTIN_BSWAP32__
+ #define __HAVE_BUILTIN_BSWAP64__
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -352,8 +352,8 @@ struct ftrace_likely_data {
+ # define __realloc_size(x, ...)
+ #endif
+-#ifndef asm_volatile_goto
+-#define asm_volatile_goto(x...) asm goto(x)
++#ifndef asm_goto_output
++#define asm_goto_output(x...) asm goto(x)
+ #endif
+ #ifdef CONFIG_CC_HAS_ASM_INLINE
+--- a/net/netfilter/nft_set_pipapo_avx2.c
++++ b/net/netfilter/nft_set_pipapo_avx2.c
+@@ -57,7 +57,7 @@
+ /* Jump to label if @reg is zero */
+ #define NFT_PIPAPO_AVX2_NOMATCH_GOTO(reg, label)                      \
+-      asm_volatile_goto("vptest %%ymm" #reg ", %%ymm" #reg ";"        \
++      asm goto("vptest %%ymm" #reg ", %%ymm" #reg ";" \
+                         "je %l[" #label "]" : : : : label)
+ /* Store 256 bits from YMM register into memory. Contrary to bucket load
+--- a/samples/bpf/asm_goto_workaround.h
++++ b/samples/bpf/asm_goto_workaround.h
+@@ -4,14 +4,14 @@
+ #define __ASM_GOTO_WORKAROUND_H
+ /*
+- * This will bring in asm_volatile_goto and asm_inline macro definitions
++ * This will bring in asm_goto_output and asm_inline macro definitions
+  * if enabled by compiler and config options.
+  */
+ #include <linux/types.h>
+-#ifdef asm_volatile_goto
+-#undef asm_volatile_goto
+-#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto")
++#ifdef asm_goto_output
++#undef asm_goto_output
++#define asm_goto_output(x...) asm volatile("invalid use of asm_goto_output")
+ #endif
+ /*
+--- a/tools/arch/x86/include/asm/rmwcc.h
++++ b/tools/arch/x86/include/asm/rmwcc.h
+@@ -4,7 +4,7 @@
+ #define __GEN_RMWcc(fullop, var, cc, ...)                             \
+ do {                                                                  \
+-      asm_volatile_goto (fullop "; j" cc " %l[cc_label]"              \
++      asm goto (fullop "; j" cc " %l[cc_label]"               \
+                       : : "m" (var), ## __VA_ARGS__                   \
+                       : "memory" : cc_label);                         \
+       return 0;                                                       \
+--- a/tools/include/linux/compiler_types.h
++++ b/tools/include/linux/compiler_types.h
+@@ -36,8 +36,8 @@
+ #include <linux/compiler-gcc.h>
+ #endif
+-#ifndef asm_volatile_goto
+-#define asm_volatile_goto(x...) asm goto(x)
++#ifndef asm_goto_output
++#define asm_goto_output(x...) asm goto(x)
+ #endif
+ #endif /* __LINUX_COMPILER_TYPES_H */