Blame view
mm/bootmem.c
24.4 KB
1da177e4c Linux-2.6.12-rc2 |
1 |
/* |
57cfc29ef bootmem: clean up... |
2 |
* bootmem - A boot-time physical memory allocator and configurator |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* * Copyright (C) 1999 Ingo Molnar |
57cfc29ef bootmem: clean up... |
5 6 |
* 1999 Kanoj Sarcar, SGI * 2008 Johannes Weiner |
1da177e4c Linux-2.6.12-rc2 |
7 |
* |
57cfc29ef bootmem: clean up... |
8 9 |
* Access to this subsystem has to be serialized externally (which is true * for the boot process anyway). |
1da177e4c Linux-2.6.12-rc2 |
10 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
11 |
#include <linux/init.h> |
bbc7b92e3 [PATCH] bootmem: ... |
12 |
#include <linux/pfn.h> |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/bootmem.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <linux/module.h> |
ec3a354bd kmemleak: Add cal... |
16 |
#include <linux/kmemleak.h> |
08677214e x86: Make 64 bit ... |
17 |
#include <linux/range.h> |
72d7c3b33 x86: Use memblock... |
18 |
#include <linux/memblock.h> |
e786e86a5 [PATCH] bootmem: ... |
19 20 |
#include <asm/bug.h> |
1da177e4c Linux-2.6.12-rc2 |
21 |
#include <asm/io.h> |
dfd54cbcc [PATCH] bootmem: ... |
22 |
#include <asm/processor.h> |
e786e86a5 [PATCH] bootmem: ... |
23 |
|
1da177e4c Linux-2.6.12-rc2 |
24 |
#include "internal.h" |
1da177e4c Linux-2.6.12-rc2 |
25 26 27 |
unsigned long max_low_pfn; unsigned long min_low_pfn; unsigned long max_pfn; |
92aa63a5a [PATCH] kdump: Re... |
28 29 30 31 32 33 34 |
#ifdef CONFIG_CRASH_DUMP /* * If we have booted due to a crash, max_pfn will be a very low value. We need * to know the amount of memory that the previous kernel used. */ unsigned long saved_max_pfn; #endif |
08677214e x86: Make 64 bit ... |
35 |
#ifndef CONFIG_NO_BOOTMEM |
b61bfa3c4 mm: move bootmem ... |
36 |
bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata; |
636cc40cb bootmem: revisit ... |
37 |
static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list); |
2e5237daf bootmem: add debu... |
38 39 40 41 42 43 44 45 46 47 48 49 50 |
static int bootmem_debug; static int __init bootmem_debug_setup(char *buf) { bootmem_debug = 1; return 0; } early_param("bootmem_debug", bootmem_debug_setup); #define bdebug(fmt, args...) ({ \ if (unlikely(bootmem_debug)) \ printk(KERN_INFO \ "bootmem::%s " fmt, \ |
80a914dc0 misc: replace __F... |
51 |
__func__, ## args); \ |
2e5237daf bootmem: add debu... |
52 |
}) |
df049a5f4 bootmem: revisit ... |
53 |
static unsigned long __init bootmap_bytes(unsigned long pages) |
223e8dc92 bootmem: reorder ... |
54 |
{ |
df049a5f4 bootmem: revisit ... |
55 |
unsigned long bytes = (pages + 7) / 8; |
223e8dc92 bootmem: reorder ... |
56 |
|
df049a5f4 bootmem: revisit ... |
57 |
return ALIGN(bytes, sizeof(long)); |
223e8dc92 bootmem: reorder ... |
58 |
} |
a66fd7dae bootmem: add docu... |
59 60 61 62 |
/** * bootmem_bootmap_pages - calculate bitmap size in pages * @pages: number of pages the bitmap has to represent */ |
f71bf0cac [PATCH] bootmem: ... |
63 |
unsigned long __init bootmem_bootmap_pages(unsigned long pages) |
1da177e4c Linux-2.6.12-rc2 |
64 |
{ |
df049a5f4 bootmem: revisit ... |
65 |
unsigned long bytes = bootmap_bytes(pages); |
1da177e4c Linux-2.6.12-rc2 |
66 |
|
df049a5f4 bootmem: revisit ... |
67 |
return PAGE_ALIGN(bytes) >> PAGE_SHIFT; |
1da177e4c Linux-2.6.12-rc2 |
68 |
} |
f71bf0cac [PATCH] bootmem: ... |
69 |
|
679bc9fbb [PATCH] for_each_... |
70 71 72 |
/* * link bdata in order */ |
69d49e681 [PATCH] bootmem: ... |
73 |
static void __init link_bootmem(bootmem_data_t *bdata) |
679bc9fbb [PATCH] for_each_... |
74 |
{ |
636cc40cb bootmem: revisit ... |
75 |
struct list_head *iter; |
f71bf0cac [PATCH] bootmem: ... |
76 |
|
636cc40cb bootmem: revisit ... |
77 78 79 80 |
list_for_each(iter, &bdata_list) { bootmem_data_t *ent; ent = list_entry(iter, bootmem_data_t, list); |
3560e249a bootmem: replace ... |
81 |
if (bdata->node_min_pfn < ent->node_min_pfn) |
636cc40cb bootmem: revisit ... |
82 |
break; |
679bc9fbb [PATCH] for_each_... |
83 |
} |
636cc40cb bootmem: revisit ... |
84 |
list_add_tail(&bdata->list, iter); |
679bc9fbb [PATCH] for_each_... |
85 |
} |
bbc7b92e3 [PATCH] bootmem: ... |
86 |
/* |
1da177e4c Linux-2.6.12-rc2 |
87 88 |
* Called once to set up the allocator itself. */ |
8ae044630 mm: normalize int... |
89 |
static unsigned long __init init_bootmem_core(bootmem_data_t *bdata, |
1da177e4c Linux-2.6.12-rc2 |
90 91 |
unsigned long mapstart, unsigned long start, unsigned long end) { |
bbc7b92e3 [PATCH] bootmem: ... |
92 |
unsigned long mapsize; |
1da177e4c Linux-2.6.12-rc2 |
93 |
|
2dbb51c49 mm: make defensiv... |
94 |
mminit_validate_memmodel_limits(&start, &end); |
bbc7b92e3 [PATCH] bootmem: ... |
95 |
bdata->node_bootmem_map = phys_to_virt(PFN_PHYS(mapstart)); |
3560e249a bootmem: replace ... |
96 |
bdata->node_min_pfn = start; |
1da177e4c Linux-2.6.12-rc2 |
97 |
bdata->node_low_pfn = end; |
679bc9fbb [PATCH] for_each_... |
98 |
link_bootmem(bdata); |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 102 103 |
/* * Initially all pages are reserved - setup_arch() has to * register free RAM areas explicitly. */ |
df049a5f4 bootmem: revisit ... |
104 |
mapsize = bootmap_bytes(end - start); |
1da177e4c Linux-2.6.12-rc2 |
105 |
memset(bdata->node_bootmem_map, 0xff, mapsize); |
2e5237daf bootmem: add debu... |
106 107 108 |
bdebug("nid=%td start=%lx map=%lx end=%lx mapsize=%lx ", bdata - bootmem_node_data, start, mapstart, end, mapsize); |
1da177e4c Linux-2.6.12-rc2 |
109 110 |
return mapsize; } |
a66fd7dae bootmem: add docu... |
111 112 113 114 115 116 117 118 119 |
/** * init_bootmem_node - register a node as boot memory * @pgdat: node to register * @freepfn: pfn where the bitmap for this node is to be placed * @startpfn: first pfn on the node * @endpfn: first pfn after the node * * Returns the number of bytes needed to hold the bitmap for this node. */ |
223e8dc92 bootmem: reorder ... |
120 121 122 123 124 |
unsigned long __init init_bootmem_node(pg_data_t *pgdat, unsigned long freepfn, unsigned long startpfn, unsigned long endpfn) { return init_bootmem_core(pgdat->bdata, freepfn, startpfn, endpfn); } |
a66fd7dae bootmem: add docu... |
125 126 127 128 129 130 131 |
/** * init_bootmem - register boot memory * @start: pfn where the bitmap is to be placed * @pages: number of available physical pages * * Returns the number of bytes needed to hold the bitmap. */ |
223e8dc92 bootmem: reorder ... |
132 133 134 135 136 137 |
unsigned long __init init_bootmem(unsigned long start, unsigned long pages) { max_low_pfn = pages; min_low_pfn = start; return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages); } |
08677214e x86: Make 64 bit ... |
138 |
#endif |
9f993ac3f bootmem: Add free... |
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
/* * free_bootmem_late - free bootmem pages directly to page allocator * @addr: starting address of the range * @size: size of the range in bytes * * This is only useful when the bootmem allocator has already been torn * down, but we are still initializing the system. Pages are given directly * to the page allocator, no bootmem metadata is updated because it is gone. */ void __init free_bootmem_late(unsigned long addr, unsigned long size) { unsigned long cursor, end; kmemleak_free_part(__va(addr), size); cursor = PFN_UP(addr); end = PFN_DOWN(addr + size); for (; cursor < end; cursor++) { __free_pages_bootmem(pfn_to_page(cursor), 0); totalram_pages++; } } |
08677214e x86: Make 64 bit ... |
162 163 164 165 166 167 168 169 170 171 172 |
#ifdef CONFIG_NO_BOOTMEM static void __init __free_pages_memory(unsigned long start, unsigned long end) { int i; unsigned long start_aligned, end_aligned; int order = ilog2(BITS_PER_LONG); start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); end_aligned = end & ~(BITS_PER_LONG - 1); if (end_aligned <= start_aligned) { |
08677214e x86: Make 64 bit ... |
173 174 175 176 177 |
for (i = start; i < end; i++) __free_pages_bootmem(pfn_to_page(i), 0); return; } |
08677214e x86: Make 64 bit ... |
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
for (i = start; i < start_aligned; i++) __free_pages_bootmem(pfn_to_page(i), 0); for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG) __free_pages_bootmem(pfn_to_page(i), order); for (i = end_aligned; i < end; i++) __free_pages_bootmem(pfn_to_page(i), 0); } unsigned long __init free_all_memory_core_early(int nodeid) { int i; u64 start, end; unsigned long count = 0; struct range *range = NULL; int nr_range; nr_range = get_free_all_memory_range(&range, nodeid); for (i = 0; i < nr_range; i++) { start = range[i].start; end = range[i].end; count += end - start; __free_pages_memory(start, end); } return count; } #else |
223e8dc92 bootmem: reorder ... |
208 209 |
static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) { |
41546c174 bootmem: clean up... |
210 |
int aligned; |
223e8dc92 bootmem: reorder ... |
211 |
struct page *page; |
41546c174 bootmem: clean up... |
212 213 214 215 |
unsigned long start, end, pages, count = 0; if (!bdata->node_bootmem_map) return 0; |
3560e249a bootmem: replace ... |
216 |
start = bdata->node_min_pfn; |
41546c174 bootmem: clean up... |
217 |
end = bdata->node_low_pfn; |
223e8dc92 bootmem: reorder ... |
218 |
/* |
41546c174 bootmem: clean up... |
219 220 |
* If the start is aligned to the machines wordsize, we might * be able to free pages in bulks of that order. |
223e8dc92 bootmem: reorder ... |
221 |
*/ |
41546c174 bootmem: clean up... |
222 |
aligned = !(start & (BITS_PER_LONG - 1)); |
223e8dc92 bootmem: reorder ... |
223 |
|
41546c174 bootmem: clean up... |
224 225 226 |
bdebug("nid=%td start=%lx end=%lx aligned=%d ", bdata - bootmem_node_data, start, end, aligned); |
223e8dc92 bootmem: reorder ... |
227 |
|
41546c174 bootmem: clean up... |
228 229 |
while (start < end) { unsigned long *map, idx, vec; |
223e8dc92 bootmem: reorder ... |
230 |
|
41546c174 bootmem: clean up... |
231 |
map = bdata->node_bootmem_map; |
3560e249a bootmem: replace ... |
232 |
idx = start - bdata->node_min_pfn; |
41546c174 bootmem: clean up... |
233 234 235 236 237 238 |
vec = ~map[idx / BITS_PER_LONG]; if (aligned && vec == ~0UL && start + BITS_PER_LONG < end) { int order = ilog2(BITS_PER_LONG); __free_pages_bootmem(pfn_to_page(start), order); |
223e8dc92 bootmem: reorder ... |
239 |
count += BITS_PER_LONG; |
41546c174 bootmem: clean up... |
240 241 242 243 244 245 |
} else { unsigned long off = 0; while (vec && off < BITS_PER_LONG) { if (vec & 1) { page = pfn_to_page(start + off); |
223e8dc92 bootmem: reorder ... |
246 |
__free_pages_bootmem(page, 0); |
41546c174 bootmem: clean up... |
247 |
count++; |
223e8dc92 bootmem: reorder ... |
248 |
} |
41546c174 bootmem: clean up... |
249 250 |
vec >>= 1; off++; |
223e8dc92 bootmem: reorder ... |
251 |
} |
223e8dc92 bootmem: reorder ... |
252 |
} |
41546c174 bootmem: clean up... |
253 |
start += BITS_PER_LONG; |
223e8dc92 bootmem: reorder ... |
254 |
} |
223e8dc92 bootmem: reorder ... |
255 |
page = virt_to_page(bdata->node_bootmem_map); |
3560e249a bootmem: replace ... |
256 |
pages = bdata->node_low_pfn - bdata->node_min_pfn; |
41546c174 bootmem: clean up... |
257 258 259 260 |
pages = bootmem_bootmap_pages(pages); count += pages; while (pages--) __free_pages_bootmem(page++, 0); |
223e8dc92 bootmem: reorder ... |
261 |
|
2e5237daf bootmem: add debu... |
262 263 |
bdebug("nid=%td released=%lx ", bdata - bootmem_node_data, count); |
223e8dc92 bootmem: reorder ... |
264 265 |
return count; } |
08677214e x86: Make 64 bit ... |
266 |
#endif |
223e8dc92 bootmem: reorder ... |
267 |
|
a66fd7dae bootmem: add docu... |
268 269 270 271 272 273 |
/** * free_all_bootmem_node - release a node's free pages to the buddy allocator * @pgdat: node to be released * * Returns the number of pages actually released. */ |
223e8dc92 bootmem: reorder ... |
274 275 276 |
unsigned long __init free_all_bootmem_node(pg_data_t *pgdat) { register_page_bootmem_info_node(pgdat); |
08677214e x86: Make 64 bit ... |
277 278 279 280 |
#ifdef CONFIG_NO_BOOTMEM /* free_all_memory_core_early(MAX_NUMNODES) will be called later */ return 0; #else |
223e8dc92 bootmem: reorder ... |
281 |
return free_all_bootmem_core(pgdat->bdata); |
08677214e x86: Make 64 bit ... |
282 |
#endif |
223e8dc92 bootmem: reorder ... |
283 |
} |
a66fd7dae bootmem: add docu... |
284 285 286 287 288 |
/** * free_all_bootmem - release free pages to the buddy allocator * * Returns the number of pages actually released. */ |
223e8dc92 bootmem: reorder ... |
289 290 |
unsigned long __init free_all_bootmem(void) { |
08677214e x86: Make 64 bit ... |
291 |
#ifdef CONFIG_NO_BOOTMEM |
337998587 nobootmem, x86: F... |
292 293 294 295 296 297 298 299 |
/* * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id * because in some case like Node0 doesnt have RAM installed * low ram will be on Node1 * Use MAX_NUMNODES will make sure all ranges in early_node_map[] * will be used instead of only Node0 related */ return free_all_memory_core_early(MAX_NUMNODES); |
08677214e x86: Make 64 bit ... |
300 |
#else |
aa235fc71 bootmem, x86: Fix... |
301 302 303 304 305 306 307 |
unsigned long total_pages = 0; bootmem_data_t *bdata; list_for_each_entry(bdata, &bdata_list, list) total_pages += free_all_bootmem_core(bdata); return total_pages; |
08677214e x86: Make 64 bit ... |
308 |
#endif |
223e8dc92 bootmem: reorder ... |
309 |
} |
08677214e x86: Make 64 bit ... |
310 |
#ifndef CONFIG_NO_BOOTMEM |
d747fa4bc bootmem: free/res... |
311 312 313 314 315 316 317 |
static void __init __free(bootmem_data_t *bdata, unsigned long sidx, unsigned long eidx) { unsigned long idx; bdebug("nid=%td start=%lx end=%lx ", bdata - bootmem_node_data, |
3560e249a bootmem: replace ... |
318 319 |
sidx + bdata->node_min_pfn, eidx + bdata->node_min_pfn); |
d747fa4bc bootmem: free/res... |
320 |
|
e2bf3cae5 bootmem: factor o... |
321 322 |
if (bdata->hint_idx > sidx) bdata->hint_idx = sidx; |
d747fa4bc bootmem: free/res... |
323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
for (idx = sidx; idx < eidx; idx++) if (!test_and_clear_bit(idx, bdata->node_bootmem_map)) BUG(); } static int __init __reserve(bootmem_data_t *bdata, unsigned long sidx, unsigned long eidx, int flags) { unsigned long idx; int exclusive = flags & BOOTMEM_EXCLUSIVE; bdebug("nid=%td start=%lx end=%lx flags=%x ", bdata - bootmem_node_data, |
3560e249a bootmem: replace ... |
337 338 |
sidx + bdata->node_min_pfn, eidx + bdata->node_min_pfn, |
d747fa4bc bootmem: free/res... |
339 340 341 342 343 344 345 346 347 348 |
flags); for (idx = sidx; idx < eidx; idx++) if (test_and_set_bit(idx, bdata->node_bootmem_map)) { if (exclusive) { __free(bdata, sidx, idx); return -EBUSY; } bdebug("silent double reserve of PFN %lx ", |
3560e249a bootmem: replace ... |
349 |
idx + bdata->node_min_pfn); |
d747fa4bc bootmem: free/res... |
350 351 352 |
} return 0; } |
e2bf3cae5 bootmem: factor o... |
353 354 355 |
static int __init mark_bootmem_node(bootmem_data_t *bdata, unsigned long start, unsigned long end, int reserve, int flags) |
223e8dc92 bootmem: reorder ... |
356 357 |
{ unsigned long sidx, eidx; |
223e8dc92 bootmem: reorder ... |
358 |
|
e2bf3cae5 bootmem: factor o... |
359 360 361 |
bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x ", bdata - bootmem_node_data, start, end, reserve, flags); |
223e8dc92 bootmem: reorder ... |
362 |
|
3560e249a bootmem: replace ... |
363 |
BUG_ON(start < bdata->node_min_pfn); |
e2bf3cae5 bootmem: factor o... |
364 |
BUG_ON(end > bdata->node_low_pfn); |
223e8dc92 bootmem: reorder ... |
365 |
|
3560e249a bootmem: replace ... |
366 367 |
sidx = start - bdata->node_min_pfn; eidx = end - bdata->node_min_pfn; |
223e8dc92 bootmem: reorder ... |
368 |
|
e2bf3cae5 bootmem: factor o... |
369 370 |
if (reserve) return __reserve(bdata, sidx, eidx, flags); |
223e8dc92 bootmem: reorder ... |
371 |
else |
e2bf3cae5 bootmem: factor o... |
372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
__free(bdata, sidx, eidx); return 0; } static int __init mark_bootmem(unsigned long start, unsigned long end, int reserve, int flags) { unsigned long pos; bootmem_data_t *bdata; pos = start; list_for_each_entry(bdata, &bdata_list, list) { int err; unsigned long max; |
3560e249a bootmem: replace ... |
386 387 |
if (pos < bdata->node_min_pfn || pos >= bdata->node_low_pfn) { |
e2bf3cae5 bootmem: factor o... |
388 389 390 391 392 |
BUG_ON(pos != start); continue; } max = min(bdata->node_low_pfn, end); |
223e8dc92 bootmem: reorder ... |
393 |
|
e2bf3cae5 bootmem: factor o... |
394 395 396 397 398 |
err = mark_bootmem_node(bdata, pos, max, reserve, flags); if (reserve && err) { mark_bootmem(start, pos, 0, 0); return err; } |
223e8dc92 bootmem: reorder ... |
399 |
|
e2bf3cae5 bootmem: factor o... |
400 401 402 403 404 |
if (max == end) return 0; pos = bdata->node_low_pfn; } BUG(); |
223e8dc92 bootmem: reorder ... |
405 |
} |
08677214e x86: Make 64 bit ... |
406 |
#endif |
223e8dc92 bootmem: reorder ... |
407 |
|
a66fd7dae bootmem: add docu... |
408 409 410 411 412 413 414 415 |
/** * free_bootmem_node - mark a page range as usable * @pgdat: node the range resides on * @physaddr: starting address of the range * @size: size of the range in bytes * * Partial pages will be considered reserved and left as they are. * |
e2bf3cae5 bootmem: factor o... |
416 |
* The range must reside completely on the specified node. |
a66fd7dae bootmem: add docu... |
417 |
*/ |
223e8dc92 bootmem: reorder ... |
418 419 420 |
void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, unsigned long size) { |
08677214e x86: Make 64 bit ... |
421 |
#ifdef CONFIG_NO_BOOTMEM |
72d7c3b33 x86: Use memblock... |
422 |
kmemleak_free_part(__va(physaddr), size); |
a9ce6bc15 x86, memblock: Re... |
423 |
memblock_x86_free_range(physaddr, physaddr + size); |
08677214e x86: Make 64 bit ... |
424 |
#else |
e2bf3cae5 bootmem: factor o... |
425 |
unsigned long start, end; |
ec3a354bd kmemleak: Add cal... |
426 |
kmemleak_free_part(__va(physaddr), size); |
e2bf3cae5 bootmem: factor o... |
427 428 429 430 |
start = PFN_UP(physaddr); end = PFN_DOWN(physaddr + size); mark_bootmem_node(pgdat->bdata, start, end, 0, 0); |
08677214e x86: Make 64 bit ... |
431 |
#endif |
223e8dc92 bootmem: reorder ... |
432 |
} |
a66fd7dae bootmem: add docu... |
433 434 435 436 437 438 439 |
/** * free_bootmem - mark a page range as usable * @addr: starting address of the range * @size: size of the range in bytes * * Partial pages will be considered reserved and left as they are. * |
e2bf3cae5 bootmem: factor o... |
440 |
* The range must be contiguous but may span node boundaries. |
a66fd7dae bootmem: add docu... |
441 |
*/ |
223e8dc92 bootmem: reorder ... |
442 443 |
void __init free_bootmem(unsigned long addr, unsigned long size) { |
08677214e x86: Make 64 bit ... |
444 |
#ifdef CONFIG_NO_BOOTMEM |
72d7c3b33 x86: Use memblock... |
445 |
kmemleak_free_part(__va(addr), size); |
a9ce6bc15 x86, memblock: Re... |
446 |
memblock_x86_free_range(addr, addr + size); |
08677214e x86: Make 64 bit ... |
447 |
#else |
e2bf3cae5 bootmem: factor o... |
448 |
unsigned long start, end; |
a5645a61b mm: allow reserve... |
449 |
|
ec3a354bd kmemleak: Add cal... |
450 |
kmemleak_free_part(__va(addr), size); |
e2bf3cae5 bootmem: factor o... |
451 452 |
start = PFN_UP(addr); end = PFN_DOWN(addr + size); |
1da177e4c Linux-2.6.12-rc2 |
453 |
|
e2bf3cae5 bootmem: factor o... |
454 |
mark_bootmem(start, end, 0, 0); |
08677214e x86: Make 64 bit ... |
455 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
456 |
} |
a66fd7dae bootmem: add docu... |
457 458 459 460 461 462 463 464 465 |
/** * reserve_bootmem_node - mark a page range as reserved * @pgdat: node the range resides on * @physaddr: starting address of the range * @size: size of the range in bytes * @flags: reservation flags (see linux/bootmem.h) * * Partial pages will be reserved. * |
e2bf3cae5 bootmem: factor o... |
466 |
* The range must reside completely on the specified node. |
a66fd7dae bootmem: add docu... |
467 |
*/ |
223e8dc92 bootmem: reorder ... |
468 469 |
int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, unsigned long size, int flags) |
1da177e4c Linux-2.6.12-rc2 |
470 |
{ |
08677214e x86: Make 64 bit ... |
471 472 473 474 |
#ifdef CONFIG_NO_BOOTMEM panic("no bootmem"); return 0; #else |
e2bf3cae5 bootmem: factor o... |
475 |
unsigned long start, end; |
1da177e4c Linux-2.6.12-rc2 |
476 |
|
e2bf3cae5 bootmem: factor o... |
477 478 479 480 |
start = PFN_DOWN(physaddr); end = PFN_UP(physaddr + size); return mark_bootmem_node(pgdat->bdata, start, end, 1, flags); |
08677214e x86: Make 64 bit ... |
481 |
#endif |
223e8dc92 bootmem: reorder ... |
482 |
} |
5a982cbc7 mm: fix boundary ... |
483 |
|
a66fd7dae bootmem: add docu... |
484 485 486 487 488 489 490 491 |
/** * reserve_bootmem - mark a page range as usable * @addr: starting address of the range * @size: size of the range in bytes * @flags: reservation flags (see linux/bootmem.h) * * Partial pages will be reserved. * |
e2bf3cae5 bootmem: factor o... |
492 |
* The range must be contiguous but may span node boundaries. |
a66fd7dae bootmem: add docu... |
493 |
*/ |
223e8dc92 bootmem: reorder ... |
494 495 496 |
int __init reserve_bootmem(unsigned long addr, unsigned long size, int flags) { |
08677214e x86: Make 64 bit ... |
497 498 499 500 |
#ifdef CONFIG_NO_BOOTMEM panic("no bootmem"); return 0; #else |
e2bf3cae5 bootmem: factor o... |
501 |
unsigned long start, end; |
1da177e4c Linux-2.6.12-rc2 |
502 |
|
e2bf3cae5 bootmem: factor o... |
503 504 |
start = PFN_DOWN(addr); end = PFN_UP(addr + size); |
223e8dc92 bootmem: reorder ... |
505 |
|
e2bf3cae5 bootmem: factor o... |
506 |
return mark_bootmem(start, end, 1, flags); |
08677214e x86: Make 64 bit ... |
507 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
508 |
} |
08677214e x86: Make 64 bit ... |
509 |
#ifndef CONFIG_NO_BOOTMEM |
f88eff74a bootmem, x86: Add... |
510 511 512 513 514 |
int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len, int flags) { return reserve_bootmem(phys, len, flags); } |
8aa043d74 mm/bootmem.c: pro... |
515 516 |
static unsigned long __init align_idx(struct bootmem_data *bdata, unsigned long idx, unsigned long step) |
481ebd0d7 bootmem: fix alig... |
517 518 519 520 521 522 523 524 525 526 |
{ unsigned long base = bdata->node_min_pfn; /* * Align the index with respect to the node start so that the * combination of both satisfies the requested alignment. */ return ALIGN(base + idx, step) - base; } |
8aa043d74 mm/bootmem.c: pro... |
527 528 |
static unsigned long __init align_off(struct bootmem_data *bdata, unsigned long off, unsigned long align) |
481ebd0d7 bootmem: fix alig... |
529 530 531 532 533 534 535 |
{ unsigned long base = PFN_PHYS(bdata->node_min_pfn); /* Same as align_idx for byte offsets */ return ALIGN(base + off, align) - base; } |
d0c4f5702 bootmem, x86: fur... |
536 537 538 |
static void * __init alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) |
1da177e4c Linux-2.6.12-rc2 |
539 |
{ |
0f3caba21 bootmem: respect ... |
540 |
unsigned long fallback = 0; |
5f2809e69 bootmem: clean up... |
541 |
unsigned long min, max, start, sidx, midx, step; |
594fe1a04 bootmem: print re... |
542 543 544 545 |
bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx ", bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT, align, goal, limit); |
5f2809e69 bootmem: clean up... |
546 547 548 |
BUG_ON(!size); BUG_ON(align & (align - 1)); BUG_ON(limit && goal + size > limit); |
1da177e4c Linux-2.6.12-rc2 |
549 |
|
7c309a64d [PATCH] enable bo... |
550 551 |
if (!bdata->node_bootmem_map) return NULL; |
3560e249a bootmem: replace ... |
552 |
min = bdata->node_min_pfn; |
5f2809e69 bootmem: clean up... |
553 |
max = bdata->node_low_pfn; |
9a2dc04cf mm: offset align ... |
554 |
|
5f2809e69 bootmem: clean up... |
555 556 557 558 559 560 |
goal >>= PAGE_SHIFT; limit >>= PAGE_SHIFT; if (limit && max > limit) max = limit; if (max <= min) |
9a2dc04cf mm: offset align ... |
561 |
return NULL; |
5f2809e69 bootmem: clean up... |
562 |
step = max(align >> PAGE_SHIFT, 1UL); |
281dd25cd [PATCH] swiotlb: ... |
563 |
|
5f2809e69 bootmem: clean up... |
564 565 566 567 |
if (goal && min < goal && goal < max) start = ALIGN(goal, step); else start = ALIGN(min, step); |
1da177e4c Linux-2.6.12-rc2 |
568 |
|
481ebd0d7 bootmem: fix alig... |
569 |
sidx = start - bdata->node_min_pfn; |
3560e249a bootmem: replace ... |
570 |
midx = max - bdata->node_min_pfn; |
1da177e4c Linux-2.6.12-rc2 |
571 |
|
5f2809e69 bootmem: clean up... |
572 |
if (bdata->hint_idx > sidx) { |
0f3caba21 bootmem: respect ... |
573 574 575 576 577 |
/* * Handle the valid case of sidx being zero and still * catch the fallback below. */ fallback = sidx + 1; |
481ebd0d7 bootmem: fix alig... |
578 |
sidx = align_idx(bdata, bdata->hint_idx, step); |
5f2809e69 bootmem: clean up... |
579 |
} |
1da177e4c Linux-2.6.12-rc2 |
580 |
|
5f2809e69 bootmem: clean up... |
581 582 583 584 585 586 |
while (1) { int merge; void *region; unsigned long eidx, i, start_off, end_off; find_block: sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx); |
481ebd0d7 bootmem: fix alig... |
587 |
sidx = align_idx(bdata, sidx, step); |
5f2809e69 bootmem: clean up... |
588 |
eidx = sidx + PFN_UP(size); |
ad09315ca mm: fix alloc_boo... |
589 |
|
5f2809e69 bootmem: clean up... |
590 |
if (sidx >= midx || eidx > midx) |
66d43e98e [PATCH] fix in __... |
591 |
break; |
1da177e4c Linux-2.6.12-rc2 |
592 |
|
5f2809e69 bootmem: clean up... |
593 594 |
for (i = sidx; i < eidx; i++) if (test_bit(i, bdata->node_bootmem_map)) { |
481ebd0d7 bootmem: fix alig... |
595 |
sidx = align_idx(bdata, i, step); |
5f2809e69 bootmem: clean up... |
596 597 598 599 |
if (sidx == i) sidx += step; goto find_block; } |
1da177e4c Linux-2.6.12-rc2 |
600 |
|
627240aaa bootmem allocator... |
601 |
if (bdata->last_end_off & (PAGE_SIZE - 1) && |
5f2809e69 bootmem: clean up... |
602 |
PFN_DOWN(bdata->last_end_off) + 1 == sidx) |
481ebd0d7 bootmem: fix alig... |
603 |
start_off = align_off(bdata, bdata->last_end_off, align); |
5f2809e69 bootmem: clean up... |
604 605 606 607 608 609 610 611 612 613 614 615 |
else start_off = PFN_PHYS(sidx); merge = PFN_DOWN(start_off) < sidx; end_off = start_off + size; bdata->last_end_off = end_off; bdata->hint_idx = PFN_UP(end_off); /* * Reserve the area now: */ |
d747fa4bc bootmem: free/res... |
616 617 618 |
if (__reserve(bdata, PFN_DOWN(start_off) + merge, PFN_UP(end_off), BOOTMEM_EXCLUSIVE)) BUG(); |
5f2809e69 bootmem: clean up... |
619 |
|
3560e249a bootmem: replace ... |
620 621 |
region = phys_to_virt(PFN_PHYS(bdata->node_min_pfn) + start_off); |
5f2809e69 bootmem: clean up... |
622 |
memset(region, 0, size); |
008139d91 kmemleak: Do not ... |
623 624 625 626 627 |
/* * The min_count is set to 0 so that bootmem allocated blocks * are never reported as leaks. */ kmemleak_alloc(region, size, 0, 0); |
5f2809e69 bootmem: clean up... |
628 |
return region; |
1da177e4c Linux-2.6.12-rc2 |
629 |
} |
0f3caba21 bootmem: respect ... |
630 |
if (fallback) { |
481ebd0d7 bootmem: fix alig... |
631 |
sidx = align_idx(bdata, fallback - 1, step); |
0f3caba21 bootmem: respect ... |
632 633 634 635 636 637 |
fallback = 0; goto find_block; } return NULL; } |
d0c4f5702 bootmem, x86: fur... |
638 639 640 641 |
static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) { |
441c7e0a2 bootmem: use slab... |
642 643 |
if (WARN_ON_ONCE(slab_is_available())) return kzalloc(size, GFP_NOWAIT); |
d0c4f5702 bootmem, x86: fur... |
644 |
#ifdef CONFIG_HAVE_ARCH_BOOTMEM |
433f13a72 bootmem.c: avoid ... |
645 646 647 648 649 650 651 652 653 |
{ bootmem_data_t *p_bdata; p_bdata = bootmem_arch_preferred_node(bdata, size, align, goal, limit); if (p_bdata) return alloc_bootmem_core(p_bdata, size, align, goal, limit); } |
d0c4f5702 bootmem, x86: fur... |
654 655 656 |
#endif return NULL; } |
08677214e x86: Make 64 bit ... |
657 |
#endif |
d0c4f5702 bootmem, x86: fur... |
658 |
|
0f3caba21 bootmem: respect ... |
659 660 661 662 663 |
static void * __init ___alloc_bootmem_nopanic(unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) { |
08677214e x86: Make 64 bit ... |
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
#ifdef CONFIG_NO_BOOTMEM void *ptr; if (WARN_ON_ONCE(slab_is_available())) return kzalloc(size, GFP_NOWAIT); restart: ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit); if (ptr) return ptr; if (goal != 0) { goal = 0; goto restart; } return NULL; #else |
0f3caba21 bootmem: respect ... |
684 |
bootmem_data_t *bdata; |
d0c4f5702 bootmem, x86: fur... |
685 |
void *region; |
0f3caba21 bootmem: respect ... |
686 687 |
restart: |
d0c4f5702 bootmem, x86: fur... |
688 689 690 |
region = alloc_arch_preferred_bootmem(NULL, size, align, goal, limit); if (region) return region; |
0f3caba21 bootmem: respect ... |
691 |
|
d0c4f5702 bootmem, x86: fur... |
692 |
list_for_each_entry(bdata, &bdata_list, list) { |
0f3caba21 bootmem: respect ... |
693 694 |
if (goal && bdata->node_low_pfn <= PFN_DOWN(goal)) continue; |
3560e249a bootmem: replace ... |
695 |
if (limit && bdata->node_min_pfn >= PFN_DOWN(limit)) |
0f3caba21 bootmem: respect ... |
696 697 698 699 700 701 |
break; region = alloc_bootmem_core(bdata, size, align, goal, limit); if (region) return region; } |
5f2809e69 bootmem: clean up... |
702 703 |
if (goal) { goal = 0; |
0f3caba21 bootmem: respect ... |
704 |
goto restart; |
5f2809e69 bootmem: clean up... |
705 |
} |
2e5237daf bootmem: add debu... |
706 |
|
5f2809e69 bootmem: clean up... |
707 |
return NULL; |
08677214e x86: Make 64 bit ... |
708 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
709 |
} |
a66fd7dae bootmem: add docu... |
710 711 712 713 714 715 716 717 718 719 720 721 722 |
/** * __alloc_bootmem_nopanic - allocate boot memory without panicking * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * Returns NULL on failure. */ |
bb0923a66 [PATCH] bootmem: ... |
723 |
void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align, |
0f3caba21 bootmem: respect ... |
724 |
unsigned long goal) |
1da177e4c Linux-2.6.12-rc2 |
725 |
{ |
08677214e x86: Make 64 bit ... |
726 727 728 729 730 731 732 |
unsigned long limit = 0; #ifdef CONFIG_NO_BOOTMEM limit = -1UL; #endif return ___alloc_bootmem_nopanic(size, align, goal, limit); |
0f3caba21 bootmem: respect ... |
733 |
} |
1da177e4c Linux-2.6.12-rc2 |
734 |
|
0f3caba21 bootmem: respect ... |
735 736 737 738 739 740 741 742 743 744 745 746 747 |
static void * __init ___alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) { void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit); if (mem) return mem; /* * Whoops, we cannot satisfy the allocation request. */ printk(KERN_ALERT "bootmem alloc of %lu bytes failed! ", size); panic("Out of memory"); |
a8062231d [PATCH] x86_64: H... |
748 749 |
return NULL; } |
1da177e4c Linux-2.6.12-rc2 |
750 |
|
a66fd7dae bootmem: add docu... |
751 752 753 754 755 756 757 758 759 760 761 762 763 |
/** * __alloc_bootmem - allocate boot memory * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * The function panics if the request can not be satisfied. */ |
bb0923a66 [PATCH] bootmem: ... |
764 765 |
void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) |
a8062231d [PATCH] x86_64: H... |
766 |
{ |
08677214e x86: Make 64 bit ... |
767 768 769 770 771 772 773 |
unsigned long limit = 0; #ifdef CONFIG_NO_BOOTMEM limit = -1UL; #endif return ___alloc_bootmem(size, align, goal, limit); |
1da177e4c Linux-2.6.12-rc2 |
774 |
} |
08677214e x86: Make 64 bit ... |
775 |
#ifndef CONFIG_NO_BOOTMEM |
4cc278b72 bootmem: Make __a... |
776 777 778 779 780 |
static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit) { void *ptr; |
d0c4f5702 bootmem, x86: fur... |
781 782 783 |
ptr = alloc_arch_preferred_bootmem(bdata, size, align, goal, limit); if (ptr) return ptr; |
4cc278b72 bootmem: Make __a... |
784 785 786 787 788 789 |
ptr = alloc_bootmem_core(bdata, size, align, goal, limit); if (ptr) return ptr; return ___alloc_bootmem(size, align, goal, limit); } |
08677214e x86: Make 64 bit ... |
790 |
#endif |
4cc278b72 bootmem: Make __a... |
791 |
|
a66fd7dae bootmem: add docu... |
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
/** * __alloc_bootmem_node - allocate boot memory from a specific node * @pgdat: node to allocate from * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may fall back to any node in the system if the specified node * can not hold the requested memory. * * The function panics if the request can not be satisfied. */ |
bb0923a66 [PATCH] bootmem: ... |
807 808 |
void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) |
1da177e4c Linux-2.6.12-rc2 |
809 |
{ |
b8ab9f820 x86,nobootmem: ma... |
810 |
void *ptr; |
c91c4773b bootmem: fix slab... |
811 812 |
if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); |
08677214e x86: Make 64 bit ... |
813 |
#ifdef CONFIG_NO_BOOTMEM |
b8ab9f820 x86,nobootmem: ma... |
814 815 816 817 818 819 |
ptr = __alloc_memory_core_early(pgdat->node_id, size, align, goal, -1ULL); if (ptr) return ptr; ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, |
08677214e x86: Make 64 bit ... |
820 821 |
goal, -1ULL); #else |
b8ab9f820 x86,nobootmem: ma... |
822 |
ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0); |
08677214e x86: Make 64 bit ... |
823 |
#endif |
b8ab9f820 x86,nobootmem: ma... |
824 825 |
return ptr; |
08677214e x86: Make 64 bit ... |
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 |
} void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) { #ifdef MAX_DMA32_PFN unsigned long end_pfn; if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); /* update goal according ...MAX_DMA32_PFN */ end_pfn = pgdat->node_start_pfn + pgdat->node_spanned_pages; if (end_pfn > MAX_DMA32_PFN + (128 >> (20 - PAGE_SHIFT)) && (goal >> PAGE_SHIFT) < MAX_DMA32_PFN) { void *ptr; unsigned long new_goal; new_goal = MAX_DMA32_PFN << PAGE_SHIFT; #ifdef CONFIG_NO_BOOTMEM ptr = __alloc_memory_core_early(pgdat->node_id, size, align, new_goal, -1ULL); #else ptr = alloc_bootmem_core(pgdat->bdata, size, align, new_goal, 0); #endif if (ptr) return ptr; } #endif return __alloc_bootmem_node(pgdat, size, align, goal); |
1da177e4c Linux-2.6.12-rc2 |
859 |
} |
e70260aab memory hotplug: m... |
860 |
#ifdef CONFIG_SPARSEMEM |
a66fd7dae bootmem: add docu... |
861 862 863 864 865 866 867 |
/** * alloc_bootmem_section - allocate boot memory from a specific section * @size: size of the request in bytes * @section_nr: sparse map section to allocate from * * Return NULL on failure. */ |
e70260aab memory hotplug: m... |
868 869 870 |
void * __init alloc_bootmem_section(unsigned long size, unsigned long section_nr) { |
08677214e x86: Make 64 bit ... |
871 872 873 874 875 876 877 878 879 880 |
#ifdef CONFIG_NO_BOOTMEM unsigned long pfn, goal, limit; pfn = section_nr_to_pfn(section_nr); goal = pfn << PAGE_SHIFT; limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; return __alloc_memory_core_early(early_pfn_to_nid(pfn), size, SMP_CACHE_BYTES, goal, limit); #else |
75a56cfe9 bootmem: revisit ... |
881 882 |
bootmem_data_t *bdata; unsigned long pfn, goal, limit; |
e70260aab memory hotplug: m... |
883 884 |
pfn = section_nr_to_pfn(section_nr); |
75a56cfe9 bootmem: revisit ... |
885 886 887 |
goal = pfn << PAGE_SHIFT; limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; |
e70260aab memory hotplug: m... |
888 |
|
75a56cfe9 bootmem: revisit ... |
889 |
return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); |
08677214e x86: Make 64 bit ... |
890 |
#endif |
e70260aab memory hotplug: m... |
891 892 |
} #endif |
b54bbf7b8 mm: introduce non... |
893 894 895 896 |
void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) { void *ptr; |
c91c4773b bootmem: fix slab... |
897 898 |
if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); |
08677214e x86: Make 64 bit ... |
899 900 901 902 |
#ifdef CONFIG_NO_BOOTMEM ptr = __alloc_memory_core_early(pgdat->node_id, size, align, goal, -1ULL); #else |
d0c4f5702 bootmem, x86: fur... |
903 904 905 |
ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0); if (ptr) return ptr; |
b54bbf7b8 mm: introduce non... |
906 |
ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0); |
08677214e x86: Make 64 bit ... |
907 |
#endif |
b54bbf7b8 mm: introduce non... |
908 909 910 911 912 |
if (ptr) return ptr; return __alloc_bootmem_nopanic(size, align, goal); } |
dfd54cbcc [PATCH] bootmem: ... |
913 914 915 |
#ifndef ARCH_LOW_ADDRESS_LIMIT #define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL #endif |
008857c1a [PATCH] Cleanup b... |
916 |
|
a66fd7dae bootmem: add docu... |
917 918 919 920 921 922 923 924 925 926 927 928 929 |
/** * __alloc_bootmem_low - allocate low boot memory * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * The function panics if the request can not be satisfied. */ |
bb0923a66 [PATCH] bootmem: ... |
930 931 |
void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal) |
008857c1a [PATCH] Cleanup b... |
932 |
{ |
0f3caba21 bootmem: respect ... |
933 |
return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT); |
008857c1a [PATCH] Cleanup b... |
934 |
} |
a66fd7dae bootmem: add docu... |
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 |
/** * __alloc_bootmem_low_node - allocate low boot memory from a specific node * @pgdat: node to allocate from * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may fall back to any node in the system if the specified node * can not hold the requested memory. * * The function panics if the request can not be satisfied. */ |
008857c1a [PATCH] Cleanup b... |
950 951 952 |
void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal) { |
b8ab9f820 x86,nobootmem: ma... |
953 |
void *ptr; |
c91c4773b bootmem: fix slab... |
954 955 |
if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); |
08677214e x86: Make 64 bit ... |
956 |
#ifdef CONFIG_NO_BOOTMEM |
b8ab9f820 x86,nobootmem: ma... |
957 958 959 960 961 |
ptr = __alloc_memory_core_early(pgdat->node_id, size, align, goal, ARCH_LOW_ADDRESS_LIMIT); if (ptr) return ptr; ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, |
08677214e x86: Make 64 bit ... |
962 963 |
goal, ARCH_LOW_ADDRESS_LIMIT); #else |
b8ab9f820 x86,nobootmem: ma... |
964 |
ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, |
4cc278b72 bootmem: Make __a... |
965 |
goal, ARCH_LOW_ADDRESS_LIMIT); |
08677214e x86: Make 64 bit ... |
966 |
#endif |
b8ab9f820 x86,nobootmem: ma... |
967 |
return ptr; |
008857c1a [PATCH] Cleanup b... |
968 |
} |