xref: /OK3568_Linux_fs/kernel/arch/xtensa/mm/init.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * arch/xtensa/mm/init.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Derived from MIPS, PPC.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * This file is subject to the terms and conditions of the GNU General Public
7*4882a593Smuzhiyun  * License.  See the file "COPYING" in the main directory of this archive
8*4882a593Smuzhiyun  * for more details.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Copyright (C) 2001 - 2005 Tensilica Inc.
11*4882a593Smuzhiyun  * Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * Chris Zankel	<chris@zankel.net>
14*4882a593Smuzhiyun  * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
15*4882a593Smuzhiyun  * Marc Gauthier
16*4882a593Smuzhiyun  * Kevin Chea
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <linux/kernel.h>
20*4882a593Smuzhiyun #include <linux/errno.h>
21*4882a593Smuzhiyun #include <linux/memblock.h>
22*4882a593Smuzhiyun #include <linux/gfp.h>
23*4882a593Smuzhiyun #include <linux/highmem.h>
24*4882a593Smuzhiyun #include <linux/swap.h>
25*4882a593Smuzhiyun #include <linux/mman.h>
26*4882a593Smuzhiyun #include <linux/nodemask.h>
27*4882a593Smuzhiyun #include <linux/mm.h>
28*4882a593Smuzhiyun #include <linux/of_fdt.h>
29*4882a593Smuzhiyun #include <linux/dma-map-ops.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #include <asm/bootparam.h>
32*4882a593Smuzhiyun #include <asm/page.h>
33*4882a593Smuzhiyun #include <asm/sections.h>
34*4882a593Smuzhiyun #include <asm/sysmem.h>
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /*
37*4882a593Smuzhiyun  * Initialize the bootmem system and give it all low memory we have available.
38*4882a593Smuzhiyun  */
39*4882a593Smuzhiyun 
bootmem_init(void)40*4882a593Smuzhiyun void __init bootmem_init(void)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	/* Reserve all memory below PHYS_OFFSET, as memory
43*4882a593Smuzhiyun 	 * accounting doesn't work for pages below that address.
44*4882a593Smuzhiyun 	 *
45*4882a593Smuzhiyun 	 * If PHYS_OFFSET is zero reserve page at address 0:
46*4882a593Smuzhiyun 	 * successfull allocations should never return NULL.
47*4882a593Smuzhiyun 	 */
48*4882a593Smuzhiyun 	memblock_reserve(0, PHYS_OFFSET ? PHYS_OFFSET : 1);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	early_init_fdt_scan_reserved_mem();
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (!memblock_phys_mem_size())
53*4882a593Smuzhiyun 		panic("No memory found!\n");
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	min_low_pfn = PFN_UP(memblock_start_of_DRAM());
56*4882a593Smuzhiyun 	min_low_pfn = max(min_low_pfn, PFN_UP(PHYS_OFFSET));
57*4882a593Smuzhiyun 	max_pfn = PFN_DOWN(memblock_end_of_DRAM());
58*4882a593Smuzhiyun 	max_low_pfn = min(max_pfn, MAX_LOW_PFN);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	early_memtest((phys_addr_t)min_low_pfn << PAGE_SHIFT,
61*4882a593Smuzhiyun 		      (phys_addr_t)max_low_pfn << PAGE_SHIFT);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
64*4882a593Smuzhiyun 	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	memblock_dump_all();
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 
zones_init(void)70*4882a593Smuzhiyun void __init zones_init(void)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	/* All pages are DMA-able, so we put them all in the DMA zone. */
73*4882a593Smuzhiyun 	unsigned long max_zone_pfn[MAX_NR_ZONES] = {
74*4882a593Smuzhiyun 		[ZONE_NORMAL] = max_low_pfn,
75*4882a593Smuzhiyun #ifdef CONFIG_HIGHMEM
76*4882a593Smuzhiyun 		[ZONE_HIGHMEM] = max_pfn,
77*4882a593Smuzhiyun #endif
78*4882a593Smuzhiyun 	};
79*4882a593Smuzhiyun 	free_area_init(max_zone_pfn);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
free_highpages(void)82*4882a593Smuzhiyun static void __init free_highpages(void)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun #ifdef CONFIG_HIGHMEM
85*4882a593Smuzhiyun 	unsigned long max_low = max_low_pfn;
86*4882a593Smuzhiyun 	phys_addr_t range_start, range_end;
87*4882a593Smuzhiyun 	u64 i;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	/* set highmem page free */
90*4882a593Smuzhiyun 	for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
91*4882a593Smuzhiyun 				&range_start, &range_end, NULL) {
92*4882a593Smuzhiyun 		unsigned long start = PFN_UP(range_start);
93*4882a593Smuzhiyun 		unsigned long end = PFN_DOWN(range_end);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 		/* Ignore complete lowmem entries */
96*4882a593Smuzhiyun 		if (end <= max_low)
97*4882a593Smuzhiyun 			continue;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 		/* Truncate partial highmem entries */
100*4882a593Smuzhiyun 		if (start < max_low)
101*4882a593Smuzhiyun 			start = max_low;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 		for (; start < end; start++)
104*4882a593Smuzhiyun 			free_highmem_page(pfn_to_page(start));
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun #endif
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun /*
110*4882a593Smuzhiyun  * Initialize memory pages.
111*4882a593Smuzhiyun  */
112*4882a593Smuzhiyun 
mem_init(void)113*4882a593Smuzhiyun void __init mem_init(void)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	free_highpages();
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	max_mapnr = max_pfn - ARCH_PFN_OFFSET;
118*4882a593Smuzhiyun 	high_memory = (void *)__va(max_low_pfn << PAGE_SHIFT);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	memblock_free_all();
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	mem_init_print_info(NULL);
123*4882a593Smuzhiyun 	pr_info("virtual kernel memory layout:\n"
124*4882a593Smuzhiyun #ifdef CONFIG_KASAN
125*4882a593Smuzhiyun 		"    kasan   : 0x%08lx - 0x%08lx  (%5lu MB)\n"
126*4882a593Smuzhiyun #endif
127*4882a593Smuzhiyun #ifdef CONFIG_MMU
128*4882a593Smuzhiyun 		"    vmalloc : 0x%08lx - 0x%08lx  (%5lu MB)\n"
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun #ifdef CONFIG_HIGHMEM
131*4882a593Smuzhiyun 		"    pkmap   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
132*4882a593Smuzhiyun 		"    fixmap  : 0x%08lx - 0x%08lx  (%5lu kB)\n"
133*4882a593Smuzhiyun #endif
134*4882a593Smuzhiyun 		"    lowmem  : 0x%08lx - 0x%08lx  (%5lu MB)\n"
135*4882a593Smuzhiyun 		"    .text   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
136*4882a593Smuzhiyun 		"    .rodata : 0x%08lx - 0x%08lx  (%5lu kB)\n"
137*4882a593Smuzhiyun 		"    .data   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
138*4882a593Smuzhiyun 		"    .init   : 0x%08lx - 0x%08lx  (%5lu kB)\n"
139*4882a593Smuzhiyun 		"    .bss    : 0x%08lx - 0x%08lx  (%5lu kB)\n",
140*4882a593Smuzhiyun #ifdef CONFIG_KASAN
141*4882a593Smuzhiyun 		KASAN_SHADOW_START, KASAN_SHADOW_START + KASAN_SHADOW_SIZE,
142*4882a593Smuzhiyun 		KASAN_SHADOW_SIZE >> 20,
143*4882a593Smuzhiyun #endif
144*4882a593Smuzhiyun #ifdef CONFIG_MMU
145*4882a593Smuzhiyun 		VMALLOC_START, VMALLOC_END,
146*4882a593Smuzhiyun 		(VMALLOC_END - VMALLOC_START) >> 20,
147*4882a593Smuzhiyun #ifdef CONFIG_HIGHMEM
148*4882a593Smuzhiyun 		PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
149*4882a593Smuzhiyun 		(LAST_PKMAP*PAGE_SIZE) >> 10,
150*4882a593Smuzhiyun 		FIXADDR_START, FIXADDR_TOP,
151*4882a593Smuzhiyun 		(FIXADDR_TOP - FIXADDR_START) >> 10,
152*4882a593Smuzhiyun #endif
153*4882a593Smuzhiyun 		PAGE_OFFSET, PAGE_OFFSET +
154*4882a593Smuzhiyun 		(max_low_pfn - min_low_pfn) * PAGE_SIZE,
155*4882a593Smuzhiyun #else
156*4882a593Smuzhiyun 		min_low_pfn * PAGE_SIZE, max_low_pfn * PAGE_SIZE,
157*4882a593Smuzhiyun #endif
158*4882a593Smuzhiyun 		((max_low_pfn - min_low_pfn) * PAGE_SIZE) >> 20,
159*4882a593Smuzhiyun 		(unsigned long)_text, (unsigned long)_etext,
160*4882a593Smuzhiyun 		(unsigned long)(_etext - _text) >> 10,
161*4882a593Smuzhiyun 		(unsigned long)__start_rodata, (unsigned long)__end_rodata,
162*4882a593Smuzhiyun 		(unsigned long)(__end_rodata - __start_rodata) >> 10,
163*4882a593Smuzhiyun 		(unsigned long)_sdata, (unsigned long)_edata,
164*4882a593Smuzhiyun 		(unsigned long)(_edata - _sdata) >> 10,
165*4882a593Smuzhiyun 		(unsigned long)__init_begin, (unsigned long)__init_end,
166*4882a593Smuzhiyun 		(unsigned long)(__init_end - __init_begin) >> 10,
167*4882a593Smuzhiyun 		(unsigned long)__bss_start, (unsigned long)__bss_stop,
168*4882a593Smuzhiyun 		(unsigned long)(__bss_stop - __bss_start) >> 10);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
parse_memmap_one(char * p)171*4882a593Smuzhiyun static void __init parse_memmap_one(char *p)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	char *oldp;
174*4882a593Smuzhiyun 	unsigned long start_at, mem_size;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	if (!p)
177*4882a593Smuzhiyun 		return;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	oldp = p;
180*4882a593Smuzhiyun 	mem_size = memparse(p, &p);
181*4882a593Smuzhiyun 	if (p == oldp)
182*4882a593Smuzhiyun 		return;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	switch (*p) {
185*4882a593Smuzhiyun 	case '@':
186*4882a593Smuzhiyun 		start_at = memparse(p + 1, &p);
187*4882a593Smuzhiyun 		memblock_add(start_at, mem_size);
188*4882a593Smuzhiyun 		break;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	case '$':
191*4882a593Smuzhiyun 		start_at = memparse(p + 1, &p);
192*4882a593Smuzhiyun 		memblock_reserve(start_at, mem_size);
193*4882a593Smuzhiyun 		break;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	case 0:
196*4882a593Smuzhiyun 		memblock_reserve(mem_size, -mem_size);
197*4882a593Smuzhiyun 		break;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	default:
200*4882a593Smuzhiyun 		pr_warn("Unrecognized memmap syntax: %s\n", p);
201*4882a593Smuzhiyun 		break;
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
parse_memmap_opt(char * str)205*4882a593Smuzhiyun static int __init parse_memmap_opt(char *str)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	while (str) {
208*4882a593Smuzhiyun 		char *k = strchr(str, ',');
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		if (k)
211*4882a593Smuzhiyun 			*k++ = 0;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 		parse_memmap_one(str);
214*4882a593Smuzhiyun 		str = k;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun early_param("memmap", parse_memmap_opt);
220