aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2016-11-01 09:59:09 -0400
committerRalf Baechle <ralf@linux-mips.org>2016-11-03 20:45:22 -0400
commit16a767ec63167ef70c056795782d6c9c76ba5a5c (patch)
treed27dd0609ffa8a8b45c268cb06b54b4d38b0d445
parentf92722dc4545ebfa0f99a2f986fd88c112a22a42 (diff)
MIPS: Fix max_low_pfn with disabled highmem
When low memory doesn't reach HIGHMEM_START (e.g. up to 256MB at PA=0 is common) and highmem is present above HIGHMEM_START (e.g. on Malta the RAM overlayed by the IO region is aliased at PA=0x90000000), max_low_pfn will be initially calculated very large and then clipped down to HIGHMEM_START. This causes crashes when reading /sys/kernel/mm/page_idle/bitmap (i.e. CONFIG_IDLE_PAGE_TRACKING=y) when highmem is disabled. pfn_valid() will compare against max_mapnr which is derived from max_low_pfn when there is no highend_pfn set up, and will return true for PFNs right up to HIGHMEM_START, even though they are beyond the end of low memory and no page structs will actually exist for these PFNs. This is fixed by skipping high memory regions when initially calculating max_low_pfn if highmem is disabled, so it doesn't get clipped too high. We also clip regions which overlap the highmem boundary when highmem is disabled, so that max_pfn doesn't extend into highmem either. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14490/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/setup.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 0d57909d9026..f66e5ce505b2 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -368,6 +368,19 @@ static void __init bootmem_init(void)
368 end = PFN_DOWN(boot_mem_map.map[i].addr 368 end = PFN_DOWN(boot_mem_map.map[i].addr
369 + boot_mem_map.map[i].size); 369 + boot_mem_map.map[i].size);
370 370
371#ifndef CONFIG_HIGHMEM
372 /*
373 * Skip highmem here so we get an accurate max_low_pfn if low
374 * memory stops short of high memory.
375 * If the region overlaps HIGHMEM_START, end is clipped so
376 * max_pfn excludes the highmem portion.
377 */
378 if (start >= PFN_DOWN(HIGHMEM_START))
379 continue;
380 if (end > PFN_DOWN(HIGHMEM_START))
381 end = PFN_DOWN(HIGHMEM_START);
382#endif
383
371 if (end > max_low_pfn) 384 if (end > max_low_pfn)
372 max_low_pfn = end; 385 max_low_pfn = end;
373 if (start < min_low_pfn) 386 if (start < min_low_pfn)