aboutsummaryrefslogtreecommitdiffstats
path: root/mm/nobootmem.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /mm/nobootmem.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'mm/nobootmem.c')
-rw-r--r--mm/nobootmem.c190
1 files changed, 81 insertions, 109 deletions
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index b8294fc03df..6e93dc7f258 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -12,7 +12,7 @@
12#include <linux/pfn.h> 12#include <linux/pfn.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/bootmem.h> 14#include <linux/bootmem.h>
15#include <linux/export.h> 15#include <linux/module.h>
16#include <linux/kmemleak.h> 16#include <linux/kmemleak.h>
17#include <linux/range.h> 17#include <linux/range.h>
18#include <linux/memblock.h> 18#include <linux/memblock.h>
@@ -41,13 +41,14 @@ static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
41 if (limit > memblock.current_limit) 41 if (limit > memblock.current_limit)
42 limit = memblock.current_limit; 42 limit = memblock.current_limit;
43 43
44 addr = memblock_find_in_range_node(goal, limit, size, align, nid); 44 addr = find_memory_core_early(nid, size, align, goal, limit);
45 if (!addr) 45
46 if (addr == MEMBLOCK_ERROR)
46 return NULL; 47 return NULL;
47 48
48 ptr = phys_to_virt(addr); 49 ptr = phys_to_virt(addr);
49 memset(ptr, 0, size); 50 memset(ptr, 0, size);
50 memblock_reserve(addr, size); 51 memblock_x86_reserve_range(addr, addr + size, "BOOTMEM");
51 /* 52 /*
52 * The min_count is set to 0 so that bootmem allocated blocks 53 * The min_count is set to 0 so that bootmem allocated blocks
53 * are never reported as leaks. 54 * are never reported as leaks.
@@ -82,7 +83,8 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
82 83
83static void __init __free_pages_memory(unsigned long start, unsigned long end) 84static void __init __free_pages_memory(unsigned long start, unsigned long end)
84{ 85{
85 unsigned long i, start_aligned, end_aligned; 86 int i;
87 unsigned long start_aligned, end_aligned;
86 int order = ilog2(BITS_PER_LONG); 88 int order = ilog2(BITS_PER_LONG);
87 89
88 start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); 90 start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
@@ -105,54 +107,26 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end)
105 __free_pages_bootmem(pfn_to_page(i), 0); 107 __free_pages_bootmem(pfn_to_page(i), 0);
106} 108}
107 109
108static unsigned long __init __free_memory_core(phys_addr_t start, 110unsigned long __init free_all_memory_core_early(int nodeid)
109 phys_addr_t end)
110{
111 unsigned long start_pfn = PFN_UP(start);
112 unsigned long end_pfn = min_t(unsigned long,
113 PFN_DOWN(end), max_low_pfn);
114
115 if (start_pfn > end_pfn)
116 return 0;
117
118 __free_pages_memory(start_pfn, end_pfn);
119
120 return end_pfn - start_pfn;
121}
122
123unsigned long __init free_low_memory_core_early(int nodeid)
124{ 111{
112 int i;
113 u64 start, end;
125 unsigned long count = 0; 114 unsigned long count = 0;
126 phys_addr_t start, end, size; 115 struct range *range = NULL;
127 u64 i; 116 int nr_range;
128 117
129 for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) 118 nr_range = get_free_all_memory_range(&range, nodeid);
130 count += __free_memory_core(start, end);
131 119
132 /* free range that is used for reserved array if we allocate it */ 120 for (i = 0; i < nr_range; i++) {
133 size = get_allocated_memblock_reserved_regions_info(&start); 121 start = range[i].start;
134 if (size) 122 end = range[i].end;
135 count += __free_memory_core(start, start + size); 123 count += end - start;
124 __free_pages_memory(start, end);
125 }
136 126
137 return count; 127 return count;
138} 128}
139 129
140static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
141{
142 struct zone *z;
143
144 /*
145 * In free_area_init_core(), highmem zone's managed_pages is set to
146 * present_pages, and bootmem allocator doesn't allocate from highmem
147 * zones. So there's no need to recalculate managed_pages because all
148 * highmem pages will be managed by the buddy system. Here highmem
149 * zone also includes highmem movable zone.
150 */
151 for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
152 if (!is_highmem(z))
153 z->managed_pages = 0;
154}
155
156/** 130/**
157 * free_all_bootmem_node - release a node's free pages to the buddy allocator 131 * free_all_bootmem_node - release a node's free pages to the buddy allocator
158 * @pgdat: node to be released 132 * @pgdat: node to be released
@@ -162,9 +136,8 @@ static void reset_node_lowmem_managed_pages(pg_data_t *pgdat)
162unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) 136unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
163{ 137{
164 register_page_bootmem_info_node(pgdat); 138 register_page_bootmem_info_node(pgdat);
165 reset_node_lowmem_managed_pages(pgdat);
166 139
167 /* free_low_memory_core_early(MAX_NUMNODES) will be called later */ 140 /* free_all_memory_core_early(MAX_NUMNODES) will be called later */
168 return 0; 141 return 0;
169} 142}
170 143
@@ -175,17 +148,14 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
175 */ 148 */
176unsigned long __init free_all_bootmem(void) 149unsigned long __init free_all_bootmem(void)
177{ 150{
178 struct pglist_data *pgdat;
179
180 for_each_online_pgdat(pgdat)
181 reset_node_lowmem_managed_pages(pgdat);
182
183 /* 151 /*
184 * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id 152 * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id
185 * because in some case like Node0 doesn't have RAM installed 153 * because in some case like Node0 doesn't have RAM installed
186 * low ram will be on Node1 154 * low ram will be on Node1
155 * Use MAX_NUMNODES will make sure all ranges in early_node_map[]
156 * will be used instead of only Node0 related
187 */ 157 */
188 return free_low_memory_core_early(MAX_NUMNODES); 158 return free_all_memory_core_early(MAX_NUMNODES);
189} 159}
190 160
191/** 161/**
@@ -202,7 +172,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
202 unsigned long size) 172 unsigned long size)
203{ 173{
204 kmemleak_free_part(__va(physaddr), size); 174 kmemleak_free_part(__va(physaddr), size);
205 memblock_free(physaddr, size); 175 memblock_x86_free_range(physaddr, physaddr + size);
206} 176}
207 177
208/** 178/**
@@ -217,7 +187,7 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
217void __init free_bootmem(unsigned long addr, unsigned long size) 187void __init free_bootmem(unsigned long addr, unsigned long size)
218{ 188{
219 kmemleak_free_part(__va(addr), size); 189 kmemleak_free_part(__va(addr), size);
220 memblock_free(addr, size); 190 memblock_x86_free_range(addr, addr + size);
221} 191}
222 192
223static void * __init ___alloc_bootmem_nopanic(unsigned long size, 193static void * __init ___alloc_bootmem_nopanic(unsigned long size,
@@ -302,57 +272,6 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
302 return ___alloc_bootmem(size, align, goal, limit); 272 return ___alloc_bootmem(size, align, goal, limit);
303} 273}
304 274
305void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
306 unsigned long size,
307 unsigned long align,
308 unsigned long goal,
309 unsigned long limit)
310{
311 void *ptr;
312
313again:
314 ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
315 goal, limit);
316 if (ptr)
317 return ptr;
318
319 ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
320 goal, limit);
321 if (ptr)
322 return ptr;
323
324 if (goal) {
325 goal = 0;
326 goto again;
327 }
328
329 return NULL;
330}
331
332void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
333 unsigned long align, unsigned long goal)
334{
335 if (WARN_ON_ONCE(slab_is_available()))
336 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
337
338 return ___alloc_bootmem_node_nopanic(pgdat, size, align, goal, 0);
339}
340
341void * __init ___alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
342 unsigned long align, unsigned long goal,
343 unsigned long limit)
344{
345 void *ptr;
346
347 ptr = ___alloc_bootmem_node_nopanic(pgdat, size, align, goal, limit);
348 if (ptr)
349 return ptr;
350
351 printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
352 panic("Out of memory");
353 return NULL;
354}
355
356/** 275/**
357 * __alloc_bootmem_node - allocate boot memory from a specific node 276 * __alloc_bootmem_node - allocate boot memory from a specific node
358 * @pgdat: node to allocate from 277 * @pgdat: node to allocate from
@@ -371,10 +290,18 @@ void * __init ___alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
371void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, 290void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
372 unsigned long align, unsigned long goal) 291 unsigned long align, unsigned long goal)
373{ 292{
293 void *ptr;
294
374 if (WARN_ON_ONCE(slab_is_available())) 295 if (WARN_ON_ONCE(slab_is_available()))
375 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); 296 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
376 297
377 return ___alloc_bootmem_node(pgdat, size, align, goal, 0); 298 ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
299 goal, -1ULL);
300 if (ptr)
301 return ptr;
302
303 return __alloc_memory_core_early(MAX_NUMNODES, size, align,
304 goal, -1ULL);
378} 305}
379 306
380void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, 307void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
@@ -383,6 +310,44 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
383 return __alloc_bootmem_node(pgdat, size, align, goal); 310 return __alloc_bootmem_node(pgdat, size, align, goal);
384} 311}
385 312
313#ifdef CONFIG_SPARSEMEM
314/**
315 * alloc_bootmem_section - allocate boot memory from a specific section
316 * @size: size of the request in bytes
317 * @section_nr: sparse map section to allocate from
318 *
319 * Return NULL on failure.
320 */
321void * __init alloc_bootmem_section(unsigned long size,
322 unsigned long section_nr)
323{
324 unsigned long pfn, goal, limit;
325
326 pfn = section_nr_to_pfn(section_nr);
327 goal = pfn << PAGE_SHIFT;
328 limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
329
330 return __alloc_memory_core_early(early_pfn_to_nid(pfn), size,
331 SMP_CACHE_BYTES, goal, limit);
332}
333#endif
334
335void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
336 unsigned long align, unsigned long goal)
337{
338 void *ptr;
339
340 if (WARN_ON_ONCE(slab_is_available()))
341 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
342
343 ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
344 goal, -1ULL);
345 if (ptr)
346 return ptr;
347
348 return __alloc_bootmem_nopanic(size, align, goal);
349}
350
386#ifndef ARCH_LOW_ADDRESS_LIMIT 351#ifndef ARCH_LOW_ADDRESS_LIMIT
387#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL 352#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
388#endif 353#endif
@@ -424,9 +389,16 @@ void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
424void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, 389void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
425 unsigned long align, unsigned long goal) 390 unsigned long align, unsigned long goal)
426{ 391{
392 void *ptr;
393
427 if (WARN_ON_ONCE(slab_is_available())) 394 if (WARN_ON_ONCE(slab_is_available()))
428 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); 395 return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
429 396
430 return ___alloc_bootmem_node(pgdat, size, align, goal, 397 ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
431 ARCH_LOW_ADDRESS_LIMIT); 398 goal, ARCH_LOW_ADDRESS_LIMIT);
399 if (ptr)
400 return ptr;
401
402 return __alloc_memory_core_early(MAX_NUMNODES, size, align,
403 goal, ARCH_LOW_ADDRESS_LIMIT);
432} 404}