Commit 0c4b0f81 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mips_4.19_2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux

Pull MIPS fixes from Paul Burton:

  - Fix microMIPS build failures by adding a .insn directive to the
    barrier_before_unreachable() asm statement in order to convince the
    toolchain that the asm statement is a valid branch target rather
    than a bogus attempt to switch ISA.

  - Clean up our declarations of TLB functions that we overwrite with
    generated code in order to prevent the compiler making assumptions
    about alignment that cause microMIPS kernels built with GCC 7 &
    above to die early during boot.

  - Fix up a regression for MIPS32 kernels which slipped into the main
    MIPS pull for 4.19, causing CONFIG_32BIT=y kernels to contain
    inappropriate MIPS64 instructions.

  - Extend our existing workaround for MIPSr6 builds that end up using
    the __multi3 intrinsic to GCC 7 & below, rather than just GCC 7.

* tag 'mips_4.19_2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux:
  MIPS: lib: Provide MIPS64r6 __multi3() for GCC < 7
  MIPS: Workaround GCC __builtin_unreachable reordering bug
  compiler.h: Allow arch-specific asm/compiler.h
  MIPS: Avoid move psuedo-instruction whilst using MIPS_ISA_LEVEL
  MIPS: Consistently declare TLB functions
  MIPS: Export tlbmiss_handler_setup_pgd near its definition
parents 2ab054fd 690d9163
......@@ -841,6 +841,14 @@ config REFCOUNT_FULL
against various use-after-free conditions that can be used in
security flaw exploits.
config HAVE_ARCH_COMPILER_H
bool
help
An architecture can select this if it provides an
asm/compiler.h header that should be included after
linux/compiler-*.h in order to override macro definitions that those
headers generally provide.
config HAVE_ARCH_PREL32_RELOCATIONS
bool
help
......
......@@ -33,6 +33,7 @@ config MIPS
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_COMPILER_H
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KGDB
select HAVE_ARCH_MMAP_RND_BITS if MMU
......
......@@ -5,3 +5,4 @@
#include <asm-generic/asm-prototypes.h>
#include <linux/uaccess.h>
#include <asm/ftrace.h>
#include <asm/mmu_context.h>
......@@ -122,8 +122,8 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \
" " #asm_op " %0, %1, %3 \n" \
" sc %0, %2 \n" \
"\t" __scbeqz " %0, 1b \n" \
" move %0, %1 \n" \
" .set mips0 \n" \
" move %0, %1 \n" \
: "=&r" (result), "=&r" (temp), \
"+" GCC_OFF_SMALL_ASM() (v->counter) \
: "Ir" (i)); \
......@@ -190,9 +190,11 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
__asm__ __volatile__(
" .set "MIPS_ISA_LEVEL" \n"
"1: ll %1, %2 # atomic_sub_if_positive\n"
" .set mips0 \n"
" subu %0, %1, %3 \n"
" move %1, %0 \n"
" bltz %0, 1f \n"
" .set "MIPS_ISA_LEVEL" \n"
" sc %1, %2 \n"
"\t" __scbeqz " %1, 1b \n"
"1: \n"
......
......@@ -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"
......
......@@ -32,6 +32,7 @@ do { \
} while (0)
extern void tlbmiss_handler_setup_pgd(unsigned long);
extern char tlbmiss_handler_setup_pgd_end[];
/* Note: This is also implemented with uasm in arch/mips/kvm/entry.c */
#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
......
......@@ -24,4 +24,13 @@ void build_tlb_write_entry(u32 **p, struct uasm_label **l,
struct uasm_reloc **r,
enum tlb_write_entry wmode);
extern void handle_tlbl(void);
extern char handle_tlbl_end[];
extern void handle_tlbs(void);
extern char handle_tlbs_end[];
extern void handle_tlbm(void);
extern char handle_tlbm_end[];
#endif /* __ASM_TLBEX_H */
......@@ -67,14 +67,12 @@
#include <asm/mmu_context.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
#include <asm/tlbex.h>
#include <asm/uasm.h>
extern void check_wait(void);
extern asmlinkage void rollback_handle_int(void);
extern asmlinkage void handle_int(void);
extern u32 handle_tlbl[];
extern u32 handle_tlbs[];
extern u32 handle_tlbm[];
extern asmlinkage void handle_adel(void);
extern asmlinkage void handle_ades(void);
extern asmlinkage void handle_ibe(void);
......
......@@ -4,12 +4,12 @@
#include "libgcc.h"
/*
* GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
* specific case only we'll implement it here.
* GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
* that specific case only we implement that intrinsic here.
*
* See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
*/
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
/* multiply 64-bit values, low 64-bits returned */
static inline long long notrace dmulu(long long a, long long b)
......
......@@ -12,16 +12,17 @@
* Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
*/
#include <asm/asm.h>
#include <asm/export.h>
#include <asm/regdef.h>
#define FASTPATH_SIZE 128
EXPORT(tlbmiss_handler_setup_pgd_start)
LEAF(tlbmiss_handler_setup_pgd)
1: j 1b /* Dummy, will be replaced. */
.space 64
END(tlbmiss_handler_setup_pgd)
EXPORT(tlbmiss_handler_setup_pgd_end)
EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd)
LEAF(handle_tlbm)
.space FASTPATH_SIZE * 4
......
This diff is collapsed.
......@@ -66,6 +66,18 @@ extern void __chk_io_ptr(const volatile void __iomem *);
#error "Unknown compiler"
#endif
/*
* Some architectures need to provide custom definitions of macros provided
* by linux/compiler-*.h, and can do so using asm/compiler.h. We include that
* conditionally rather than using an asm-generic wrapper in order to avoid
* build failures if any C compilation, which will include this file via an
* -include argument in c_flags, occurs prior to the asm-generic wrappers being
* generated.
*/
#ifdef CONFIG_HAVE_ARCH_COMPILER_H
#include <asm/compiler.h>
#endif
/*
* Generic compiler-independent macros required for kernel
* build go below this comment. Actual compiler/compiler version
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment