aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-07-09 11:27:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-27 03:48:22 -0400
commit2778f62056ada442414392d7ccd41188bb631619 (patch)
treea7c15cc7ca077e5e4c2161f5062c44e408c03a08 /arch
parent4bb2e27db10abc555dfabd73661485fb75e4e97d (diff)
ARM: initial LMB trial
Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/include/asm/memblock.h15
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/mm/init.c164
-rw-r--r--arch/arm/mm/mm.h2
-rw-r--r--arch/arm/mm/mmu.c34
-rw-r--r--arch/arm/mm/nommu.c19
7 files changed, 83 insertions, 155 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 410edd65f117..36c8b5e12590 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,6 +10,7 @@ config ARM
10 default y 10 default y
11 select HAVE_AOUT 11 select HAVE_AOUT
12 select HAVE_IDE 12 select HAVE_IDE
13 select HAVE_MEMBLOCK
13 select RTC_LIB 14 select RTC_LIB
14 select SYS_SUPPORTS_APM_EMULATION 15 select SYS_SUPPORTS_APM_EMULATION
15 select GENERIC_ATOMIC64 if (!CPU_32v6K) 16 select GENERIC_ATOMIC64 if (!CPU_32v6K)
diff --git a/arch/arm/include/asm/memblock.h b/arch/arm/include/asm/memblock.h
new file mode 100644
index 000000000000..3a1d58096f44
--- /dev/null
+++ b/arch/arm/include/asm/memblock.h
@@ -0,0 +1,15 @@
1#ifndef _ASM_ARM_MEMBLOCK_H
2#define _ASM_ARM_MEMBLOCK_H
3
4#ifdef CONFIG_MMU
5extern phys_addr_t lowmem_end_addr;
6#define MEMBLOCK_REAL_LIMIT lowmem_end_addr
7#else
8#define MEMBLOCK_REAL_LIMIT 0
9#endif
10
11struct meminfo;
12
13extern void arm_memblock_init(struct meminfo *);
14
15#endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 387d2e9cb51f..dfd293477751 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -25,6 +25,7 @@
25#include <linux/smp.h> 25#include <linux/smp.h>
26#include <linux/fs.h> 26#include <linux/fs.h>
27#include <linux/proc_fs.h> 27#include <linux/proc_fs.h>
28#include <linux/memblock.h>
28 29
29#include <asm/unified.h> 30#include <asm/unified.h>
30#include <asm/cpu.h> 31#include <asm/cpu.h>
@@ -715,6 +716,8 @@ void __init setup_arch(char **cmdline_p)
715 716
716 parse_early_param(); 717 parse_early_param();
717 718
719 arm_memblock_init(&meminfo);
720
718 paging_init(mdesc); 721 paging_init(mdesc);
719 request_standard_resources(&meminfo, mdesc); 722 request_standard_resources(&meminfo, mdesc);
720 723
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 1a227eea64bd..4877e06308b7 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -17,6 +17,7 @@
17#include <linux/initrd.h> 17#include <linux/initrd.h>
18#include <linux/highmem.h> 18#include <linux/highmem.h>
19#include <linux/gfp.h> 19#include <linux/gfp.h>
20#include <linux/memblock.h>
20 21
21#include <asm/mach-types.h> 22#include <asm/mach-types.h>
22#include <asm/sections.h> 23#include <asm/sections.h>
@@ -146,95 +147,21 @@ static void __init find_limits(struct meminfo *mi,
146 } 147 }
147} 148}
148 149
149/*
150 * FIXME: We really want to avoid allocating the bootmap bitmap
151 * over the top of the initrd. Hopefully, this is located towards
152 * the start of a bank, so if we allocate the bootmap bitmap at
153 * the end, we won't clash.
154 */
155static unsigned int __init
156find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
157{
158 unsigned int start_pfn, i, bootmap_pfn;
159
160 start_pfn = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT;
161 bootmap_pfn = 0;
162
163 for_each_bank(i, mi) {
164 struct membank *bank = &mi->bank[i];
165 unsigned int start, end;
166
167 start = bank_pfn_start(bank);
168 end = bank_pfn_end(bank);
169
170 if (end < start_pfn)
171 continue;
172
173 if (start < start_pfn)
174 start = start_pfn;
175
176 if (end <= start)
177 continue;
178
179 if (end - start >= bootmap_pages) {
180 bootmap_pfn = start;
181 break;
182 }
183 }
184
185 if (bootmap_pfn == 0)
186 BUG();
187
188 return bootmap_pfn;
189}
190
191static int __init check_initrd(struct meminfo *mi)
192{
193 int initrd = -2;
194#ifdef CONFIG_BLK_DEV_INITRD
195 unsigned long end = phys_initrd_start + phys_initrd_size;
196
197 /*
198 * Make sure that the initrd is within a valid area of
199 * memory.
200 */
201 if (phys_initrd_size) {
202 unsigned int i;
203
204 initrd = -1;
205
206 for (i = 0; i < mi->nr_banks; i++) {
207 struct membank *bank = &mi->bank[i];
208 if (bank_phys_start(bank) <= phys_initrd_start &&
209 end <= bank_phys_end(bank))
210 initrd = 0;
211 }
212 }
213
214 if (initrd == -1) {
215 printk(KERN_ERR "INITRD: 0x%08lx+0x%08lx extends beyond "
216 "physical memory - disabling initrd\n",
217 phys_initrd_start, phys_initrd_size);
218 phys_initrd_start = phys_initrd_size = 0;
219 }
220#endif
221
222 return initrd;
223}
224
225static void __init arm_bootmem_init(struct meminfo *mi, 150static void __init arm_bootmem_init(struct meminfo *mi,
226 unsigned long start_pfn, unsigned long end_pfn) 151 unsigned long start_pfn, unsigned long end_pfn)
227{ 152{
228 unsigned long boot_pfn;
229 unsigned int boot_pages; 153 unsigned int boot_pages;
154 phys_addr_t bitmap;
230 pg_data_t *pgdat; 155 pg_data_t *pgdat;
231 int i; 156 int i;
232 157
233 /* 158 /*
234 * Allocate the bootmem bitmap page. 159 * Allocate the bootmem bitmap page. This must be in a region
160 * of memory which has already been mapped.
235 */ 161 */
236 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); 162 boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
237 boot_pfn = find_bootmap_pfn(mi, boot_pages); 163 bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
164 __pfn_to_phys(end_pfn));
238 165
239 /* 166 /*
240 * Initialise the bootmem allocator, handing the 167 * Initialise the bootmem allocator, handing the
@@ -242,7 +169,7 @@ static void __init arm_bootmem_init(struct meminfo *mi,
242 */ 169 */
243 node_set_online(0); 170 node_set_online(0);
244 pgdat = NODE_DATA(0); 171 pgdat = NODE_DATA(0);
245 init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn); 172 init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
246 173
247 for_each_bank(i, mi) { 174 for_each_bank(i, mi) {
248 struct membank *bank = &mi->bank[i]; 175 struct membank *bank = &mi->bank[i];
@@ -251,30 +178,16 @@ static void __init arm_bootmem_init(struct meminfo *mi,
251 } 178 }
252 179
253 /* 180 /*
254 * Reserve the bootmem bitmap. 181 * Reserve the memblock reserved regions in bootmem.
255 */ 182 */
256 reserve_bootmem(boot_pfn << PAGE_SHIFT, 183 for (i = 0; i < memblock.reserved.cnt; i++) {
257 boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); 184 phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
258} 185 if (start >= start_pfn &&
259 186 memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
260static void __init bootmem_reserve_initrd(void) 187 reserve_bootmem_node(pgdat, __pfn_to_phys(start),
261{ 188 memblock_size_bytes(&memblock.reserved, i),
262#ifdef CONFIG_BLK_DEV_INITRD 189 BOOTMEM_DEFAULT);
263 int res;
264
265 res = reserve_bootmem(phys_initrd_start,
266 phys_initrd_size, BOOTMEM_EXCLUSIVE);
267
268 if (res == 0) {
269 initrd_start = __phys_to_virt(phys_initrd_start);
270 initrd_end = initrd_start + phys_initrd_size;
271 } else {
272 printk(KERN_ERR
273 "INITRD: 0x%08lx+0x%08lx overlaps in-use "
274 "memory region - disabling initrd\n",
275 phys_initrd_start, phys_initrd_size);
276 } 190 }
277#endif
278} 191}
279 192
280static void __init arm_bootmem_free(struct meminfo *mi) 193static void __init arm_bootmem_free(struct meminfo *mi)
@@ -358,16 +271,40 @@ static void arm_memory_present(struct meminfo *mi)
358} 271}
359#endif 272#endif
360 273
274void __init arm_memblock_init(struct meminfo *mi)
275{
276 int i;
277
278 memblock_init();
279 for (i = 0; i < mi->nr_banks; i++)
280 memblock_add(mi->bank[i].start, mi->bank[i].size);
281
282 /* Register the kernel text, kernel data and initrd with memblock. */
283#ifdef CONFIG_XIP_KERNEL
284 memblock_reserve(__pa(_data), _end - _data);
285#else
286 memblock_reserve(__pa(_stext), _end - _stext);
287#endif
288#ifdef CONFIG_BLK_DEV_INITRD
289 if (phys_initrd_size) {
290 memblock_reserve(phys_initrd_start, phys_initrd_size);
291
292 /* Now convert initrd to virtual addresses */
293 initrd_start = __phys_to_virt(phys_initrd_start);
294 initrd_end = initrd_start + phys_initrd_size;
295 }
296#endif
297
298 arm_mm_memblock_reserve();
299
300 memblock_analyze();
301 memblock_dump_all();
302}
303
361void __init bootmem_init(struct machine_desc *mdesc) 304void __init bootmem_init(struct machine_desc *mdesc)
362{ 305{
363 struct meminfo *mi = &meminfo; 306 struct meminfo *mi = &meminfo;
364 unsigned long min, max_low, max_high; 307 unsigned long min, max_low, max_high;
365 int initrd;
366
367 /*
368 * Locate the ramdisk image, if any.
369 */
370 initrd = check_initrd(mi);
371 308
372 max_low = max_high = 0; 309 max_low = max_high = 0;
373 310
@@ -375,21 +312,10 @@ void __init bootmem_init(struct machine_desc *mdesc)
375 312
376 arm_bootmem_init(mi, min, max_low); 313 arm_bootmem_init(mi, min, max_low);
377 314
378 /*
379 * Reserve any special regions.
380 */
381 reserve_special_regions();
382
383 if (mdesc->reserve) 315 if (mdesc->reserve)
384 mdesc->reserve(); 316 mdesc->reserve();
385 317
386 /* 318 /*
387 * If the initrd is present, reserve its memory.
388 */
389 if (initrd == 0)
390 bootmem_reserve_initrd();
391
392 /*
393 * Sparsemem tries to allocate bootmem in memory_present(), 319 * Sparsemem tries to allocate bootmem in memory_present(),
394 * so must be done after the fixed reservations 320 * so must be done after the fixed reservations
395 */ 321 */
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index afafe4fc5431..fcfffae69b49 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -30,4 +30,4 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
30 30
31struct machine_desc; 31struct machine_desc;
32void __init bootmem_init(struct machine_desc *); 32void __init bootmem_init(struct machine_desc *);
33void reserve_special_regions(void); 33void arm_mm_memblock_reserve(void);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 05dbb956175b..833a6c3f70c0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -11,9 +11,9 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/errno.h> 12#include <linux/errno.h>
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/bootmem.h>
15#include <linux/mman.h> 14#include <linux/mman.h>
16#include <linux/nodemask.h> 15#include <linux/nodemask.h>
16#include <linux/memblock.h>
17#include <linux/sort.h> 17#include <linux/sort.h>
18 18
19#include <asm/cputype.h> 19#include <asm/cputype.h>
@@ -489,7 +489,9 @@ static void __init build_mem_type_table(void)
489 489
490static void __init *early_alloc(unsigned long sz) 490static void __init *early_alloc(unsigned long sz)
491{ 491{
492 return alloc_bootmem_low_pages(sz); 492 void *ptr = __va(memblock_alloc(sz, sz));
493 memset(ptr, 0, sz);
494 return ptr;
493} 495}
494 496
495static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot) 497static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
@@ -705,10 +707,14 @@ static int __init early_vmalloc(char *arg)
705} 707}
706early_param("vmalloc", early_vmalloc); 708early_param("vmalloc", early_vmalloc);
707 709
710phys_addr_t lowmem_end_addr;
711
708static void __init sanity_check_meminfo(void) 712static void __init sanity_check_meminfo(void)
709{ 713{
710 int i, j, highmem = 0; 714 int i, j, highmem = 0;
711 715
716 lowmem_end_addr = __pa(vmalloc_min - 1) + 1;
717
712 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 718 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
713 struct membank *bank = &meminfo.bank[j]; 719 struct membank *bank = &meminfo.bank[j];
714 *bank = meminfo.bank[i]; 720 *bank = meminfo.bank[i];
@@ -834,34 +840,22 @@ static inline void prepare_page_table(void)
834} 840}
835 841
836/* 842/*
837 * Reserve the various regions 843 * Reserve the special regions of memory
838 */ 844 */
839void __init reserve_special_regions(void) 845void __init arm_mm_memblock_reserve(void)
840{ 846{
841 /* 847 /*
842 * Register the kernel text and data with bootmem.
843 * Note that this can only be in node 0.
844 */
845#ifdef CONFIG_XIP_KERNEL
846 reserve_bootmem(__pa(_data), _end - _data, BOOTMEM_DEFAULT);
847#else
848 reserve_bootmem(__pa(_stext), _end - _stext, BOOTMEM_DEFAULT);
849#endif
850
851 /*
852 * Reserve the page tables. These are already in use, 848 * Reserve the page tables. These are already in use,
853 * and can only be in node 0. 849 * and can only be in node 0.
854 */ 850 */
855 reserve_bootmem(__pa(swapper_pg_dir), 851 memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
856 PTRS_PER_PGD * sizeof(pgd_t), BOOTMEM_DEFAULT);
857 852
858#ifdef CONFIG_SA1111 853#ifdef CONFIG_SA1111
859 /* 854 /*
860 * Because of the SA1111 DMA bug, we want to preserve our 855 * Because of the SA1111 DMA bug, we want to preserve our
861 * precious DMA-able memory... 856 * precious DMA-able memory...
862 */ 857 */
863 reserve_bootmem(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET, 858 memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
864 BOOTMEM_DEFAULT);
865#endif 859#endif
866} 860}
867 861
@@ -1004,7 +998,6 @@ void __init paging_init(struct machine_desc *mdesc)
1004 sanity_check_meminfo(); 998 sanity_check_meminfo();
1005 prepare_page_table(); 999 prepare_page_table();
1006 map_lowmem(); 1000 map_lowmem();
1007 bootmem_init(mdesc);
1008 devicemaps_init(mdesc); 1001 devicemaps_init(mdesc);
1009 kmap_init(); 1002 kmap_init();
1010 1003
@@ -1012,6 +1005,9 @@ void __init paging_init(struct machine_desc *mdesc)
1012 1005
1013 /* allocate the zero page. */ 1006 /* allocate the zero page. */
1014 zero_page = early_alloc(PAGE_SIZE); 1007 zero_page = early_alloc(PAGE_SIZE);
1008
1009 bootmem_init(mdesc);
1010
1015 empty_zero_page = virt_to_page(zero_page); 1011 empty_zero_page = virt_to_page(zero_page);
1016 __flush_dcache_page(NULL, empty_zero_page); 1012 __flush_dcache_page(NULL, empty_zero_page);
1017} 1013}
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index ed58ddbbc5b3..40e38fcccc7a 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -6,8 +6,8 @@
6#include <linux/module.h> 6#include <linux/module.h>
7#include <linux/mm.h> 7#include <linux/mm.h>
8#include <linux/pagemap.h> 8#include <linux/pagemap.h>
9#include <linux/bootmem.h>
10#include <linux/io.h> 9#include <linux/io.h>
10#include <linux/memblock.h>
11 11
12#include <asm/cacheflush.h> 12#include <asm/cacheflush.h>
13#include <asm/sections.h> 13#include <asm/sections.h>
@@ -17,27 +17,14 @@
17 17
18#include "mm.h" 18#include "mm.h"
19 19
20/* 20void __init arm_mm_memblock_reserve(void)
21 * Reserve the various regions
22 */
23void __init reserve_special_regions(void)
24{ 21{
25 /* 22 /*
26 * Register the kernel text and data with bootmem.
27 * Note that this can only be in node 0.
28 */
29#ifdef CONFIG_XIP_KERNEL
30 reserve_bootmem(__pa(_data), _end - _data, BOOTMEM_DEFAULT);
31#else
32 reserve_bootmem(__pa(_stext), _end - _stext, BOOTMEM_DEFAULT);
33#endif
34
35 /*
36 * Register the exception vector page. 23 * Register the exception vector page.
37 * some architectures which the DRAM is the exception vector to trap, 24 * some architectures which the DRAM is the exception vector to trap,
38 * alloc_page breaks with error, although it is not NULL, but "0." 25 * alloc_page breaks with error, although it is not NULL, but "0."
39 */ 26 */
40 reserve_bootmem(CONFIG_VECTORS_BASE, PAGE_SIZE, BOOTMEM_DEFAULT); 27 memblock_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE);
41} 28}
42 29
43/* 30/*