static phys_addr_t __init_memblock memblock_find_region(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align) { phys_addr_t base, res_base; long j; /* In case, huge size is requested */ if (end < size) return MEMBLOCK_ERROR; base = memblock_align_down((end - size), align); /* Prevent allocations returning 0 as it's also used to * indicate an allocation failure */ if (start == 0) start = PAGE_SIZE; while (start <= base) { j = memblock_overlaps_region(&memblock.reserved, base, size); if (j < 0) return base; res_base = memblock.reserved.regions[j].base; if (res_base < size) break; base = memblock_align_down(res_base - size, align); } return MEMBLOCK_ERROR; }
u64 __init __memblock_alloc_base(u64 size, u64 align, u64 max_addr) { long i, j; u64 base = 0; u64 res_base; BUG_ON(0 == size); size = memblock_align_up(size, align); /* On some platforms, make sure we allocate lowmem */ /* Note that MEMBLOCK_REAL_LIMIT may be MEMBLOCK_ALLOC_ANYWHERE */ if (max_addr == MEMBLOCK_ALLOC_ANYWHERE) max_addr = MEMBLOCK_REAL_LIMIT; for (i = memblock.memory.cnt - 1; i >= 0; i--) { u64 memblockbase = memblock.memory.region[i].base; u64 memblocksize = memblock.memory.region[i].size; if (memblocksize < size) continue; if (max_addr == MEMBLOCK_ALLOC_ANYWHERE) base = memblock_align_down(memblockbase + memblocksize - size, align); else if (memblockbase < max_addr) { base = min(memblockbase + memblocksize, max_addr); base = memblock_align_down(base - size, align); } else continue; while (base && memblockbase <= base) { j = memblock_overlaps_region(&memblock.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ if (memblock_add_region(&memblock.reserved, base, size) < 0) return 0; return base; } res_base = memblock.reserved.region[j].base; if (res_base < size) break; base = memblock_align_down(res_base - size, align); } } return 0; }
static u64 __init memblock_alloc_nid_unreserved(u64 start, u64 end, u64 size, u64 align) { u64 base, res_base; long j; base = memblock_align_down((end - size), align); while (start <= base) { j = memblock_overlaps_region(&memblock.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ if (memblock_add_region(&memblock.reserved, base, size) < 0) base = ~(u64)0; return base; } res_base = memblock.reserved.region[j].base; if (res_base < size) break; base = memblock_align_down(res_base - size, align); } return ~(u64)0; }