From: Sasha Levin Date: Thu, 4 Jul 2019 00:11:04 +0000 (-0400) Subject: fixes for 4.4 X-Git-Tag: v5.1.17~41 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c775271c438ccaad33f025bb5027c573bd7d8c35;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.4 Signed-off-by: Sasha Levin --- diff --git a/queue-4.4/arc-assume-multiplier-is-always-present.patch b/queue-4.4/arc-assume-multiplier-is-always-present.patch new file mode 100644 index 00000000000..f99bbd26975 --- /dev/null +++ b/queue-4.4/arc-assume-multiplier-is-always-present.patch @@ -0,0 +1,69 @@ +From 7cb68b3f3c5e1edfaa12fb937a3ae76c1617b9c1 Mon Sep 17 00:00:00 2001 +From: Vineet Gupta +Date: Tue, 16 Feb 2016 09:42:57 +0530 +Subject: ARC: Assume multiplier is always present + +[ Upstream commit 0eca6fdb3193410fbe66b6f064431cc394513e82 ] + +It is unlikely that designs running Linux will not have multiplier. +Further the current support is not complete as tool don't generate a +multilib w/o multiplier. + +Signed-off-by: Vineet Gupta +Signed-off-by: Sasha Levin +--- + arch/arc/Kconfig | 8 -------- + arch/arc/Makefile | 4 ---- + arch/arc/kernel/setup.c | 2 -- + 3 files changed, 14 deletions(-) + +diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig +index e983f410135a..a5d8bef65911 100644 +--- a/arch/arc/Kconfig ++++ b/arch/arc/Kconfig +@@ -278,14 +278,6 @@ config ARC_DCCM_BASE + default "0xA0000000" + depends on ARC_HAS_DCCM + +-config ARC_HAS_HW_MPY +- bool "Use Hardware Multiplier (Normal or Faster XMAC)" +- default y +- help +- Influences how gcc generates code for MPY operations. +- If enabled, MPYxx insns are generated, provided by Standard/XMAC +- Multipler. Otherwise software multipy lib is used +- + choice + prompt "MMU Version" + default ARC_MMU_V3 if ARC_CPU_770 +diff --git a/arch/arc/Makefile b/arch/arc/Makefile +index fffaff9c7b2c..8f8d53f08141 100644 +--- a/arch/arc/Makefile ++++ b/arch/arc/Makefile +@@ -72,10 +72,6 @@ ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB + # --build-id w/o "-marclinux". Default arc-elf32-ld is OK + ldflags-$(upto_gcc44) += -marclinux + +-ifndef CONFIG_ARC_HAS_HW_MPY +- cflags-y += -mno-mpy +-endif +- + LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name) + + # Modules with short calls might break for calls into builtin-kernel +diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c +index 05131805aa33..3013f3f82b95 100644 +--- a/arch/arc/kernel/setup.c ++++ b/arch/arc/kernel/setup.c +@@ -232,8 +232,6 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) + + n += scnprintf(buf + n, len - n, "mpy[opt %d] ", opt); + } +- n += scnprintf(buf + n, len - n, "%s", +- IS_USED_CFG(CONFIG_ARC_HAS_HW_MPY)); + } + + n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n", +-- +2.20.1 + diff --git a/queue-4.4/arc-fix-build-warning-in-elf.h.patch b/queue-4.4/arc-fix-build-warning-in-elf.h.patch new file mode 100644 index 00000000000..34bc32d2f48 --- /dev/null +++ b/queue-4.4/arc-fix-build-warning-in-elf.h.patch @@ -0,0 +1,42 @@ +From 5c2c646c52962e98a6df34fe28dc6a2a96ebaee1 Mon Sep 17 00:00:00 2001 +From: Vineet Gupta +Date: Wed, 19 Oct 2016 14:38:50 -0700 +Subject: ARC: fix build warning in elf.h + +[ Upstream commit 1dec78585328db00e33fb18dc1a6deed0e2095a5 ] + +The cast valid since TASK_SIZE * 2 will never actually cause overflow. + +| CC fs/binfmt_elf.o +| In file included from ../include/linux/elf.h:4:0, +| from ../include/linux/module.h:15, +| from ../fs/binfmt_elf.c:12: +| ../fs/binfmt_elf.c: In function load_elf_binar: +| ../arch/arc/include/asm/elf.h:57:29: warning: integer overflow in expression [-Woverflow] +| #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) +| ^ +| ../fs/binfmt_elf.c:921:16: note: in expansion of macro ELF_ET_DYN_BASE +| load_bias = ELF_ET_DYN_BASE - vaddr; + +Signed-off-by: Vineet Gupta +Signed-off-by: Sasha Levin +--- + arch/arc/include/asm/elf.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arc/include/asm/elf.h b/arch/arc/include/asm/elf.h +index 51a99e25fe33..8ee9113b2f8b 100644 +--- a/arch/arc/include/asm/elf.h ++++ b/arch/arc/include/asm/elf.h +@@ -55,7 +55,7 @@ extern int elf_check_arch(const struct elf32_hdr *); + * the loader. We need to make sure that it is out of the way of the program + * that it will "exec", and that there is sufficient room for the brk. + */ +-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) ++#define ELF_ET_DYN_BASE (2UL * TASK_SIZE / 3) + + /* + * When the program starts, a1 contains a pointer to a function to be +-- +2.20.1 + diff --git a/queue-4.4/bug.h-work-around-gcc-pr82365-in-bug.patch b/queue-4.4/bug.h-work-around-gcc-pr82365-in-bug.patch new file mode 100644 index 00000000000..8426d41f8bf --- /dev/null +++ b/queue-4.4/bug.h-work-around-gcc-pr82365-in-bug.patch @@ -0,0 +1,275 @@ +From 509ed98ccdc5e8b4810a74a31efe22c767135d16 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 21 Feb 2018 14:45:54 -0800 +Subject: bug.h: work around GCC PR82365 in BUG() + +[ Upstream commit 173a3efd3edb2ef6ef07471397c5f542a360e9c1 ] + +Looking at functions with large stack frames across all architectures +led me discovering that BUG() suffers from the same problem as +fortify_panic(), which I've added a workaround for already. + +In short, variables that go out of scope by calling a noreturn function +or __builtin_unreachable() keep using stack space in functions +afterwards. + +A workaround that was identified is to insert an empty assembler +statement just before calling the function that doesn't return. I'm +adding a macro "barrier_before_unreachable()" to document this, and +insert calls to that in all instances of BUG() that currently suffer +from this problem. + +The files that saw the largest change from this had these frame sizes +before, and much less with my patch: + + fs/ext4/inode.c:82:1: warning: the frame size of 1672 bytes is larger than 800 bytes [-Wframe-larger-than=] + fs/ext4/namei.c:434:1: warning: the frame size of 904 bytes is larger than 800 bytes [-Wframe-larger-than=] + fs/ext4/super.c:2279:1: warning: the frame size of 1160 bytes is larger than 800 bytes [-Wframe-larger-than=] + fs/ext4/xattr.c:146:1: warning: the frame size of 1168 bytes is larger than 800 bytes [-Wframe-larger-than=] + fs/f2fs/inode.c:152:1: warning: the frame size of 1424 bytes is larger than 800 bytes [-Wframe-larger-than=] + net/netfilter/ipvs/ip_vs_core.c:1195:1: warning: the frame size of 1068 bytes is larger than 800 bytes [-Wframe-larger-than=] + net/netfilter/ipvs/ip_vs_core.c:395:1: warning: the frame size of 1084 bytes is larger than 800 bytes [-Wframe-larger-than=] + net/netfilter/ipvs/ip_vs_ftp.c:298:1: warning: the frame size of 928 bytes is larger than 800 bytes [-Wframe-larger-than=] + net/netfilter/ipvs/ip_vs_ftp.c:418:1: warning: the frame size of 908 bytes is larger than 800 bytes [-Wframe-larger-than=] + net/netfilter/ipvs/ip_vs_lblcr.c:718:1: warning: the frame size of 960 bytes is larger than 800 bytes [-Wframe-larger-than=] + drivers/net/xen-netback/netback.c:1500:1: warning: the frame size of 1088 bytes is larger than 800 bytes [-Wframe-larger-than=] + +In case of ARC and CRIS, it turns out that the BUG() implementation +actually does return (or at least the compiler thinks it does), +resulting in lots of warnings about uninitialized variable use and +leaving noreturn functions, such as: + + block/cfq-iosched.c: In function 'cfq_async_queue_prio': + block/cfq-iosched.c:3804:1: error: control reaches end of non-void function [-Werror=return-type] + include/linux/dmaengine.h: In function 'dma_maxpq': + include/linux/dmaengine.h:1123:1: error: control reaches end of non-void function [-Werror=return-type] + +This makes them call __builtin_trap() instead, which should normally +dump the stack and kill the current process, like some of the other +architectures already do. + +I tried adding barrier_before_unreachable() to panic() and +fortify_panic() as well, but that had very little effect, so I'm not +submitting that patch. + +Vineet said: + +: For ARC, it is double win. +: +: 1. Fixes 3 -Wreturn-type warnings +: +: | ../net/core/ethtool.c:311:1: warning: control reaches end of non-void function +: [-Wreturn-type] +: | ../kernel/sched/core.c:3246:1: warning: control reaches end of non-void function +: [-Wreturn-type] +: | ../include/linux/sunrpc/svc_xprt.h:180:1: warning: control reaches end of +: non-void function [-Wreturn-type] +: +: 2. bloat-o-meter reports code size improvements as gcc elides the +: generated code for stack return. + +Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 +Link: http://lkml.kernel.org/r/20171219114112.939391-1-arnd@arndb.de +Signed-off-by: Arnd Bergmann +Acked-by: Vineet Gupta [arch/arc] +Tested-by: Vineet Gupta [arch/arc] +Cc: Mikael Starvik +Cc: Jesper Nilsson +Cc: Tony Luck +Cc: Fenghua Yu +Cc: Geert Uytterhoeven +Cc: "David S. Miller" +Cc: Christopher Li +Cc: Thomas Gleixner +Cc: Peter Zijlstra +Cc: Kees Cook +Cc: Ingo Molnar +Cc: Josh Poimboeuf +Cc: Will Deacon +Cc: "Steven Rostedt (VMware)" +Cc: Mark Rutland +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + arch/arc/include/asm/bug.h | 3 ++- + arch/cris/include/arch-v10/arch/bug.h | 11 +++++++++-- + arch/ia64/include/asm/bug.h | 6 +++++- + arch/m68k/include/asm/bug.h | 3 +++ + arch/sparc/include/asm/bug.h | 6 +++++- + include/asm-generic/bug.h | 1 + + include/linux/compiler-gcc.h | 15 ++++++++++++++- + include/linux/compiler.h | 5 +++++ + 8 files changed, 44 insertions(+), 6 deletions(-) + +diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h +index ea022d47896c..21ec82466d62 100644 +--- a/arch/arc/include/asm/bug.h ++++ b/arch/arc/include/asm/bug.h +@@ -23,7 +23,8 @@ void die(const char *str, struct pt_regs *regs, unsigned long address); + + #define BUG() do { \ + pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ +- dump_stack(); \ ++ barrier_before_unreachable(); \ ++ __builtin_trap(); \ + } while (0) + + #define HAVE_ARCH_BUG +diff --git a/arch/cris/include/arch-v10/arch/bug.h b/arch/cris/include/arch-v10/arch/bug.h +index 3485d6b34bb0..06701ac0596f 100644 +--- a/arch/cris/include/arch-v10/arch/bug.h ++++ b/arch/cris/include/arch-v10/arch/bug.h +@@ -43,18 +43,25 @@ struct bug_frame { + * not be used like this with newer versions of gcc. + */ + #define BUG() \ ++do { \ + __asm__ __volatile__ ("clear.d [" __stringify(BUG_MAGIC) "]\n\t"\ + "movu.w " __stringify(__LINE__) ",$r0\n\t"\ + "jump 0f\n\t" \ + ".section .rodata\n" \ + "0:\t.string \"" __FILE__ "\"\n\t" \ +- ".previous") ++ ".previous"); \ ++ unreachable(); \ ++} while (0) + #endif + + #else + + /* This just causes an oops. */ +-#define BUG() (*(int *)0 = 0) ++#define BUG() \ ++do { \ ++ barrier_before_unreachable(); \ ++ __builtin_trap(); \ ++} while (0) + + #endif + +diff --git a/arch/ia64/include/asm/bug.h b/arch/ia64/include/asm/bug.h +index 823616b5020b..19067821249f 100644 +--- a/arch/ia64/include/asm/bug.h ++++ b/arch/ia64/include/asm/bug.h +@@ -3,7 +3,11 @@ + + #ifdef CONFIG_BUG + #define ia64_abort() __builtin_trap() +-#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0) ++#define BUG() do { \ ++ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ ++ barrier_before_unreachable(); \ ++ ia64_abort(); \ ++} while (0) + + /* should this BUG be made generic? */ + #define HAVE_ARCH_BUG +diff --git a/arch/m68k/include/asm/bug.h b/arch/m68k/include/asm/bug.h +index ef9a2e47352f..21ddbf925e22 100644 +--- a/arch/m68k/include/asm/bug.h ++++ b/arch/m68k/include/asm/bug.h +@@ -7,16 +7,19 @@ + #ifndef CONFIG_SUN3 + #define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ ++ barrier_before_unreachable(); \ + __builtin_trap(); \ + } while (0) + #else + #define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ ++ barrier_before_unreachable(); \ + panic("BUG!"); \ + } while (0) + #endif + #else + #define BUG() do { \ ++ barrier_before_unreachable(); \ + __builtin_trap(); \ + } while (0) + #endif +diff --git a/arch/sparc/include/asm/bug.h b/arch/sparc/include/asm/bug.h +index eaa8f8d38125..fa85cac0285c 100644 +--- a/arch/sparc/include/asm/bug.h ++++ b/arch/sparc/include/asm/bug.h +@@ -8,10 +8,14 @@ + void do_BUG(const char *file, int line); + #define BUG() do { \ + do_BUG(__FILE__, __LINE__); \ ++ barrier_before_unreachable(); \ + __builtin_trap(); \ + } while (0) + #else +-#define BUG() __builtin_trap() ++#define BUG() do { \ ++ barrier_before_unreachable(); \ ++ __builtin_trap(); \ ++} while (0) + #endif + + #define HAVE_ARCH_BUG +diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h +index 630dd2372238..09aa521a0085 100644 +--- a/include/asm-generic/bug.h ++++ b/include/asm-generic/bug.h +@@ -47,6 +47,7 @@ struct bug_entry { + #ifndef HAVE_ARCH_BUG + #define BUG() do { \ + printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ ++ barrier_before_unreachable(); \ + panic("BUG!"); \ + } while (0) + #endif +diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h +index 143d40e8a1ea..af8b4a879934 100644 +--- a/include/linux/compiler-gcc.h ++++ b/include/linux/compiler-gcc.h +@@ -206,6 +206,15 @@ + #endif /* GCC_VERSION >= 40300 */ + + #if GCC_VERSION >= 40500 ++/* ++ * calling noreturn functions, __builtin_unreachable() and __builtin_trap() ++ * confuse the stack allocation in gcc, leading to overly large stack ++ * frames, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 ++ * ++ * Adding an empty inline assembly before it works around the problem ++ */ ++#define barrier_before_unreachable() asm volatile("") ++ + /* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer +@@ -215,7 +224,11 @@ + * 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() ++#define unreachable() \ ++ do { \ ++ barrier_before_unreachable(); \ ++ __builtin_unreachable(); \ ++ } while (0) + + /* Mark a function definition as prohibited from being cloned. */ + #define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) +diff --git a/include/linux/compiler.h b/include/linux/compiler.h +index 0db1fa621d8a..ed772311ec1f 100644 +--- a/include/linux/compiler.h ++++ b/include/linux/compiler.h +@@ -175,6 +175,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); + # define barrier_data(ptr) barrier() + #endif + ++/* workaround for GCC PR82365 if needed */ ++#ifndef barrier_before_unreachable ++# define barrier_before_unreachable() do { } while (0) ++#endif ++ + /* Unreachable code */ + #ifndef unreachable + # define unreachable() do { } while (1) +-- +2.20.1 + diff --git a/queue-4.4/mfd-omap-usb-tll-fix-register-offsets.patch b/queue-4.4/mfd-omap-usb-tll-fix-register-offsets.patch new file mode 100644 index 00000000000..828143ee3ac --- /dev/null +++ b/queue-4.4/mfd-omap-usb-tll-fix-register-offsets.patch @@ -0,0 +1,47 @@ +From 00f3b19db1ca923e047437123f3a264922a3fc7f Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 23 Aug 2017 16:44:51 +0200 +Subject: mfd: omap-usb-tll: Fix register offsets + +[ Upstream commit 993dc737c0996c163325961fb62a0ed9fd0308b4 ] + +gcc-8 notices that the register number calculation is wrong +when the offset is an 'u8' but the number is larger than 256: + +drivers/mfd/omap-usb-tll.c: In function 'omap_tll_init': +drivers/mfd/omap-usb-tll.c:90:46: error: overflow in conversion from 'int' to 'u8 {aka unsigned char}' chages value from 'i * 256 + 2070' to '22' [-Werror=overflow] + +This addresses it by always using a 32-bit offset number for +the register. This is apparently an old problem that previous +compilers did not find. + +Fixes: 16fa3dc75c22 ("mfd: omap-usb-tll: HOST TLL platform driver") +Signed-off-by: Arnd Bergmann +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/mfd/omap-usb-tll.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c +index fe51e9709210..1093d8ad232b 100644 +--- a/drivers/mfd/omap-usb-tll.c ++++ b/drivers/mfd/omap-usb-tll.c +@@ -129,12 +129,12 @@ static inline u32 usbtll_read(void __iomem *base, u32 reg) + return readl_relaxed(base + reg); + } + +-static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val) ++static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val) + { + writeb_relaxed(val, base + reg); + } + +-static inline u8 usbtll_readb(void __iomem *base, u8 reg) ++static inline u8 usbtll_readb(void __iomem *base, u32 reg) + { + return readb_relaxed(base + reg); + } +-- +2.20.1 + diff --git a/queue-4.4/mips-math-emu-do-not-use-bools-for-arithmetic.patch b/queue-4.4/mips-math-emu-do-not-use-bools-for-arithmetic.patch new file mode 100644 index 00000000000..f0648512274 --- /dev/null +++ b/queue-4.4/mips-math-emu-do-not-use-bools-for-arithmetic.patch @@ -0,0 +1,55 @@ +From 08cf23029b9e2deeff36576b6f227cca81daec5e Mon Sep 17 00:00:00 2001 +From: Manuel Lauss +Date: Mon, 14 Aug 2017 12:21:48 +0200 +Subject: MIPS: math-emu: do not use bools for arithmetic + +[ Upstream commit 8535f2ba0a9b971df62a5890699b9dfe2e0d5580 ] + +GCC-7 complains about a boolean value being used with an arithmetic +AND: + +arch/mips/math-emu/cp1emu.c: In function 'cop1Emulate': +arch/mips/math-emu/cp1emu.c:838:14: warning: '~' on a boolean expression [-Wbool-operation] + fpr = (x) & ~(cop1_64bit(xcp) == 0); \ + ^ +arch/mips/math-emu/cp1emu.c:1068:3: note: in expansion of macro 'DITOREG' + DITOREG(dval, MIPSInst_RT(ir)); + ^~~~~~~ +arch/mips/math-emu/cp1emu.c:838:14: note: did you mean to use logical not? + fpr = (x) & ~(cop1_64bit(xcp) == 0); \ + +Since cop1_64bit() returns and int, just flip the LSB. + +Suggested-by: Maciej W. Rozycki +Signed-off-by: Manuel Lauss +Reviewed-by: Maciej W. Rozycki +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/17058/ +Signed-off-by: Ralf Baechle +Signed-off-by: Sasha Levin +--- + arch/mips/math-emu/cp1emu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c +index 89d05de8040a..011b9b9574f1 100644 +--- a/arch/mips/math-emu/cp1emu.c ++++ b/arch/mips/math-emu/cp1emu.c +@@ -829,12 +829,12 @@ do { \ + } while (0) + + #define DIFROMREG(di, x) \ +- ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) ++ ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) ^ 1)], 0)) + + #define DITOREG(di, x) \ + do { \ + unsigned fpr, i; \ +- fpr = (x) & ~(cop1_64bit(xcp) == 0); \ ++ fpr = (x) & ~(cop1_64bit(xcp) ^ 1); \ + set_fpr64(&ctx->fpr[fpr], 0, di); \ + for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \ + set_fpr64(&ctx->fpr[fpr], i, 0); \ +-- +2.20.1 + diff --git a/queue-4.4/mips-workaround-gcc-__builtin_unreachable-reordering.patch b/queue-4.4/mips-workaround-gcc-__builtin_unreachable-reordering.patch new file mode 100644 index 00000000000..6b72ca58dfa --- /dev/null +++ b/queue-4.4/mips-workaround-gcc-__builtin_unreachable-reordering.patch @@ -0,0 +1,149 @@ +From 9d788727b95af099a964d285afe0a6726ebf85d5 Mon Sep 17 00:00:00 2001 +From: Paul Burton +Date: Mon, 20 Aug 2018 15:36:18 -0700 +Subject: MIPS: Workaround GCC __builtin_unreachable reordering bug + +[ Upstream commit 906d441febc0de974b2a6ef848a8f058f3bfada3 ] + +Some versions of GCC for the MIPS architecture suffer from a bug which +can lead to instructions from beyond an unreachable statement being +incorrectly reordered into earlier branch delay slots if the unreachable +statement is the only content of a case in a switch statement. This can +lead to seemingly random behaviour, such as invalid memory accesses from +incorrectly reordered loads or stores, and link failures on microMIPS +builds. + +See this potential GCC fix for details: + + https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html + +Runtime problems resulting from this bug were initially observed using a +maltasmvp_defconfig v4.4 kernel built 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 + + +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 nature of the bug it may potentially be hit with differing +symptoms. The bug is known to affect GCC versions as recent as 7.3, and +it is unclear whether GCC 8 fixed it or just happens not to encounter +the bug in the testcase found at the link above due to differing +optimizations. + +This bug can be worked around by placing a volatile asm statement, which +GCC is prevented from reordering past, prior to the +__builtin_unreachable call. + +That was actually done already for other reasons by commit 173a3efd3edb +("bug.h: work around GCC PR82365 in BUG()"), but creates problems for +microMIPS builds due to the lack of a .insn directive. The microMIPS ISA +allows for interlinking with regular MIPS32 code by repurposing bit 0 of +the program counter as an ISA mode bit. To switch modes one changes the +value of this bit in the PC. However typical branch instructions encode +their offsets as multiples of 2-byte instruction halfwords, which means +they cannot change ISA mode - this must be done using either an indirect +branch (a jump-register in MIPS terminology) or a dedicated jalx +instruction. In order to ensure that regular branches don't attempt to +target code in a different ISA which they can't actually switch to, the +linker will check that branch targets are code in the same ISA as the +branch. + +Unfortunately our empty asm volatile statements don't qualify as code, +and the link for microMIPS builds fails with errors such as: + + arch/mips/mm/dma-default.s:3265: Error: branch to a symbol in another ISA mode + arch/mips/mm/dma-default.s:5027: Error: branch to a symbol in another ISA mode + +Resolve this by adding a .insn directive within the asm statement which +declares that what comes next is code. This may or may not be true, +since we don't really know what comes next, but as this code is in an +unreachable path anyway that doesn't matter since we won't execute it. + +We do this in asm/compiler.h & select CONFIG_HAVE_ARCH_COMPILER_H in +order to have this included by linux/compiler_types.h after +linux/compiler-gcc.h. This will result in asm/compiler.h being included +in all C compilations via the -include linux/compiler_types.h argument +in c_flags, which should be harmless. + +Signed-off-by: Paul Burton +Fixes: 173a3efd3edb ("bug.h: work around GCC PR82365 in BUG()") +Patchwork: https://patchwork.linux-mips.org/patch/20270/ +Cc: James Hogan +Cc: Ralf Baechle +Cc: Arnd Bergmann +Cc: linux-mips@linux-mips.org +Signed-off-by: Sasha Levin +--- + arch/mips/Kconfig | 1 + + arch/mips/include/asm/compiler.h | 35 ++++++++++++++++++++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig +index 333ea0389adb..687a3eb8d4d9 100644 +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -13,6 +13,7 @@ config MIPS + select HAVE_OPROFILE + select HAVE_PERF_EVENTS + select PERF_USE_VMALLOC ++ select HAVE_ARCH_COMPILER_H + select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_TRACEHOOK +diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h +index e081a265f422..cc2eb1b06050 100644 +--- a/arch/mips/include/asm/compiler.h ++++ b/arch/mips/include/asm/compiler.h +@@ -8,6 +8,41 @@ + #ifndef _ASM_COMPILER_H + #define _ASM_COMPILER_H + ++/* ++ * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the ++ * compiler that a particular code path will never be hit. This allows it to be ++ * optimised out of the generated binary. ++ * ++ * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug ++ * that can lead to instructions from beyond an unreachable statement being ++ * incorrectly reordered into earlier delay slots if the unreachable statement ++ * is the only content of a case in a switch statement. This can lead to ++ * seemingly random behaviour, such as invalid memory accesses from incorrectly ++ * reordered loads or stores. See this potential GCC fix for details: ++ * ++ * https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html ++ * ++ * It is unclear whether GCC 8 onwards suffer from the same issue - nothing ++ * relevant is mentioned in GCC 8 release notes and nothing obviously relevant ++ * stands out in GCC commit logs, but these newer GCC versions generate very ++ * different code for the testcase which doesn't exhibit the bug. ++ * ++ * GCC also handles stack allocation suboptimally when calling noreturn ++ * functions or calling __builtin_unreachable(): ++ * ++ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 ++ * ++ * We work around both of these issues by placing a volatile asm statement, ++ * which GCC is prevented from reordering past, prior to __builtin_unreachable ++ * calls. ++ * ++ * The .insn statement is required to ensure that any branches to the ++ * statement, which sadly must be kept due to the asm statement, are known to ++ * be branches to code and satisfy linker requirements for microMIPS kernels. ++ */ ++#undef barrier_before_unreachable ++#define barrier_before_unreachable() asm volatile(".insn") ++ + #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) + #define GCC_IMM_ASM() "n" + #define GCC_REG_ACCUM "$0" +-- +2.20.1 + diff --git a/queue-4.4/series b/queue-4.4/series index 347e1143c82..cd16dd58283 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -52,3 +52,10 @@ asoc-max98090-remove-24-bit-format-support-if-rj-is-.patch usb-gadget-fusb300_udc-fix-memory-leak-of-fusb300-ep.patch usb-gadget-udc-lpc32xx-allocate-descriptor-with-gfp_.patch scsi-hpsa-correct-ioaccel2-chaining.patch +arc-assume-multiplier-is-always-present.patch +arc-fix-build-warning-in-elf.h.patch +mips-math-emu-do-not-use-bools-for-arithmetic.patch +mfd-omap-usb-tll-fix-register-offsets.patch +swiotlb-make-linux-swiotlb.h-standalone-includible.patch +bug.h-work-around-gcc-pr82365-in-bug.patch +mips-workaround-gcc-__builtin_unreachable-reordering.patch diff --git a/queue-4.4/swiotlb-make-linux-swiotlb.h-standalone-includible.patch b/queue-4.4/swiotlb-make-linux-swiotlb.h-standalone-includible.patch new file mode 100644 index 00000000000..b71175c1e25 --- /dev/null +++ b/queue-4.4/swiotlb-make-linux-swiotlb.h-standalone-includible.patch @@ -0,0 +1,43 @@ +From b13698a147aaf3d2dca1e5cb5e7857fcd4773263 Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Wed, 1 Jul 2015 14:17:58 +0200 +Subject: swiotlb: Make linux/swiotlb.h standalone includible + +[ Upstream commit 386744425e35e04984c6e741c7750fd6eef1a9df ] + +This header file uses the enum dma_data_direction and struct page types +without explicitly including the corresponding header files. This makes +it rely on the includer to have included the proper headers before. + +To fix this, include linux/dma-direction.h and forward-declare struct +page. The swiotlb_free() function is also annotated __init, therefore +requires linux/init.h to be included as well. + +Signed-off-by: Thierry Reding +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Sasha Levin +--- + include/linux/swiotlb.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h +index e7a018eaf3a2..017fced60242 100644 +--- a/include/linux/swiotlb.h ++++ b/include/linux/swiotlb.h +@@ -1,10 +1,13 @@ + #ifndef __LINUX_SWIOTLB_H + #define __LINUX_SWIOTLB_H + ++#include ++#include + #include + + struct device; + struct dma_attrs; ++struct page; + struct scatterlist; + + extern int swiotlb_force; +-- +2.20.1 +