static phys_addr_t __init_memblock memblock_find_base(phys_addr_t size, phys_addr_t align, phys_addr_t start, phys_addr_t end) { long i; BUG_ON(0 == size); /* Pump up max_addr */ if (end == MEMBLOCK_ALLOC_ACCESSIBLE) end = memblock.current_limit; /* We do a top-down search, this tends to limit memory * fragmentation by keeping early boot allocs near the * top of memory */ for (i = memblock.memory.cnt - 1; i >= 0; i--) { phys_addr_t memblockbase = memblock.memory.regions[i].base; phys_addr_t memblocksize = memblock.memory.regions[i].size; phys_addr_t bottom, top, found; if (memblocksize < size) continue; if ((memblockbase + memblocksize) <= start) break; bottom = max(memblockbase, start); top = min(memblockbase + memblocksize, end); if (bottom >= top) continue; found = memblock_find_region(bottom, top, size, align); if (found != MEMBLOCK_ERROR) return found; } return MEMBLOCK_ERROR; }
static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp, phys_addr_t size, phys_addr_t align, int nid) { phys_addr_t start, end; start = mp->base; end = start + mp->size; start = memblock_align_up(start, align); while (start < end) { phys_addr_t this_end; int this_nid; this_end = memblock_nid_range(start, end, &this_nid); if (this_nid == nid) { phys_addr_t ret = memblock_find_region(start, this_end, size, align); if (ret != MEMBLOCK_ERROR && !memblock_add_region(&memblock.reserved, ret, size)) return ret; } start = this_end; } return MEMBLOCK_ERROR; }
phys_addr_t __init memblock_find_in_range_node(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align, int nid) { struct memblock_type *mem = &memblock.memory; int i; BUG_ON(0 == size); /* Pump up max_addr */ if (end == MEMBLOCK_ALLOC_ACCESSIBLE) end = memblock.current_limit; for (i = mem->cnt - 1; i >= 0; i--) { struct memblock_region *r = &mem->regions[i]; phys_addr_t base = max(start, r->base); phys_addr_t top = min(end, r->base + r->size); while (base < top) { phys_addr_t tbase, ret; int tnid; tbase = memblock_nid_range_rev(base, top, &tnid); if (nid == MAX_NUMNODES || tnid == nid) { ret = memblock_find_region(tbase, top, size, align); if (ret) return ret; } top = tbase; } } return 0; }