]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Merge tag 'mips_4.19_2' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 21:23:08 +0000 (14:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 23 Aug 2018 21:23:08 +0000 (14:23 -0700)
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

12 files changed:
arch/Kconfig
arch/mips/Kconfig
arch/mips/include/asm/asm-prototypes.h
arch/mips/include/asm/atomic.h
arch/mips/include/asm/compiler.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/tlbex.h
arch/mips/kernel/traps.c
arch/mips/lib/multi3.c
arch/mips/mm/tlb-funcs.S
arch/mips/mm/tlbex.c
include/linux/compiler_types.h

index 4426e9687d89832e405c448eef7e41cb7a26d9ce..0a0ea5066fc0cb413f2940edefa7cb289739c709 100644 (file)
@@ -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
index 2af13b162e5e564cd8ac710e7154c108664f92f8..35511999156af4a2d3559b3ac9d6c0038630451e 100644 (file)
@@ -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
index 576f1a62dea99b9608518e3b7ffae467d770f990..f901ed043c71b983f5e26ba721b24bbc83c14490 100644 (file)
@@ -5,3 +5,4 @@
 #include <asm-generic/asm-prototypes.h>
 #include <linux/uaccess.h>
 #include <asm/ftrace.h>
+#include <asm/mmu_context.h>
index 0269b3de8b5197ab171ea9e4e4870ab4fe68dea9..d4ea7a5b60cf469772ed1651fd58d1f7010402e4 100644 (file)
@@ -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"
index e081a265f4227475d17fef0d53cf07f7e9ffb6a3..cc2eb1b06050c4255810843ba0ef513d2441bcdd 100644 (file)
@@ -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"
index b509371a6b0cce4842ab634c80c658e35d245db6..94414561de0e7b9c46d6d6af17c42de6e8519ab6 100644 (file)
@@ -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)                                 \
index 4ed7ebed3bf1f060d2f6965618120751e519605a..6d97e23f30abdded461a1b93f17feb9fd5d85a65 100644 (file)
@@ -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 */
index f8871d5b7eb3e863bc5abf6b77dbd2f04fdd877d..9dab0ed1b227804f92b16de32a9098ae20d1365a 100644 (file)
 #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);
index 111ad475aa0cdd111ebe362af928414d9499f666..4c2483f410c26b5b65ded652c1b0694b06a9bf92 100644 (file)
@@ -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)
index a5427c6e97574c6a1a0dbad628f7a75a3feed516..00fef578c8cdcfbc1359e476255d81f5c6cd4363 100644 (file)
  * 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
index 49312a14cd1702e148c22d71c68384c41ef717de..06771429164317c3e8bfe5da8e02e33445fb0b14 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/cpu-type.h>
+#include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
@@ -253,8 +254,10 @@ static void output_pgtable_bits_defines(void)
        pr_debug("\n");
 }
 
-static inline void dump_handler(const char *symbol, const u32 *handler, int count)
+static inline void dump_handler(const char *symbol, const void *start, const void *end)
 {
+       unsigned int count = (end - start) / sizeof(u32);
+       const u32 *handler = start;
        int i;
 
        pr_debug("LEAF(%s)\n", symbol);
@@ -402,12 +405,6 @@ static void build_restore_work_registers(u32 **p)
  * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
  * we cannot do r3000 under these circumstances.
  *
- * Declare pgd_current here instead of including mmu_context.h to avoid type
- * conflicts for tlbmiss_handler_setup_pgd
- */
-extern unsigned long pgd_current[];
-
-/*
  * The R3000 TLB handler is simple.
  */
 static void build_r3000_tlb_refill_handler(void)
@@ -444,8 +441,7 @@ static void build_r3000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, tlb_handler, 0x80);
        local_flush_icache_range(ebase, ebase + 0x80);
-
-       dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
+       dump_handler("r3000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x80));
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -1465,8 +1461,7 @@ static void build_r4000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, final_handler, 0x100);
        local_flush_icache_range(ebase, ebase + 0x100);
-
-       dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
+       dump_handler("r4000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x100));
 }
 
 static void setup_pw(void)
@@ -1568,31 +1563,21 @@ static void build_loongson3_tlb_refill_handler(void)
        uasm_resolve_relocs(relocs, labels);
        memcpy((void *)(ebase + 0x80), tlb_handler, 0x80);
        local_flush_icache_range(ebase + 0x80, ebase + 0x100);
-       dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
+       dump_handler("loongson3_tlb_refill",
+                    (u32 *)(ebase + 0x80), (u32 *)(ebase + 0x100));
 }
 
-extern u32 handle_tlbl[], handle_tlbl_end[];
-extern u32 handle_tlbs[], handle_tlbs_end[];
-extern u32 handle_tlbm[], handle_tlbm_end[];
-extern u32 tlbmiss_handler_setup_pgd_start[];
-extern u32 tlbmiss_handler_setup_pgd[];
-EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd);
-extern u32 tlbmiss_handler_setup_pgd_end[];
-
 static void build_setup_pgd(void)
 {
        const int a0 = 4;
        const int __maybe_unused a1 = 5;
        const int __maybe_unused a2 = 6;
-       u32 *p = tlbmiss_handler_setup_pgd_start;
-       const int tlbmiss_handler_setup_pgd_size =
-               tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start;
+       u32 *p = (u32 *)msk_isa16_mode((ulong)tlbmiss_handler_setup_pgd);
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
        long pgdc = (long)pgd_current;
 #endif
 
-       memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
-                                       sizeof(tlbmiss_handler_setup_pgd[0]));
+       memset(p, 0, tlbmiss_handler_setup_pgd_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
        pgd_reg = allocate_kscratch();
@@ -1645,15 +1630,15 @@ static void build_setup_pgd(void)
        else
                uasm_i_nop(&p);
 #endif
-       if (p >= tlbmiss_handler_setup_pgd_end)
+       if (p >= (u32 *)tlbmiss_handler_setup_pgd_end)
                panic("tlbmiss_handler_setup_pgd space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
-                (unsigned int)(p - tlbmiss_handler_setup_pgd));
+                (unsigned int)(p - (u32 *)tlbmiss_handler_setup_pgd));
 
        dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
-                                       tlbmiss_handler_setup_pgd_size);
+                                       tlbmiss_handler_setup_pgd_end);
 }
 
 static void
@@ -1922,12 +1907,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
 
 static void build_r3000_tlb_load_handler(void)
 {
-       u32 *p = handle_tlbl;
-       const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
+       u32 *p = (u32 *)handle_tlbl;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+       memset(p, 0, handle_tlbl_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -1941,24 +1925,23 @@ static void build_r3000_tlb_load_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbl_end)
+       if (p >= (u32 *)handle_tlbl_end)
                panic("TLB load handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbl));
+                (unsigned int)(p - (u32 *)handle_tlbl));
 
-       dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size);
+       dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_end);
 }
 
 static void build_r3000_tlb_store_handler(void)
 {
-       u32 *p = handle_tlbs;
-       const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
+       u32 *p = (u32 *)handle_tlbs;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+       memset(p, 0, handle_tlbs_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -1972,24 +1955,23 @@ static void build_r3000_tlb_store_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbs_end)
+       if (p >= (u32 *)handle_tlbs_end)
                panic("TLB store handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbs));
+                (unsigned int)(p - (u32 *)handle_tlbs));
 
-       dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size);
+       dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_end);
 }
 
 static void build_r3000_tlb_modify_handler(void)
 {
-       u32 *p = handle_tlbm;
-       const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
+       u32 *p = (u32 *)handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+       memset(p, 0, handle_tlbm_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2003,14 +1985,14 @@ static void build_r3000_tlb_modify_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbm_end)
+       if (p >= (u32 *)handle_tlbm_end)
                panic("TLB modify handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbm));
+                (unsigned int)(p - (u32 *)handle_tlbm));
 
-       dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size);
+       dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_end);
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -2102,12 +2084,11 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
 static void build_r4000_tlb_load_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbl);
-       const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+       memset(p, 0, handle_tlbl_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2288,25 +2269,24 @@ static void build_r4000_tlb_load_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbl_end)
+       if (p >= (u32 *)handle_tlbl_end)
                panic("TLB load handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbl));
+                (unsigned int)(p - (u32 *)handle_tlbl));
 
-       dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size);
+       dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_end);
 }
 
 static void build_r4000_tlb_store_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbs);
-       const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+       memset(p, 0, handle_tlbs_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2343,25 +2323,24 @@ static void build_r4000_tlb_store_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbs_end)
+       if (p >= (u32 *)handle_tlbs_end)
                panic("TLB store handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbs));
+                (unsigned int)(p - (u32 *)handle_tlbs));
 
-       dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size);
+       dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_end);
 }
 
 static void build_r4000_tlb_modify_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbm);
-       const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+       memset(p, 0, handle_tlbm_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2399,14 +2378,14 @@ static void build_r4000_tlb_modify_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbm_end)
+       if (p >= (u32 *)handle_tlbm_end)
                panic("TLB modify handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbm));
+                (unsigned int)(p - (u32 *)handle_tlbm));
 
-       dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size);
+       dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_end);
 }
 
 static void flush_tlb_handlers(void)
index 90479a0f398630c5659832e813c16e33ea9d9746..3525c179698c238c70145574c03e71620054777c 100644 (file)
@@ -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