Skip to content

Commit 3f0116c

Browse files
author
Ingo Molnar
committed
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. Reported-and-tested-by: Fengguang Wu <[email protected]> Reported-by: Oleg Nesterov <[email protected]> Reported-by: Peter Zijlstra <[email protected]> Suggested-by: Jakub Jelinek <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Andrew Morton <[email protected]> Cc: <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 2fe80d3 commit 3f0116c

File tree

9 files changed

+26
-11
lines changed

9 files changed

+26
-11
lines changed

arch/arm/include/asm/jump_label.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit)
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)
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)
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
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)
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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,21 @@
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

0 commit comments

Comments
 (0)