| From 4cd5f75f3255a1820a1d30f3728deeb79ff5e4db Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 29 Jul 2019 14:10:12 -0700 |
| Subject: mips: avoid explicit UB in assignment of mips_io_port_base |
| |
| From: Nick Desaulniers <ndesaulniers@google.com> |
| |
| [ Upstream commit 12051b318bc3ce5b42d6d786191008284b067d83 ] |
| |
| The code in question is modifying a variable declared const through |
| pointer manipulation. Such code is explicitly undefined behavior, and |
| is the lone issue preventing malta_defconfig from booting when built |
| with Clang: |
| |
| If an attempt is made to modify an object defined with a const-qualified |
| type through use of an lvalue with non-const-qualified type, the |
| behavior is undefined. |
| |
| LLVM is removing such assignments. A simple fix is to not declare |
| variables const that you plan on modifying. Limiting the scope would be |
| a better method of preventing unwanted writes to such a variable. |
| |
| Further, the code in question mentions "compiler bugs" without any links |
| to bug reports, so it is difficult to know if the issue is resolved in |
| GCC. The patch was authored in 2006, which would have been GCC 4.0.3 or |
| 4.1.1. The minimal supported version of GCC in the Linux kernel is |
| currently 4.6. |
| |
| For what its worth, there was UB before the commit in question, it just |
| added a barrier and got lucky IRT codegen. I don't think there's any |
| actual compiler bugs related, just runtime bugs due to UB. |
| |
| Link: https://github.com/ClangBuiltLinux/linux/issues/610 |
| Fixes: 966f4406d903 ("[MIPS] Work around bad code generation for <asm/io.h>.") |
| Reported-by: Nathan Chancellor <natechancellor@gmail.com> |
| Debugged-by: Nathan Chancellor <natechancellor@gmail.com> |
| Suggested-by: Eli Friedman <efriedma@quicinc.com> |
| Signed-off-by: Nick Desaulniers <ndesaulniers@google.com> |
| Reviewed-by: Nathan Chancellor <natechancellor@gmail.com> |
| Tested-by: Nathan Chancellor <natechancellor@gmail.com> |
| Signed-off-by: Paul Burton <paul.burton@mips.com> |
| Cc: ralf@linux-mips.org |
| Cc: jhogan@kernel.org |
| Cc: Maciej W. Rozycki <macro@linux-mips.org> |
| Cc: Hassan Naveed <hnaveed@wavecomp.com> |
| Cc: Stephen Kitt <steve@sk2.org> |
| Cc: Serge Semin <fancer.lancer@gmail.com> |
| Cc: Mike Rapoport <rppt@linux.ibm.com> |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Michal Hocko <mhocko@suse.com> |
| Cc: linux-mips@vger.kernel.org |
| Cc: linux-kernel@vger.kernel.org |
| Cc: clang-built-linux@googlegroups.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/mips/include/asm/io.h | 14 ++------------ |
| arch/mips/kernel/setup.c | 2 +- |
| 2 files changed, 3 insertions(+), 13 deletions(-) |
| |
| diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h |
| index 06049b6b3dddb..5dfae80264b9b 100644 |
| --- a/arch/mips/include/asm/io.h |
| +++ b/arch/mips/include/asm/io.h |
| @@ -60,21 +60,11 @@ |
| * instruction, so the lower 16 bits must be zero. Should be true on |
| * on any sane architecture; generic code does not use this assumption. |
| */ |
| -extern const unsigned long mips_io_port_base; |
| +extern unsigned long mips_io_port_base; |
| |
| -/* |
| - * Gcc will generate code to load the value of mips_io_port_base after each |
| - * function call which may be fairly wasteful in some cases. So we don't |
| - * play quite by the book. We tell gcc mips_io_port_base is a long variable |
| - * which solves the code generation issue. Now we need to violate the |
| - * aliasing rules a little to make initialization possible and finally we |
| - * will need the barrier() to fight side effects of the aliasing chat. |
| - * This trickery will eventually collapse under gcc's optimizer. Oh well. |
| - */ |
| static inline void set_io_port_base(unsigned long base) |
| { |
| - * (unsigned long *) &mips_io_port_base = base; |
| - barrier(); |
| + mips_io_port_base = base; |
| } |
| |
| /* |
| diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c |
| index 695950361d2a7..7cc1d29334ee1 100644 |
| --- a/arch/mips/kernel/setup.c |
| +++ b/arch/mips/kernel/setup.c |
| @@ -74,7 +74,7 @@ static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; |
| * mips_io_port_base is the begin of the address space to which x86 style |
| * I/O ports are mapped. |
| */ |
| -const unsigned long mips_io_port_base = -1; |
| +unsigned long mips_io_port_base = -1; |
| EXPORT_SYMBOL(mips_io_port_base); |
| |
| static struct resource code_resource = { .name = "Kernel code", }; |
| -- |
| 2.20.1 |
| |