diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2016-04-25 15:08:20 -0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2016-07-23 23:34:00 -0400 |
commit | 0e46c1115f5816949220d62dd3ff04aa68e7ac6b (patch) | |
tree | 2a2ed0cfd8424a3090432128a865f02c009e9214 | |
parent | 3de00482b006daa110151ac6775adc52538a3d6a (diff) |
xtensa: drop sysmem and switch to memblock
Memblock is the standard kernel boot-time memory tracker/allocator. Use
it instead of the custom sysmem allocator. This allows using kmemleak,
CMA and device tree memory reservation.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r-- | arch/xtensa/Kconfig | 3 | ||||
-rw-r--r-- | arch/xtensa/include/asm/sysmem.h | 21 | ||||
-rw-r--r-- | arch/xtensa/kernel/setup.c | 36 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 272 |
4 files changed, 40 insertions, 292 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 7a4c77b39ce0..d20ddf7bf6a9 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -13,16 +13,19 @@ config XTENSA | |||
13 | select GENERIC_IRQ_SHOW | 13 | select GENERIC_IRQ_SHOW |
14 | select GENERIC_PCI_IOMAP | 14 | select GENERIC_PCI_IOMAP |
15 | select GENERIC_SCHED_CLOCK | 15 | select GENERIC_SCHED_CLOCK |
16 | select HAVE_DEBUG_KMEMLEAK | ||
16 | select HAVE_DMA_API_DEBUG | 17 | select HAVE_DMA_API_DEBUG |
17 | select HAVE_EXIT_THREAD | 18 | select HAVE_EXIT_THREAD |
18 | select HAVE_FUNCTION_TRACER | 19 | select HAVE_FUNCTION_TRACER |
19 | select HAVE_FUTEX_CMPXCHG if !MMU | 20 | select HAVE_FUTEX_CMPXCHG if !MMU |
20 | select HAVE_HW_BREAKPOINT if PERF_EVENTS | 21 | select HAVE_HW_BREAKPOINT if PERF_EVENTS |
21 | select HAVE_IRQ_TIME_ACCOUNTING | 22 | select HAVE_IRQ_TIME_ACCOUNTING |
23 | select HAVE_MEMBLOCK | ||
22 | select HAVE_OPROFILE | 24 | select HAVE_OPROFILE |
23 | select HAVE_PERF_EVENTS | 25 | select HAVE_PERF_EVENTS |
24 | select IRQ_DOMAIN | 26 | select IRQ_DOMAIN |
25 | select MODULES_USE_ELF_RELA | 27 | select MODULES_USE_ELF_RELA |
28 | select NO_BOOTMEM | ||
26 | select PERF_USE_VMALLOC | 29 | select PERF_USE_VMALLOC |
27 | select VIRT_TO_BUS | 30 | select VIRT_TO_BUS |
28 | help | 31 | help |
diff --git a/arch/xtensa/include/asm/sysmem.h b/arch/xtensa/include/asm/sysmem.h index c015c5c8e3f7..552cdfd8590e 100644 --- a/arch/xtensa/include/asm/sysmem.h +++ b/arch/xtensa/include/asm/sysmem.h | |||
@@ -11,27 +11,8 @@ | |||
11 | #ifndef _XTENSA_SYSMEM_H | 11 | #ifndef _XTENSA_SYSMEM_H |
12 | #define _XTENSA_SYSMEM_H | 12 | #define _XTENSA_SYSMEM_H |
13 | 13 | ||
14 | #define SYSMEM_BANKS_MAX 31 | 14 | #include <linux/memblock.h> |
15 | 15 | ||
16 | struct meminfo { | ||
17 | unsigned long start; | ||
18 | unsigned long end; | ||
19 | }; | ||
20 | |||
21 | /* | ||
22 | * Bank array is sorted by .start. | ||
23 | * Banks don't overlap and there's at least one page gap | ||
24 | * between adjacent bank entries. | ||
25 | */ | ||
26 | struct sysmem_info { | ||
27 | int nr_banks; | ||
28 | struct meminfo bank[SYSMEM_BANKS_MAX]; | ||
29 | }; | ||
30 | |||
31 | extern struct sysmem_info sysmem; | ||
32 | |||
33 | int add_sysmem_bank(unsigned long start, unsigned long end); | ||
34 | int mem_reserve(unsigned long, unsigned long, int); | ||
35 | void bootmem_init(void); | 16 | void bootmem_init(void); |
36 | void zones_init(void); | 17 | void zones_init(void); |
37 | 18 | ||
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 0e59b8900e6a..393206b6aabc 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright (C) 1995 Linus Torvalds | 8 | * Copyright (C) 1995 Linus Torvalds |
9 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 9 | * Copyright (C) 2001 - 2005 Tensilica Inc. |
10 | * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. | ||
10 | * | 11 | * |
11 | * Chris Zankel <chris@zankel.net> | 12 | * Chris Zankel <chris@zankel.net> |
12 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | 13 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> |
@@ -24,6 +25,7 @@ | |||
24 | #include <linux/percpu.h> | 25 | #include <linux/percpu.h> |
25 | #include <linux/clk-provider.h> | 26 | #include <linux/clk-provider.h> |
26 | #include <linux/cpu.h> | 27 | #include <linux/cpu.h> |
28 | #include <linux/of.h> | ||
27 | #include <linux/of_fdt.h> | 29 | #include <linux/of_fdt.h> |
28 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
29 | 31 | ||
@@ -114,7 +116,7 @@ static int __init parse_tag_mem(const bp_tag_t *tag) | |||
114 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) | 116 | if (mi->type != MEMORY_TYPE_CONVENTIONAL) |
115 | return -1; | 117 | return -1; |
116 | 118 | ||
117 | return add_sysmem_bank(mi->start, mi->end); | 119 | return memblock_add(mi->start, mi->end - mi->start); |
118 | } | 120 | } |
119 | 121 | ||
120 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); | 122 | __tagtable(BP_TAG_MEMORY, parse_tag_mem); |
@@ -228,7 +230,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, | |||
228 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | 230 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
229 | { | 231 | { |
230 | size &= PAGE_MASK; | 232 | size &= PAGE_MASK; |
231 | add_sysmem_bank(base, base + size); | 233 | memblock_add(base, size); |
232 | } | 234 | } |
233 | 235 | ||
234 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | 236 | void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) |
@@ -440,6 +442,10 @@ static int __init check_s32c1i(void) | |||
440 | early_initcall(check_s32c1i); | 442 | early_initcall(check_s32c1i); |
441 | #endif /* CONFIG_S32C1I_SELFTEST */ | 443 | #endif /* CONFIG_S32C1I_SELFTEST */ |
442 | 444 | ||
445 | static inline int mem_reserve(unsigned long start, unsigned long end) | ||
446 | { | ||
447 | return memblock_reserve(start, end - start); | ||
448 | } | ||
443 | 449 | ||
444 | void __init setup_arch(char **cmdline_p) | 450 | void __init setup_arch(char **cmdline_p) |
445 | { | 451 | { |
@@ -451,54 +457,54 @@ void __init setup_arch(char **cmdline_p) | |||
451 | #ifdef CONFIG_BLK_DEV_INITRD | 457 | #ifdef CONFIG_BLK_DEV_INITRD |
452 | if (initrd_start < initrd_end) { | 458 | if (initrd_start < initrd_end) { |
453 | initrd_is_mapped = mem_reserve(__pa(initrd_start), | 459 | initrd_is_mapped = mem_reserve(__pa(initrd_start), |
454 | __pa(initrd_end), 0) == 0; | 460 | __pa(initrd_end)) == 0; |
455 | initrd_below_start_ok = 1; | 461 | initrd_below_start_ok = 1; |
456 | } else { | 462 | } else { |
457 | initrd_start = 0; | 463 | initrd_start = 0; |
458 | } | 464 | } |
459 | #endif | 465 | #endif |
460 | 466 | ||
461 | mem_reserve(__pa(&_stext),__pa(&_end), 1); | 467 | mem_reserve(__pa(&_stext), __pa(&_end)); |
462 | 468 | ||
463 | mem_reserve(__pa(&_WindowVectors_text_start), | 469 | mem_reserve(__pa(&_WindowVectors_text_start), |
464 | __pa(&_WindowVectors_text_end), 0); | 470 | __pa(&_WindowVectors_text_end)); |
465 | 471 | ||
466 | mem_reserve(__pa(&_DebugInterruptVector_literal_start), | 472 | mem_reserve(__pa(&_DebugInterruptVector_literal_start), |
467 | __pa(&_DebugInterruptVector_text_end), 0); | 473 | __pa(&_DebugInterruptVector_text_end)); |
468 | 474 | ||
469 | mem_reserve(__pa(&_KernelExceptionVector_literal_start), | 475 | mem_reserve(__pa(&_KernelExceptionVector_literal_start), |
470 | __pa(&_KernelExceptionVector_text_end), 0); | 476 | __pa(&_KernelExceptionVector_text_end)); |
471 | 477 | ||
472 | mem_reserve(__pa(&_UserExceptionVector_literal_start), | 478 | mem_reserve(__pa(&_UserExceptionVector_literal_start), |
473 | __pa(&_UserExceptionVector_text_end), 0); | 479 | __pa(&_UserExceptionVector_text_end)); |
474 | 480 | ||
475 | mem_reserve(__pa(&_DoubleExceptionVector_literal_start), | 481 | mem_reserve(__pa(&_DoubleExceptionVector_literal_start), |
476 | __pa(&_DoubleExceptionVector_text_end), 0); | 482 | __pa(&_DoubleExceptionVector_text_end)); |
477 | 483 | ||
478 | #if XCHAL_EXCM_LEVEL >= 2 | 484 | #if XCHAL_EXCM_LEVEL >= 2 |
479 | mem_reserve(__pa(&_Level2InterruptVector_text_start), | 485 | mem_reserve(__pa(&_Level2InterruptVector_text_start), |
480 | __pa(&_Level2InterruptVector_text_end), 0); | 486 | __pa(&_Level2InterruptVector_text_end)); |
481 | #endif | 487 | #endif |
482 | #if XCHAL_EXCM_LEVEL >= 3 | 488 | #if XCHAL_EXCM_LEVEL >= 3 |
483 | mem_reserve(__pa(&_Level3InterruptVector_text_start), | 489 | mem_reserve(__pa(&_Level3InterruptVector_text_start), |
484 | __pa(&_Level3InterruptVector_text_end), 0); | 490 | __pa(&_Level3InterruptVector_text_end)); |
485 | #endif | 491 | #endif |
486 | #if XCHAL_EXCM_LEVEL >= 4 | 492 | #if XCHAL_EXCM_LEVEL >= 4 |
487 | mem_reserve(__pa(&_Level4InterruptVector_text_start), | 493 | mem_reserve(__pa(&_Level4InterruptVector_text_start), |
488 | __pa(&_Level4InterruptVector_text_end), 0); | 494 | __pa(&_Level4InterruptVector_text_end)); |
489 | #endif | 495 | #endif |
490 | #if XCHAL_EXCM_LEVEL >= 5 | 496 | #if XCHAL_EXCM_LEVEL >= 5 |
491 | mem_reserve(__pa(&_Level5InterruptVector_text_start), | 497 | mem_reserve(__pa(&_Level5InterruptVector_text_start), |
492 | __pa(&_Level5InterruptVector_text_end), 0); | 498 | __pa(&_Level5InterruptVector_text_end)); |
493 | #endif | 499 | #endif |
494 | #if XCHAL_EXCM_LEVEL >= 6 | 500 | #if XCHAL_EXCM_LEVEL >= 6 |
495 | mem_reserve(__pa(&_Level6InterruptVector_text_start), | 501 | mem_reserve(__pa(&_Level6InterruptVector_text_start), |
496 | __pa(&_Level6InterruptVector_text_end), 0); | 502 | __pa(&_Level6InterruptVector_text_end)); |
497 | #endif | 503 | #endif |
498 | 504 | ||
499 | #ifdef CONFIG_SMP | 505 | #ifdef CONFIG_SMP |
500 | mem_reserve(__pa(&_SecondaryResetVector_text_start), | 506 | mem_reserve(__pa(&_SecondaryResetVector_text_start), |
501 | __pa(&_SecondaryResetVector_text_end), 0); | 507 | __pa(&_SecondaryResetVector_text_end)); |
502 | #endif | 508 | #endif |
503 | parse_early_param(); | 509 | parse_early_param(); |
504 | bootmem_init(); | 510 | bootmem_init(); |
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 302fa72d0d5a..3ee7e29603af 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * for more details. | 8 | * for more details. |
9 | * | 9 | * |
10 | * Copyright (C) 2001 - 2005 Tensilica Inc. | 10 | * Copyright (C) 2001 - 2005 Tensilica Inc. |
11 | * Copyright (C) 2014 Cadence Design Systems Inc. | 11 | * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. |
12 | * | 12 | * |
13 | * Chris Zankel <chris@zankel.net> | 13 | * Chris Zankel <chris@zankel.net> |
14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | 14 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> |
@@ -31,277 +31,35 @@ | |||
31 | #include <asm/sections.h> | 31 | #include <asm/sections.h> |
32 | #include <asm/sysmem.h> | 32 | #include <asm/sysmem.h> |
33 | 33 | ||
34 | struct sysmem_info sysmem __initdata; | ||
35 | |||
36 | static void __init sysmem_dump(void) | ||
37 | { | ||
38 | unsigned i; | ||
39 | |||
40 | pr_debug("Sysmem:\n"); | ||
41 | for (i = 0; i < sysmem.nr_banks; ++i) | ||
42 | pr_debug(" 0x%08lx - 0x%08lx (%ldK)\n", | ||
43 | sysmem.bank[i].start, sysmem.bank[i].end, | ||
44 | (sysmem.bank[i].end - sysmem.bank[i].start) >> 10); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * Find bank with maximal .start such that bank.start <= start | ||
49 | */ | ||
50 | static inline struct meminfo * __init find_bank(unsigned long start) | ||
51 | { | ||
52 | unsigned i; | ||
53 | struct meminfo *it = NULL; | ||
54 | |||
55 | for (i = 0; i < sysmem.nr_banks; ++i) | ||
56 | if (sysmem.bank[i].start <= start) | ||
57 | it = sysmem.bank + i; | ||
58 | else | ||
59 | break; | ||
60 | return it; | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Move all memory banks starting at 'from' to a new place at 'to', | ||
65 | * adjust nr_banks accordingly. | ||
66 | * Both 'from' and 'to' must be inside the sysmem.bank. | ||
67 | * | ||
68 | * Returns: 0 (success), -ENOMEM (not enough space in the sysmem.bank). | ||
69 | */ | ||
70 | static int __init move_banks(struct meminfo *to, struct meminfo *from) | ||
71 | { | ||
72 | unsigned n = sysmem.nr_banks - (from - sysmem.bank); | ||
73 | |||
74 | if (to > from && to - from + sysmem.nr_banks > SYSMEM_BANKS_MAX) | ||
75 | return -ENOMEM; | ||
76 | if (to != from) | ||
77 | memmove(to, from, n * sizeof(struct meminfo)); | ||
78 | sysmem.nr_banks += to - from; | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Add new bank to sysmem. Resulting sysmem is the union of bytes of the | ||
84 | * original sysmem and the new bank. | ||
85 | * | ||
86 | * Returns: 0 (success), < 0 (error) | ||
87 | */ | ||
88 | int __init add_sysmem_bank(unsigned long start, unsigned long end) | ||
89 | { | ||
90 | unsigned i; | ||
91 | struct meminfo *it = NULL; | ||
92 | unsigned long sz; | ||
93 | unsigned long bank_sz = 0; | ||
94 | |||
95 | if (start == end || | ||
96 | (start < end) != (PAGE_ALIGN(start) < (end & PAGE_MASK))) { | ||
97 | pr_warn("Ignoring small memory bank 0x%08lx size: %ld bytes\n", | ||
98 | start, end - start); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | start = PAGE_ALIGN(start); | ||
103 | end &= PAGE_MASK; | ||
104 | sz = end - start; | ||
105 | |||
106 | it = find_bank(start); | ||
107 | |||
108 | if (it) | ||
109 | bank_sz = it->end - it->start; | ||
110 | |||
111 | if (it && bank_sz >= start - it->start) { | ||
112 | if (end - it->start > bank_sz) | ||
113 | it->end = end; | ||
114 | else | ||
115 | return 0; | ||
116 | } else { | ||
117 | if (!it) | ||
118 | it = sysmem.bank; | ||
119 | else | ||
120 | ++it; | ||
121 | |||
122 | if (it - sysmem.bank < sysmem.nr_banks && | ||
123 | it->start - start <= sz) { | ||
124 | it->start = start; | ||
125 | if (it->end - it->start < sz) | ||
126 | it->end = end; | ||
127 | else | ||
128 | return 0; | ||
129 | } else { | ||
130 | if (move_banks(it + 1, it) < 0) { | ||
131 | pr_warn("Ignoring memory bank 0x%08lx size %ld bytes\n", | ||
132 | start, end - start); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | it->start = start; | ||
136 | it->end = end; | ||
137 | return 0; | ||
138 | } | ||
139 | } | ||
140 | sz = it->end - it->start; | ||
141 | for (i = it + 1 - sysmem.bank; i < sysmem.nr_banks; ++i) | ||
142 | if (sysmem.bank[i].start - it->start <= sz) { | ||
143 | if (sz < sysmem.bank[i].end - it->start) | ||
144 | it->end = sysmem.bank[i].end; | ||
145 | } else { | ||
146 | break; | ||
147 | } | ||
148 | |||
149 | move_banks(it + 1, sysmem.bank + i); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * mem_reserve(start, end, must_exist) | ||
155 | * | ||
156 | * Reserve some memory from the memory pool. | ||
157 | * If must_exist is set and a part of the region being reserved does not exist | ||
158 | * memory map is not altered. | ||
159 | * | ||
160 | * Parameters: | ||
161 | * start Start of region, | ||
162 | * end End of region, | ||
163 | * must_exist Must exist in memory pool. | ||
164 | * | ||
165 | * Returns: | ||
166 | * 0 (success) | ||
167 | * < 0 (error) | ||
168 | */ | ||
169 | |||
170 | int __init mem_reserve(unsigned long start, unsigned long end, int must_exist) | ||
171 | { | ||
172 | struct meminfo *it; | ||
173 | struct meminfo *rm = NULL; | ||
174 | unsigned long sz; | ||
175 | unsigned long bank_sz = 0; | ||
176 | |||
177 | start = start & PAGE_MASK; | ||
178 | end = PAGE_ALIGN(end); | ||
179 | sz = end - start; | ||
180 | if (!sz) | ||
181 | return -EINVAL; | ||
182 | |||
183 | it = find_bank(start); | ||
184 | |||
185 | if (it) | ||
186 | bank_sz = it->end - it->start; | ||
187 | |||
188 | if ((!it || end - it->start > bank_sz) && must_exist) { | ||
189 | pr_warn("mem_reserve: [0x%0lx, 0x%0lx) not in any region!\n", | ||
190 | start, end); | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | if (it && start - it->start <= bank_sz) { | ||
195 | if (start == it->start) { | ||
196 | if (end - it->start < bank_sz) { | ||
197 | it->start = end; | ||
198 | return 0; | ||
199 | } else { | ||
200 | rm = it; | ||
201 | } | ||
202 | } else { | ||
203 | it->end = start; | ||
204 | if (end - it->start < bank_sz) | ||
205 | return add_sysmem_bank(end, | ||
206 | it->start + bank_sz); | ||
207 | ++it; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | if (!it) | ||
212 | it = sysmem.bank; | ||
213 | |||
214 | for (; it < sysmem.bank + sysmem.nr_banks; ++it) { | ||
215 | if (it->end - start <= sz) { | ||
216 | if (!rm) | ||
217 | rm = it; | ||
218 | } else { | ||
219 | if (it->start - start < sz) | ||
220 | it->start = end; | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if (rm) | ||
226 | move_banks(rm, it); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | /* | 34 | /* |
233 | * Initialize the bootmem system and give it all low memory we have available. | 35 | * Initialize the bootmem system and give it all low memory we have available. |
234 | */ | 36 | */ |
235 | 37 | ||
236 | void __init bootmem_init(void) | 38 | void __init bootmem_init(void) |
237 | { | 39 | { |
238 | unsigned long pfn; | 40 | /* Reserve all memory below PHYS_OFFSET, as memory |
239 | unsigned long bootmap_start, bootmap_size; | ||
240 | int i; | ||
241 | |||
242 | /* Reserve all memory below PLATFORM_DEFAULT_MEM_START, as memory | ||
243 | * accounting doesn't work for pages below that address. | 41 | * accounting doesn't work for pages below that address. |
244 | * | 42 | * |
245 | * If PLATFORM_DEFAULT_MEM_START is zero reserve page at address 0: | 43 | * If PHYS_OFFSET is zero reserve page at address 0: |
246 | * successfull allocations should never return NULL. | 44 | * successfull allocations should never return NULL. |
247 | */ | 45 | */ |
248 | if (PLATFORM_DEFAULT_MEM_START) | 46 | if (PHYS_OFFSET) |
249 | mem_reserve(0, PLATFORM_DEFAULT_MEM_START, 0); | 47 | memblock_reserve(0, PHYS_OFFSET); |
250 | else | 48 | else |
251 | mem_reserve(0, 1, 0); | 49 | memblock_reserve(0, 1); |
252 | 50 | ||
253 | sysmem_dump(); | ||
254 | max_low_pfn = max_pfn = 0; | ||
255 | min_low_pfn = ~0; | ||
256 | |||
257 | for (i=0; i < sysmem.nr_banks; i++) { | ||
258 | pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT; | ||
259 | if (pfn < min_low_pfn) | ||
260 | min_low_pfn = pfn; | ||
261 | pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT; | ||
262 | if (pfn > max_pfn) | ||
263 | max_pfn = pfn; | ||
264 | } | ||
265 | 51 | ||
266 | if (min_low_pfn > max_pfn) | 52 | if (!memblock_phys_mem_size()) |
267 | panic("No memory found!\n"); | 53 | panic("No memory found!\n"); |
268 | 54 | ||
55 | min_low_pfn = PFN_UP(memblock_start_of_DRAM()); | ||
56 | min_low_pfn = max(min_low_pfn, PFN_UP(PHYS_OFFSET)); | ||
57 | max_pfn = PFN_DOWN(memblock_end_of_DRAM()); | ||
269 | max_low_pfn = min(max_pfn, MAX_LOW_PFN); | 58 | max_low_pfn = min(max_pfn, MAX_LOW_PFN); |
270 | 59 | ||
271 | /* Find an area to use for the bootmem bitmap. */ | 60 | memblock_set_current_limit(PFN_PHYS(max_low_pfn)); |
272 | |||
273 | bootmap_size = bootmem_bootmap_pages(max_low_pfn - min_low_pfn); | ||
274 | bootmap_size <<= PAGE_SHIFT; | ||
275 | bootmap_start = ~0; | ||
276 | |||
277 | for (i=0; i<sysmem.nr_banks; i++) | ||
278 | if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) { | ||
279 | bootmap_start = sysmem.bank[i].start; | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | if (bootmap_start == ~0UL) | ||
284 | panic("Cannot find %ld bytes for bootmap\n", bootmap_size); | ||
285 | |||
286 | /* Reserve the bootmem bitmap area */ | ||
287 | |||
288 | mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1); | ||
289 | bootmap_size = init_bootmem_node(NODE_DATA(0), | ||
290 | bootmap_start >> PAGE_SHIFT, | ||
291 | min_low_pfn, | ||
292 | max_low_pfn); | ||
293 | |||
294 | /* Add all remaining memory pieces into the bootmem map */ | ||
295 | |||
296 | for (i = 0; i < sysmem.nr_banks; i++) { | ||
297 | if (sysmem.bank[i].start >> PAGE_SHIFT < max_low_pfn) { | ||
298 | unsigned long end = min(max_low_pfn << PAGE_SHIFT, | ||
299 | sysmem.bank[i].end); | ||
300 | free_bootmem(sysmem.bank[i].start, | ||
301 | end - sysmem.bank[i].start); | ||
302 | } | ||
303 | } | ||
304 | 61 | ||
62 | memblock_dump_all(); | ||
305 | } | 63 | } |
306 | 64 | ||
307 | 65 | ||
@@ -394,16 +152,16 @@ static void __init parse_memmap_one(char *p) | |||
394 | switch (*p) { | 152 | switch (*p) { |
395 | case '@': | 153 | case '@': |
396 | start_at = memparse(p + 1, &p); | 154 | start_at = memparse(p + 1, &p); |
397 | add_sysmem_bank(start_at, start_at + mem_size); | 155 | memblock_add(start_at, mem_size); |
398 | break; | 156 | break; |
399 | 157 | ||
400 | case '$': | 158 | case '$': |
401 | start_at = memparse(p + 1, &p); | 159 | start_at = memparse(p + 1, &p); |
402 | mem_reserve(start_at, start_at + mem_size, 0); | 160 | memblock_reserve(start_at, mem_size); |
403 | break; | 161 | break; |
404 | 162 | ||
405 | case 0: | 163 | case 0: |
406 | mem_reserve(mem_size, 0, 0); | 164 | memblock_reserve(mem_size, -mem_size); |
407 | break; | 165 | break; |
408 | 166 | ||
409 | default: | 167 | default: |