GCC for MIPS currently has a bug which leads to it reordering instructions into branch delay slots incorrectly when a call to __builtin_unreachable is the only content of the default case of a switch statement. See this thread for details: https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html Work around this bug by placing an empty volatile asm statement before the __builtin_unreachable call, which prevents GCC's delay slot filler from seeing past the asm statement (& thus the call to __builtin_unreachable) to instructions it shouldn't reorder. It would be good to guard this based upon GCC_VERSION once the bug is fixed in GCC, but meanwhile this workaround has no known negative side effects. This bug affects at least a maltasmvp_defconfig kernel built from the v4.4 tag using GCC 4.9.2 (from a Codescape SDK 2015.06-05 toolchain), with the result being an address exception taken after log messages about the L1 caches (during probe of the L2 cache): Initmem setup node 0 [mem 0x0000000080000000-0x000000009fffffff] VPE topology {2,2} total 4 Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes. Primary data cache 64kB, 4-way, PIPT, no aliases, linesize 32 bytes <AdEL exception here> This is early enough that the kernel exception vectors are not in use, so any further output depends upon the bootloader. This is reproducible in QEMU where no further output occurs - ie. the system hangs here. Given the affected v4.4 configuration this patch is marked for stable backport to v4.4, however I cannot test every configuration so it's entirely possible that this bug hits other platforms in earlier kernel versions. Given the nature of the bug it may potentially be hit with differing symptoms. Signed-off-by: Paul Burton <paul.burton@xxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> # v4.4+ Cc: Matthew Fortune <matthew.fortune@xxxxxxxxxx> Cc: Robert Suchanek <robert.suchanek@xxxxxxxxxx> --- include/linux/compiler-gcc.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 22ab246..e7c3502 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -196,7 +196,25 @@ * this in the preprocessor, but we can live with this because they're * unreleased. Really, we need to have autoconf for the kernel. */ -#define unreachable() __builtin_unreachable() +#if defined(__mips__) +/* + * GCC for MIPS currently has a bug which leads to it incorrectly + * reordering instructions into branch delay slots when a call to + * __builtin_unreachable() is the only thing in the default case of a + * switch statement. We avoid this bug for those versions of GCC by + * placing an empty volatile asm statement before the call to + * __builtin_unreachable, which GCC is prevented from reordering past. + * + * See this thread for details: + * https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html + */ +# define unreachable() do { \ + asm volatile(""); \ + __builtin_unreachable(); \ +} while (0) +#else +# define unreachable() __builtin_unreachable() +#endif /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__)) -- 2.7.1 -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html