linux/arch/mips/mm
Paul Burton 4bcb4ad663
MIPS: Consistently declare TLB functions
Since at least the beginning of the git era we've declared our TLB
exception handling functions inconsistently. They're actually functions,
but we declare them as arrays of u32 where each u32 is an encoded
instruction. This has always been the case for arch/mips/mm/tlbex.c, and
has also been true for arch/mips/kernel/traps.c since commit
86a1708a9d ("MIPS: Make tlb exception handler definitions and
declarations match.") which aimed for consistency but did so by
consistently making the our C code inconsistent with our assembly.

This is all usually harmless, but when using GCC 7 or newer to build a
kernel targeting microMIPS (ie. CONFIG_CPU_MICROMIPS=y) it becomes
problematic. With microMIPS bit 0 of the program counter indicates the
ISA mode. When bit 0 is zero instructions are decoded using the standard
MIPS32 or MIPS64 ISA. When bit 0 is one instructions are decoded using
microMIPS. This means that function pointers become odd - their least
significant bit is one for microMIPS code. We work around this in cases
where we need to access code using loads & stores with our
msk_isa16_mode() macro which simply clears bit 0 of the value it is
given:

  #define msk_isa16_mode(x) ((x) & ~0x1)

For example we do this for our TLB load handler in
build_r4000_tlb_load_handler():

  u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbl);

We then write code to p, expecting it to be suitably aligned (our LEAF
macro aligns functions on 4 byte boundaries, so (ulong)handle_tlbl will
give a value one greater than a multiple of 4 - ie. the start of a
function on a 4 byte boundary, with the ISA mode bit 0 set).

This worked fine up to GCC 6, but GCC 7 & onwards is smart enough to
presume that handle_tlbl which we declared as an array of u32s must be
aligned sufficiently that bit 0 of its address will never be set, and as
a result optimize out msk_isa16_mode(). This leads to p having an
address with bit 0 set, and when we go on to attempt to store code at
that address we take an address error exception due to the unaligned
memory access.

This leads to an exception prior to the kernel having configured its own
exception handlers, so we jump to whatever handlers the bootloader
configured. In the case of QEMU this results in a silent hang, since it
has no useful general exception vector.

Fix this by consistently declaring our TLB-related functions as
functions. For handle_tlbl(), handle_tlbs() & handle_tlbm() we do this
in asm/tlbex.h & we make use of the existing declaration of
tlbmiss_handler_setup_pgd() in asm/mmu_context.h. Our TLB handler
generation code in arch/mips/mm/tlbex.c is adjusted to deal with these
definitions, in most cases simply by casting the function pointers to
u32 pointers.

This allows us to include asm/mmu_context.h in arch/mips/mm/tlbex.c to
get the definitions of tlbmiss_handler_setup_pgd & pgd_current, removing
some needless duplication. Consistently using msk_isa16_mode() on
function pointers means we no longer need the
tlbmiss_handler_setup_pgd_start symbol so that is removed entirely.

Now that we're declaring our functions as functions GCC stops optimizing
out msk_isa16_mode() & a microMIPS kernel built with either GCC 7.3.0 or
8.1.0 boots successfully.

Signed-off-by: Paul Burton <paul.burton@mips.com>
2018-08-10 17:27:53 -07:00
..
c-octeon.c MIPS: c-r4k: Split user/kernel flush_icache_range() 2016-10-04 16:13:57 +02:00
c-r3k.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
c-r4k.c MIPS: WARN_ON invalid DMA cache maintenance, not BUG_ON 2018-07-26 11:25:01 -07:00
c-tx39.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
cache.c MIPS: simplify CONFIG_DMA_NONCOHERENT ifdefs 2018-06-24 09:26:02 -07:00
cerr-sb1.c MIPS: Sibyte: Fix build for SIBYTE_BW_TRACE on BCM1x55 and BCM1x80. 2013-06-21 18:07:02 +02:00
cex-gen.S MIPS: Whitespace cleanup. 2013-02-01 10:00:22 +01:00
cex-oct.S MIPS: Whitespace cleanup. 2013-02-01 10:00:22 +01:00
cex-sb1.S mips: delete non-required instances of include <linux/init.h> 2014-01-24 22:39:56 +01:00
dma-noncoherent.c MIPS: Make (UN)CAC_ADDR() PHYS_OFFSET-agnostic 2018-07-30 10:27:20 -07:00
extable.c Replace <asm/uaccess.h> with <linux/uaccess.h> globally 2016-12-24 11:46:01 -08:00
fault.c signal/mips: Use force_sig_fault where appropriate 2018-04-25 10:41:02 -05:00
gup.c mm/gup.c: document return value 2018-04-13 17:10:27 -07:00
highmem.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
hugetlbpage.c mm/hugetlb: add size parameter to huge_pte_offset() 2017-07-06 16:24:34 -07:00
init.c MIPS: Remove duplicate includes 2018-02-19 10:55:35 +00:00
ioremap.c sched/headers: Prepare to remove the <linux/mm_types.h> dependency from <linux/sched.h> 2017-03-02 08:42:37 +01:00
Makefile MIPS: remove mips_swiotlb_ops 2018-07-27 15:19:59 -07:00
mmap.c exec: pass stack rlimit into mm layout functions 2018-04-11 10:28:37 -07:00
page-funcs.S MIPS: Export {copy, clear}_page functions alongside their definitions 2017-01-03 16:48:39 +01:00
page.c arch: mips: mm: page: Remove unused function 2018-06-24 09:27:27 -07:00
pgtable-32.c MIPS: mm: fixed mappings: correct initialisation 2017-06-08 14:51:58 +02:00
pgtable-64.c MIPS: Add 48-bit VA space (and 4-level page tables) for 4K pages. 2017-04-10 11:56:06 +02:00
pgtable.c MIPS: Move pgd_alloc() out of header 2017-02-02 15:06:26 +00:00
sc-debugfs.c MIPS: Re-use kstrtobool_from_user() 2018-05-14 23:58:23 +01:00
sc-ip22.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
sc-mips.c MIPS: JZ4770: Work around config2 misreporting associativity 2018-01-18 22:07:44 +00:00
sc-r5k.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
sc-rm7k.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tlb-funcs.S MIPS: Consistently declare TLB functions 2018-08-10 17:27:53 -07:00
tlb-r3k.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
tlb-r4k.c MIPS: Mask out limit field when calculating wired entry count 2016-11-24 16:44:16 +01:00
tlb-r8k.c MIPS: Retrieve ASID masks using function accepting struct cpuinfo_mips 2016-05-13 14:02:20 +02:00
tlbex-fault.S MIPS: Add DWARF unwinding to assembly 2017-09-06 11:01:52 +02:00
tlbex.c MIPS: Consistently declare TLB functions 2018-08-10 17:27:53 -07:00
uasm-micromips.c MIPS: Remove remnants of UASM_ISA 2018-08-09 14:45:00 -07:00
uasm-mips.c MIPS: Remove remnants of UASM_ISA 2018-08-09 14:45:00 -07:00
uasm.c MIPS: Add some instructions to uasm. 2017-06-28 12:22:39 +02:00