|
@@ -33,41 +33,6 @@ unsigned long min_low_pfn;
|
|
|
unsigned long max_pfn;
|
|
|
unsigned long long max_possible_pfn;
|
|
|
|
|
|
-static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
|
|
|
- u64 goal, u64 limit)
|
|
|
-{
|
|
|
- void *ptr;
|
|
|
- u64 addr;
|
|
|
- enum memblock_flags flags = choose_memblock_flags();
|
|
|
-
|
|
|
- if (limit > memblock.current_limit)
|
|
|
- limit = memblock.current_limit;
|
|
|
-
|
|
|
-again:
|
|
|
- addr = memblock_find_in_range_node(size, align, goal, limit, nid,
|
|
|
- flags);
|
|
|
- if (!addr && (flags & MEMBLOCK_MIRROR)) {
|
|
|
- flags &= ~MEMBLOCK_MIRROR;
|
|
|
- pr_warn("Could not allocate %pap bytes of mirrored memory\n",
|
|
|
- &size);
|
|
|
- goto again;
|
|
|
- }
|
|
|
- if (!addr)
|
|
|
- return NULL;
|
|
|
-
|
|
|
- if (memblock_reserve(addr, size))
|
|
|
- return NULL;
|
|
|
-
|
|
|
- ptr = phys_to_virt(addr);
|
|
|
- memset(ptr, 0, size);
|
|
|
- /*
|
|
|
- * The min_count is set to 0 so that bootmem allocated blocks
|
|
|
- * are never reported as leaks.
|
|
|
- */
|
|
|
- kmemleak_alloc(ptr, size, 0, 0);
|
|
|
- return ptr;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* free_bootmem_late - free bootmem pages directly to page allocator
|
|
|
* @addr: starting address of the range
|
|
@@ -215,192 +180,3 @@ void __init free_bootmem(unsigned long addr, unsigned long size)
|
|
|
{
|
|
|
memblock_free(addr, size);
|
|
|
}
|
|
|
-
|
|
|
-static void * __init ___alloc_bootmem_nopanic(unsigned long size,
|
|
|
- unsigned long align,
|
|
|
- unsigned long goal,
|
|
|
- unsigned long limit)
|
|
|
-{
|
|
|
- void *ptr;
|
|
|
-
|
|
|
- if (WARN_ON_ONCE(slab_is_available()))
|
|
|
- return kzalloc(size, GFP_NOWAIT);
|
|
|
-
|
|
|
-restart:
|
|
|
-
|
|
|
- ptr = __alloc_memory_core_early(NUMA_NO_NODE, size, align, goal, limit);
|
|
|
-
|
|
|
- if (ptr)
|
|
|
- return ptr;
|
|
|
-
|
|
|
- if (goal != 0) {
|
|
|
- goal = 0;
|
|
|
- goto restart;
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * __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.
|
|
|
- *
|
|
|
- * Return: address of the allocated region or %NULL on failure.
|
|
|
- */
|
|
|
-void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
|
|
|
- unsigned long goal)
|
|
|
-{
|
|
|
- unsigned long limit = -1UL;
|
|
|
-
|
|
|
- return ___alloc_bootmem_nopanic(size, align, goal, limit);
|
|
|
-}
|
|
|
-
|
|
|
-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.
|
|
|
- */
|
|
|
- pr_alert("bootmem alloc of %lu bytes failed!\n", size);
|
|
|
- panic("Out of memory");
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * __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.
|
|
|
- *
|
|
|
- * Return: address of the allocated region.
|
|
|
- */
|
|
|
-void * __init __alloc_bootmem(unsigned long size, unsigned long align,
|
|
|
- unsigned long goal)
|
|
|
-{
|
|
|
- unsigned long limit = -1UL;
|
|
|
-
|
|
|
- return ___alloc_bootmem(size, align, goal, limit);
|
|
|
-}
|
|
|
-
|
|
|
-void * __init ___alloc_bootmem_node_nopanic(pg_data_t *pgdat,
|
|
|
- unsigned long size,
|
|
|
- unsigned long align,
|
|
|
- unsigned long goal,
|
|
|
- unsigned long limit)
|
|
|
-{
|
|
|
- void *ptr;
|
|
|
-
|
|
|
-again:
|
|
|
- ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
|
|
|
- goal, limit);
|
|
|
- if (ptr)
|
|
|
- return ptr;
|
|
|
-
|
|
|
- ptr = __alloc_memory_core_early(NUMA_NO_NODE, size, align,
|
|
|
- goal, limit);
|
|
|
- if (ptr)
|
|
|
- return ptr;
|
|
|
-
|
|
|
- if (goal) {
|
|
|
- goal = 0;
|
|
|
- goto again;
|
|
|
- }
|
|
|
-
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
|
|
|
- unsigned long align, unsigned long goal)
|
|
|
-{
|
|
|
- if (WARN_ON_ONCE(slab_is_available()))
|
|
|
- return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
|
|
|
-
|
|
|
- return ___alloc_bootmem_node_nopanic(pgdat, size, align, goal, 0);
|
|
|
-}
|
|
|
-
|
|
|
-static void * __init ___alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
|
|
|
- unsigned long align, unsigned long goal,
|
|
|
- unsigned long limit)
|
|
|
-{
|
|
|
- void *ptr;
|
|
|
-
|
|
|
- ptr = ___alloc_bootmem_node_nopanic(pgdat, size, align, goal, limit);
|
|
|
- if (ptr)
|
|
|
- return ptr;
|
|
|
-
|
|
|
- pr_alert("bootmem alloc of %lu bytes failed!\n", size);
|
|
|
- panic("Out of memory");
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * __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.
|
|
|
- *
|
|
|
- * Return: address of the allocated region.
|
|
|
- */
|
|
|
-void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
|
|
|
- unsigned long align, unsigned long goal)
|
|
|
-{
|
|
|
- if (WARN_ON_ONCE(slab_is_available()))
|
|
|
- return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
|
|
|
-
|
|
|
- return ___alloc_bootmem_node(pgdat, size, align, goal, 0);
|
|
|
-}
|
|
|
-
|
|
|
-void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
|
|
|
- unsigned long align, unsigned long goal)
|
|
|
-{
|
|
|
- return __alloc_bootmem_node(pgdat, size, align, goal);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * __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.
|
|
|
- *
|
|
|
- * Return: address of the allocated region.
|
|
|
- */
|
|
|
-void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
|
|
|
- unsigned long goal)
|
|
|
-{
|
|
|
- return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
|
|
|
-}
|