diff options
Diffstat (limited to 'mm/bootmem.c')
-rw-r--r-- | mm/bootmem.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/mm/bootmem.c b/mm/bootmem.c index 555d5d2731c6..7d1486875e1c 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -143,6 +143,30 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages) | |||
143 | return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages); | 143 | return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages); |
144 | } | 144 | } |
145 | 145 | ||
146 | /* | ||
147 | * free_bootmem_late - free bootmem pages directly to page allocator | ||
148 | * @addr: starting address of the range | ||
149 | * @size: size of the range in bytes | ||
150 | * | ||
151 | * This is only useful when the bootmem allocator has already been torn | ||
152 | * down, but we are still initializing the system. Pages are given directly | ||
153 | * to the page allocator, no bootmem metadata is updated because it is gone. | ||
154 | */ | ||
155 | void __init free_bootmem_late(unsigned long addr, unsigned long size) | ||
156 | { | ||
157 | unsigned long cursor, end; | ||
158 | |||
159 | kmemleak_free_part(__va(addr), size); | ||
160 | |||
161 | cursor = PFN_UP(addr); | ||
162 | end = PFN_DOWN(addr + size); | ||
163 | |||
164 | for (; cursor < end; cursor++) { | ||
165 | __free_pages_bootmem(pfn_to_page(cursor), 0); | ||
166 | totalram_pages++; | ||
167 | } | ||
168 | } | ||
169 | |||
146 | static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | 170 | static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) |
147 | { | 171 | { |
148 | int aligned; | 172 | int aligned; |
@@ -408,8 +432,8 @@ int __init reserve_bootmem(unsigned long addr, unsigned long size, | |||
408 | return mark_bootmem(start, end, 1, flags); | 432 | return mark_bootmem(start, end, 1, flags); |
409 | } | 433 | } |
410 | 434 | ||
411 | static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | 435 | static unsigned long __init align_idx(struct bootmem_data *bdata, |
412 | unsigned long step) | 436 | unsigned long idx, unsigned long step) |
413 | { | 437 | { |
414 | unsigned long base = bdata->node_min_pfn; | 438 | unsigned long base = bdata->node_min_pfn; |
415 | 439 | ||
@@ -421,8 +445,8 @@ static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx, | |||
421 | return ALIGN(base + idx, step) - base; | 445 | return ALIGN(base + idx, step) - base; |
422 | } | 446 | } |
423 | 447 | ||
424 | static unsigned long align_off(struct bootmem_data *bdata, unsigned long off, | 448 | static unsigned long __init align_off(struct bootmem_data *bdata, |
425 | unsigned long align) | 449 | unsigned long off, unsigned long align) |
426 | { | 450 | { |
427 | unsigned long base = PFN_PHYS(bdata->node_min_pfn); | 451 | unsigned long base = PFN_PHYS(bdata->node_min_pfn); |
428 | 452 | ||