]> git.ipfire.org Git - people/ms/linux.git/blame - arch/arc/mm/init.c
mm: remove include/linux/bootmem.h
[people/ms/linux.git] / arch / arc / mm / init.c
CommitLineData
c121c506
VG
1/*
2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/mm.h>
c121c506 11#include <linux/memblock.h>
d6579e99
NC
12#ifdef CONFIG_BLK_DEV_INITRD
13#include <linux/initrd.h>
14#endif
1b10cb21 15#include <linux/of_fdt.h>
c121c506
VG
16#include <linux/swap.h>
17#include <linux/module.h>
29e33226 18#include <linux/highmem.h>
c121c506
VG
19#include <asm/page.h>
20#include <asm/pgalloc.h>
21#include <asm/sections.h>
22#include <asm/arcregs.h>
23
24pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
25char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
26EXPORT_SYMBOL(empty_zero_page);
27
9ed68785 28static const unsigned long low_mem_start = CONFIG_LINUX_RAM_BASE;
6101be5a 29static unsigned long low_mem_sz;
c121c506 30
29e33226 31#ifdef CONFIG_HIGHMEM
26f9d5fd 32static unsigned long min_high_pfn, max_high_pfn;
29e33226
VG
33static u64 high_mem_start;
34static u64 high_mem_sz;
35#endif
36
26f9d5fd
VG
37#ifdef CONFIG_DISCONTIGMEM
38struct pglist_data node_data[MAX_NUMNODES] __read_mostly;
39EXPORT_SYMBOL(node_data);
40#endif
41
e497c8e5
VG
42long __init arc_get_mem_sz(void)
43{
44 return low_mem_sz;
45}
46
c121c506
VG
47/* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
48static int __init setup_mem_sz(char *str)
49{
6101be5a 50 low_mem_sz = memparse(str, NULL) & PAGE_MASK;
c121c506
VG
51
52 /* early console might not be setup yet - it will show up later */
6101be5a 53 pr_info("\"mem=%s\": mem sz set to %ldM\n", str, TO_MB(low_mem_sz));
c121c506
VG
54
55 return 0;
56}
57early_param("mem", setup_mem_sz);
58
999159a5
VG
59void __init early_init_dt_add_memory_arch(u64 base, u64 size)
60{
29e33226
VG
61 int in_use = 0;
62
63 if (!low_mem_sz) {
ff1c0b6a 64 if (base != low_mem_start)
9ed68785 65 panic("CONFIG_LINUX_RAM_BASE != DT memory { }");
ff1c0b6a 66
29e33226
VG
67 low_mem_sz = size;
68 in_use = 1;
69 } else {
70#ifdef CONFIG_HIGHMEM
71 high_mem_start = base;
72 high_mem_sz = size;
73 in_use = 1;
74#endif
75 }
f759ee57 76
29e33226
VG
77 pr_info("Memory @ %llx [%lldM] %s\n",
78 base, TO_MB(size), !in_use ? "Not used":"");
999159a5
VG
79}
80
d6579e99
NC
81#ifdef CONFIG_BLK_DEV_INITRD
82static int __init early_initrd(char *p)
83{
84 unsigned long start, size;
85 char *endp;
86
87 start = memparse(p, &endp);
88 if (*endp == ',') {
89 size = memparse(endp + 1, NULL);
90
91 initrd_start = (unsigned long)__va(start);
92 initrd_end = (unsigned long)__va(start + size);
93 }
94 return 0;
95}
96early_param("initrd", early_initrd);
97#endif
98
c121c506
VG
99/*
100 * First memory setup routine called from setup_arch()
101 * 1. setup swapper's mm @init_mm
102 * 2. Count the pages we have and setup bootmem allocator
103 * 3. zone setup
104 */
105void __init setup_arch_memory(void)
106{
f2e2013f 107 unsigned long zones_size[MAX_NR_ZONES];
29e33226 108 unsigned long zones_holes[MAX_NR_ZONES];
c121c506
VG
109
110 init_mm.start_code = (unsigned long)_text;
111 init_mm.end_code = (unsigned long)_etext;
112 init_mm.end_data = (unsigned long)_edata;
113 init_mm.brk = (unsigned long)_end;
114
c121c506 115 /* first page of system - kernel .vector starts here */
f2e2013f 116 min_low_pfn = ARCH_PFN_OFFSET;
c121c506 117
6101be5a
VG
118 /* Last usable page of low mem */
119 max_low_pfn = max_pfn = PFN_DOWN(low_mem_start + low_mem_sz);
c121c506 120
26f9d5fd
VG
121#ifdef CONFIG_FLATMEM
122 /* pfn_valid() uses this */
123 max_mapnr = max_low_pfn - min_low_pfn;
29e33226
VG
124#endif
125
6101be5a 126 /*------------- bootmem allocator setup -----------------------*/
29e33226
VG
127
128 /*
129 * seed the bootmem allocator after any DT memory node parsing or
130 * "mem=xxx" cmdline overrides have potentially updated @arc_mem_sz
131 *
132 * Only low mem is added, otherwise we have crashes when allocating
133 * mem_map[] itself. NO_BOOTMEM allocates mem_map[] at the end of
134 * avail memory, ending in highmem with a > 32-bit address. However
135 * it then tries to memset it with a truncaed 32-bit handle, causing
136 * the crash
137 */
138
26f9d5fd 139 memblock_add_node(low_mem_start, low_mem_sz, 0);
6101be5a 140 memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
c121c506 141
d6579e99 142#ifdef CONFIG_BLK_DEV_INITRD
d6579e99
NC
143 if (initrd_start)
144 memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
145#endif
146
1b10cb21
AB
147 early_init_fdt_reserve_self();
148 early_init_fdt_scan_reserved_mem();
149
c121c506
VG
150 memblock_dump_all();
151
6101be5a 152 /*----------------- node/zones setup --------------------------*/
c121c506 153 memset(zones_size, 0, sizeof(zones_size));
29e33226
VG
154 memset(zones_holes, 0, sizeof(zones_holes));
155
6101be5a 156 zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
29e33226
VG
157 zones_holes[ZONE_NORMAL] = 0;
158
c121c506
VG
159 /*
160 * We can't use the helper free_area_init(zones[]) because it uses
161 * PAGE_OFFSET to compute the @min_low_pfn which would be wrong
162 * when our kernel doesn't start at PAGE_OFFSET, i.e.
9ed68785 163 * PAGE_OFFSET != CONFIG_LINUX_RAM_BASE
c121c506
VG
164 */
165 free_area_init_node(0, /* node-id */
166 zones_size, /* num pages per zone */
167 min_low_pfn, /* first pfn of node */
29e33226 168 zones_holes); /* holes */
f2e2013f 169
29e33226 170#ifdef CONFIG_HIGHMEM
26f9d5fd
VG
171 /*
172 * Populate a new node with highmem
173 *
174 * On ARC (w/o PAE) HIGHMEM addresses are actually smaller (0 based)
175 * than addresses in normal ala low memory (0x8000_0000 based).
176 * Even with PAE, the huge peripheral space hole would waste a lot of
177 * mem with single mem_map[]. This warrants a mem_map per region design.
178 * Thus HIGHMEM on ARC is imlemented with DISCONTIGMEM.
179 *
180 * DISCONTIGMEM in turns requires multiple nodes. node 0 above is
181 * populated with normal memory zone while node 1 only has highmem
182 */
183 node_set_online(1);
184
185 min_high_pfn = PFN_DOWN(high_mem_start);
186 max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
187
188 zones_size[ZONE_NORMAL] = 0;
189 zones_holes[ZONE_NORMAL] = 0;
190
191 zones_size[ZONE_HIGHMEM] = max_high_pfn - min_high_pfn;
192 zones_holes[ZONE_HIGHMEM] = 0;
193
194 free_area_init_node(1, /* node-id */
195 zones_size, /* num pages per zone */
196 min_high_pfn, /* first pfn of node */
197 zones_holes); /* holes */
198
29e33226
VG
199 high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
200 kmap_init();
201#endif
c121c506
VG
202}
203
204/*
205 * mem_init - initializes memory
206 *
207 * Frees up bootmem
208 * Calculates and displays memory available/used
209 */
210void __init mem_init(void)
211{
29e33226
VG
212#ifdef CONFIG_HIGHMEM
213 unsigned long tmp;
214
215 reset_all_zones_managed_pages();
26f9d5fd 216 for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++)
29e33226
VG
217 free_highmem_page(pfn_to_page(tmp));
218#endif
219
c6ffc5ca 220 memblock_free_all();
de35e1b8 221 mem_init_print_info(NULL);
c121c506
VG
222}
223
c121c506
VG
224/*
225 * free_initmem: Free all the __init memory.
226 */
bd721ea7 227void __ref free_initmem(void)
c121c506 228{
dbe67df4 229 free_initmem_default(-1);
c121c506
VG
230}
231
232#ifdef CONFIG_BLK_DEV_INITRD
233void __init free_initrd_mem(unsigned long start, unsigned long end)
234{
dbe67df4 235 free_reserved_area((void *)start, (void *)end, -1, "initrd");
c121c506
VG
236}
237#endif