MIPS: Fix detection of unsupported highmem with cache aliases

The paging_init() function contains code which detects that highmem is
in use but unsupported due to dcache aliasing. However this code was
ineffective because it was being run before the caches are probed,
meaning that cpu_has_dc_aliases would always evaluate to false (unless a
platform overrides it to a compile-time constant) and the detection of
the unsupported case is never triggered. The kernel would then go on to
attempt to use highmem & either hit coherency issues or trigger the
BUG_ON in flush_kernel_dcache_page().

Fix this by running paging_init() later than cpu_cache_init(), such that
the cpu_has_dc_aliases macro will evaluate correctly & the unsupported
highmem case will be detected successfully.

This then leads to a formerly hidden issue in that
mem_init_free_highmem() will attempt to free all highmem pages, even
though we're avoiding use of them & don't have valid page structs for
them. This leads to an invalid pointer dereference & a TLB exception.
Avoid this by skipping the loop in mem_init_free_highmem() if
cpu_has_dc_aliases evaluates true.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: Rabin Vincent <rabinv@axis.com>
Cc: Matt Redfearn <matt.redfearn@imgtec.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Alexander Sverdlin <alexander.sverdlin@gmail.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Jaedon Shin <jaedon.shin@gmail.com>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Cc: Jonas Gorski <jogo@openwrt.org>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/14184/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by Paul Burton and committed by Ralf Baechle 058effe7 305723ab

Changed files
+4 -1
arch
mips
kernel
mm
+1 -1
arch/mips/kernel/setup.c
··· 764 764 device_tree_init(); 765 765 sparse_init(); 766 766 plat_swiotlb_setup(); 767 - paging_init(); 768 767 769 768 dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); 770 769 /* Tell bootmem about cma reserved memblock section */ ··· 876 877 prefill_possible_map(); 877 878 878 879 cpu_cache_init(); 880 + paging_init(); 879 881 } 880 882 881 883 unsigned long kernelsp[NR_CPUS];
+3
arch/mips/mm/init.c
··· 440 440 #ifdef CONFIG_HIGHMEM 441 441 unsigned long tmp; 442 442 443 + if (cpu_has_dc_aliases) 444 + return; 445 + 443 446 for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { 444 447 struct page *page = pfn_to_page(tmp); 445 448