History

compiler/gcc4: Add quirk for 'asm goto' miscompilation bug

Fengguang Wu, Oleg Nesterov and Peter Zijlstra tracked down a kernel crash to a GCC bug: GCC miscompiles certain 'asm goto' constructs, as outlined here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 Implement a workaround suggested by Jakub Jelinek.

Ingo Molnar committed 13 years ago

Commit 3f0116c1 parent 2fe80d39 files · +26 −11Browse files

Unified · Split

9 files
  1. arch/arm/include/asm/jump_label.h +1 −1
  2. arch/mips/include/asm/jump_label.h +1 −1
  3. arch/powerpc/include/asm/jump_label.h +1 −1
  4. arch/s390/include/asm/jump_label.h +1 −1
  5. arch/sparc/include/asm/jump_label.h +1 −1
  6. arch/x86/include/asm/cpufeature.h +3 −3
  7. arch/x86/include/asm/jump_label.h +1 −1
  8. arch/x86/include/asm/mutex_64.h +2 −2
  9. include/linux/compiler-gcc4.h +15 −0
arch/arm/include/asm/jump_label.h+1−1
@@ -16,7 +16,7 @@ · 15 unmodified lines
1616
1717 static __always_inline bool arch_static_branch(struct static_key *key)
1818 {
19− asm goto("1:\n\t"
19+ asm_volatile_goto("1:\n\t"
2020 JUMP_LABEL_NOP "\n\t"
2121 ".pushsection __jump_table, \"aw\"\n\t"
2222 ".word 1b, %l[l_yes], %c0\n\t"
arch/mips/include/asm/jump_label.h+1−1
@@ -22,7 +22,7 @@ · 21 unmodified lines
2222
2323 static __always_inline bool arch_static_branch(struct static_key *key)
2424 {
25− asm goto("1:\tnop\n\t"
25+ asm_volatile_goto("1:\tnop\n\t"
2626 "nop\n\t"
2727 ".pushsection __jump_table, \"aw\"\n\t"
2828 WORD_INSN " 1b, %l[l_yes], %0\n\t"
arch/powerpc/include/asm/jump_label.h+1−1
@@ -19,7 +19,7 @@ · 18 unmodified lines
1919
2020 static __always_inline bool arch_static_branch(struct static_key *key)
2121 {
22− asm goto("1:\n\t"
22+ asm_volatile_goto("1:\n\t"
2323 "nop\n\t"
2424 ".pushsection __jump_table, \"aw\"\n\t"
2525 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
arch/s390/include/asm/jump_label.h+1−1
@@ -15,7 +15,7 @@ · 14 unmodified lines
1515
1616 static __always_inline bool arch_static_branch(struct static_key *key)
1717 {
18− asm goto("0: brcl 0,0\n"
18+ asm_volatile_goto("0: brcl 0,0\n"
1919 ".pushsection __jump_table, \"aw\"\n"
2020 ASM_ALIGN "\n"
2121 ASM_PTR " 0b, %l[label], %0\n"
arch/sparc/include/asm/jump_label.h+1−1
@@ -9,7 +9,7 @@ · 8 unmodified lines
99
1010 static __always_inline bool arch_static_branch(struct static_key *key)
1111 {
12− asm goto("1:\n\t"
12+ asm_volatile_goto("1:\n\t"
1313 "nop\n\t"
1414 "nop\n\t"
1515 ".pushsection __jump_table, \"aw\"\n\t"
arch/x86/include/asm/cpufeature.h+3−3
@@ -374,7 +374,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) · 373 unmodified lines
374374 * Catch too early usage of this before alternatives
375375 * have run.
376376 */
377− asm goto("1: jmp %l[t_warn]\n"
377+ asm_volatile_goto("1: jmp %l[t_warn]\n"
378378 "2:\n"
379379 ".section .altinstructions,\"a\"\n"
380380 " .long 1b - .\n"
@@ -388,7 +388,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) · 7 unmodified lines
388388
389389 #endif
390390
391− asm goto("1: jmp %l[t_no]\n"
391+ asm_volatile_goto("1: jmp %l[t_no]\n"
392392 "2:\n"
393393 ".section .altinstructions,\"a\"\n"
394394 " .long 1b - .\n"
@@ -453,7 +453,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) · 58 unmodified lines
453453 * have. Thus, we force the jump to the widest, 4-byte, signed relative
454454 * offset even though the last would often fit in less bytes.
455455 */
456− asm goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n"
456+ asm_volatile_goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n"
457457 "2:\n"
458458 ".section .altinstructions,\"a\"\n"
459459 " .long 1b - .\n" /* src offset */
arch/x86/include/asm/jump_label.h+1−1
@@ -18,7 +18,7 @@ · 17 unmodified lines
1818
1919 static __always_inline bool arch_static_branch(struct static_key *key)
2020 {
21− asm goto("1:"
21+ asm_volatile_goto("1:"
2222 ".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
2323 ".pushsection __jump_table, \"aw\" \n\t"
2424 _ASM_ALIGN "\n\t"
arch/x86/include/asm/mutex_64.h+2−2
@@ -20,7 +20,7 @@ · 19 unmodified lines
2020 static inline void __mutex_fastpath_lock(atomic_t *v,
2121 void (*fail_fn)(atomic_t *))
2222 {
23− asm volatile goto(LOCK_PREFIX " decl %0\n"
23+ asm_volatile_goto(LOCK_PREFIX " decl %0\n"
2424 " jns %l[exit]\n"
2525 : : "m" (v->counter)
2626 : "memory", "cc"
@@ -75,7 +75,7 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count) · 48 unmodified lines
7575 static inline void __mutex_fastpath_unlock(atomic_t *v,
7676 void (*fail_fn)(atomic_t *))
7777 {
78− asm volatile goto(LOCK_PREFIX " incl %0\n"
78+ asm_volatile_goto(LOCK_PREFIX " incl %0\n"
7979 " jg %l[exit]\n"
8080 : : "m" (v->counter)
8181 : "memory", "cc"
include/linux/compiler-gcc4.h+15−0
@@ -65,6 +65,21 @@ · 64 unmodified lines
6565 #define __visible __attribute__((externally_visible))
6666 #endif
6767
68+/*
69+ * GCC 'asm goto' miscompiles certain code sequences:
70+ *
71+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670
72+ *
73+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek.
74+ * Fixed in GCC 4.8.2 and later versions.
75+ *
76+ * (asm goto is automatically volatile - the naming reflects this.)
77+ */
78+#if GCC_VERSION <= 40801
79+# define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
80+#else
81+# define asm_volatile_goto(x...) do { asm goto(x); } while (0)
82+#endif
6883
6984 #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
7085 #if GCC_VERSION >= 40400

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t