summaryrefslogtreecommitdiffstats
path: root/arch/arc/mm
diff options
context:
space:
mode:
authorMike Rapoport <rppt@linux.ibm.com>2020-12-14 19:10:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-12-15 12:13:42 -0800
commit050b2da268f8fc4f8123f6462c430a61547b2f7b (patch)
tree7352a7be7831fd29c837e536d06037989e5801e9 /arch/arc/mm
parent4f5b0c1789963477cc9a4d45b4b62d694665cceb (diff)
arc: use FLATMEM with freeing of unused memory map instead of DISCONTIGMEM
Currently ARC uses DISCONTIGMEM to cope with sparse physical memory address space on systems with 2 memory banks. While DISCONTIGMEM avoids wasting memory on unpopulated memory map, it adds both memory and CPU overhead relatively to FLATMEM. Moreover, DISCONTINGMEM is generally considered deprecated. The obvious replacement for DISCONTIGMEM would be SPARSEMEM, but it is also less efficient than FLATMEM in pfn_to_page() and page_to_pfn() conversions. Besides it requires tuning of SECTION_SIZE which is not trivial for possible ARC memory configuration. Since the memory map for both banks is always allocated from the "lowmem" bank, it is possible to use FLATMEM for two-bank configuration and simply free the unused hole in the memory map. All is required for that is to provide ARC-specific pfn_valid() that will take into account actual physical memory configuration and define HAVE_ARCH_PFN_VALID. The resulting kernel image configured with defconfig + HIGHMEM=y is smaller: $ size a/vmlinux b/vmlinux text data bss dec hex filename 4673503 1245456 279756 6198715 5e95bb a/vmlinux 4658706 1246864 279756 6185326 5e616e b/vmlinux $ ./scripts/bloat-o-meter a/vmlinux b/vmlinux add/remove: 28/30 grow/shrink: 42/399 up/down: 10986/-29025 (-18039) ... Total: Before=4709315, After = 4691276, chg -0.38% Booting nSIM with haps_ns.dts results in the following memory usage reports: a: Memory: 1559104K/1572864K available (3531K kernel code, 595K rwdata, 752K rodata, 136K init, 275K bss, 13760K reserved, 0K cma-reserved, 1048576K highmem) b: Memory: 1559112K/1572864K available (3519K kernel code, 594K rwdata, 752K rodata, 136K init, 280K bss, 13752K reserved, 0K cma-reserved, 1048576K highmem) Link: https://lkml.kernel.org/r/20201101170454.9567-11-rppt@kernel.org Signed-off-by: Mike Rapoport <rppt@linux.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Greg Ungerer <gerg@linux-m68k.org> Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Matt Turner <mattst88@gmail.com> Cc: Meelis Roos <mroos@linux.ee> Cc: Michael Schmitz <schmitzmic@gmail.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Tony Luck <tony.luck@intel.com> Cc: Vineet Gupta <vgupta@synopsys.com> Cc: Will Deacon <will@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/arc/mm')
-rw-r--r--arch/arc/mm/init.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 3a35b82a718e..ce07e697916c 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -28,6 +28,8 @@ static unsigned long low_mem_sz;
static unsigned long min_high_pfn, max_high_pfn;
static phys_addr_t high_mem_start;
static phys_addr_t high_mem_sz;
+unsigned long arch_pfn_offset;
+EXPORT_SYMBOL(arch_pfn_offset);
#endif
#ifdef CONFIG_DISCONTIGMEM
@@ -98,16 +100,11 @@ void __init setup_arch_memory(void)
init_mm.brk = (unsigned long)_end;
/* first page of system - kernel .vector starts here */
- min_low_pfn = ARCH_PFN_OFFSET;
+ min_low_pfn = virt_to_pfn(CONFIG_LINUX_RAM_BASE);
/* Last usable page of low mem */
max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz);
-#ifdef CONFIG_FLATMEM
- /* pfn_valid() uses this */
- max_mapnr = max_low_pfn - min_low_pfn;
-#endif
-
/*------------- bootmem allocator setup -----------------------*/
/*
@@ -153,7 +150,9 @@ void __init setup_arch_memory(void)
* DISCONTIGMEM in turns requires multiple nodes. node 0 above is
* populated with normal memory zone while node 1 only has highmem
*/
+#ifdef CONFIG_DISCONTIGMEM
node_set_online(1);
+#endif
min_high_pfn = PFN_DOWN(high_mem_start);
max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
@@ -161,8 +160,15 @@ void __init setup_arch_memory(void)
max_zone_pfn[ZONE_HIGHMEM] = min_low_pfn;
high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
+
+ arch_pfn_offset = min(min_low_pfn, min_high_pfn);
kmap_init();
-#endif
+
+#else /* CONFIG_HIGHMEM */
+ /* pfn_valid() uses this when FLATMEM=y and HIGHMEM=n */
+ max_mapnr = max_low_pfn - min_low_pfn;
+
+#endif /* CONFIG_HIGHMEM */
free_area_init(max_zone_pfn);
}
@@ -190,3 +196,12 @@ void __init mem_init(void)
highmem_init();
mem_init_print_info(NULL);
}
+
+#ifdef CONFIG_HIGHMEM
+int pfn_valid(unsigned long pfn)
+{
+ return (pfn >= min_high_pfn && pfn <= max_high_pfn) ||
+ (pfn >= min_low_pfn && pfn <= max_low_pfn);
+}
+EXPORT_SYMBOL(pfn_valid);
+#endif