Skip to content

Commit 7322dd7

Browse files
arndbtorvalds
authored andcommitted
byteswap: try to avoid __builtin_constant_p gcc bug
This is another attempt to avoid a regression in wwn_to_u64() after that started using get_unaligned_be64(), which in turn ran into a bug on gcc-4.9 through 6.1. The regression got introduced due to the combination of two separate workarounds (commits e3bde95: "include/linux/unaligned: force inlining of byteswap operations" and ef3fb24: "scsi: fc: use get/put_unaligned64 for wwn access") that each try to sidestep distinct problems with gcc behavior (code growth and increased stack usage). Unfortunately after both have been applied, a more serious gcc bug has been uncovered, leading to incorrect object code that discards part of a function and causes undefined behavior. As part of this problem is how __builtin_constant_p gets evaluated on an argument passed by reference into an inline function, this avoids the use of __builtin_constant_p() for all architectures that set CONFIG_ARCH_USE_BUILTIN_BSWAP. Most architectures do not set ARCH_SUPPORTS_OPTIMIZED_INLINING, which means they probably do not suffer from the problem in the qla2xxx driver, but they might still run into it elsewhere. Both of the original workarounds were only merged in the 4.6 kernel, and the bug that is fixed by this patch should only appear if both are there, so we probably don't need to backport the fix. On the other hand, it works by simplifying the code path and should not have any negative effects. [arnd@arndb.de: fix older gcc warnings] (http://lkml.kernel.org/r/12243652.bxSxEgjgfk@wuerfel) Link: https://lkml.org/lkml/headers/2016/4/12/1103 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66122 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70232 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646 Fixes: e3bde95 ("include/linux/unaligned: force inlining of byteswap operations") Fixes: ef3fb24 ("scsi: fc: use get/put_unaligned64 for wwn access") Link: http://lkml.kernel.org/r/1780465.XdtPJpi8Tt@wuerfel Signed-off-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Tested-by: Josh Poimboeuf <jpoimboe@redhat.com> # on gcc-5.3 Tested-by: Quinn Tran <quinn.tran@qlogic.com> Cc: Martin Jambor <mjambor@suse.cz> Cc: "Martin K. Petersen" <martin.petersen@oracle.com> Cc: James Bottomley <James.Bottomley@hansenpartnership.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Thomas Graf <tgraf@suug.ch> Cc: Peter Zijlstra <peterz@infradead.org> Cc: David Rientjes <rientjes@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Himanshu Madhani <himanshu.madhani@qlogic.com> Cc: Jan Hubicka <hubicka@ucw.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 7c31190 commit 7322dd7

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

include/uapi/linux/swab.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@
4545

4646
static inline __attribute_const__ __u16 __fswab16(__u16 val)
4747
{
48-
#ifdef __HAVE_BUILTIN_BSWAP16__
49-
return __builtin_bswap16(val);
50-
#elif defined (__arch_swab16)
48+
#if defined (__arch_swab16)
5149
return __arch_swab16(val);
5250
#else
5351
return ___constant_swab16(val);
@@ -56,9 +54,7 @@ static inline __attribute_const__ __u16 __fswab16(__u16 val)
5654

5755
static inline __attribute_const__ __u32 __fswab32(__u32 val)
5856
{
59-
#ifdef __HAVE_BUILTIN_BSWAP32__
60-
return __builtin_bswap32(val);
61-
#elif defined(__arch_swab32)
57+
#if defined(__arch_swab32)
6258
return __arch_swab32(val);
6359
#else
6460
return ___constant_swab32(val);
@@ -67,9 +63,7 @@ static inline __attribute_const__ __u32 __fswab32(__u32 val)
6763

6864
static inline __attribute_const__ __u64 __fswab64(__u64 val)
6965
{
70-
#ifdef __HAVE_BUILTIN_BSWAP64__
71-
return __builtin_bswap64(val);
72-
#elif defined (__arch_swab64)
66+
#if defined (__arch_swab64)
7367
return __arch_swab64(val);
7468
#elif defined(__SWAB_64_THRU_32__)
7569
__u32 h = val >> 32;
@@ -102,28 +96,40 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val)
10296
* __swab16 - return a byteswapped 16-bit value
10397
* @x: value to byteswap
10498
*/
99+
#ifdef __HAVE_BUILTIN_BSWAP16__
100+
#define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
101+
#else
105102
#define __swab16(x) \
106103
(__builtin_constant_p((__u16)(x)) ? \
107104
___constant_swab16(x) : \
108105
__fswab16(x))
106+
#endif
109107

110108
/**
111109
* __swab32 - return a byteswapped 32-bit value
112110
* @x: value to byteswap
113111
*/
112+
#ifdef __HAVE_BUILTIN_BSWAP32__
113+
#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
114+
#else
114115
#define __swab32(x) \
115116
(__builtin_constant_p((__u32)(x)) ? \
116117
___constant_swab32(x) : \
117118
__fswab32(x))
119+
#endif
118120

119121
/**
120122
* __swab64 - return a byteswapped 64-bit value
121123
* @x: value to byteswap
122124
*/
125+
#ifdef __HAVE_BUILTIN_BSWAP64__
126+
#define __swab64(x) (__u64)__builtin_bswap64((__u64)(x))
127+
#else
123128
#define __swab64(x) \
124129
(__builtin_constant_p((__u64)(x)) ? \
125130
___constant_swab64(x) : \
126131
__fswab64(x))
132+
#endif
127133

128134
/**
129135
* __swahw32 - return a word-swapped 32-bit value

0 commit comments

Comments
 (0)