keep the most arch/x86/kernel/e820.c, and later when finish_e820_parsing() is called,
fill lmb.memory according to e820 entries with E820_RAM type.
current x86:
a. setup e820 array.
b. early_parm mem= and memmap= related code will adjust the e820.
we don't need to call lmb_enforce_memory_limit().
early_res is not sorted and merged.
if range get merged, you can not use name with them.
at least later when some code free a wrong range, we can figure who cause the problem.
lmb.memory - lmb.reserved
or e820 E820_RAM entries - early_res
move some code from early_res to lmb.c?
to make x86 to use lmb, we need to extend lmb to have find_early_area.
static int __init find_overlapped_early(u64 start, u64 end)
{
int i;
struct lmb_properties *r;
for (i = 0; i < lmb.reserved_cnt && lmb.reserved.region[i].size; i++) {
r = &lmb.reserved.region[i];
if (end > r->base && start < (r->base + r->size))
break;
}
return i;
}
/* Check for already reserved areas */
static inline int __init bad_addr(u64 *addrp, u64 size, u64 align)
{
int i;
u64 addr = *addrp;
int changed = 0;
struct lmb_properties *r;
again:
i = find_overlapped_early(addr, addr + size);
r = &lmb.reserved.region[i];
if (i < lmb.reserved.cnt && r->size) {
*addrp = addr = round_up(r->base + r->size, align);
changed = 1;
goto again;
}
return changed;
}
u64 __init find_early_area(u64 ei_start, u64 ei_last, u64 start, u64 end,
u64 size, u64 align)
{
u64 addr, last;
addr = round_up(ei_start, align);
if (addr < start)
addr = round_up(start, align);
if (addr >= ei_last)
goto out;
while (bad_addr(&addr, size, align) && addr+size <= ei_last)
;
last = addr + size;
if (last > ei_last)
goto out;
if (last > end)
goto out;
return addr;
out:
return -1ULL;
}
find_early_area_size()...
and use them we can have find_lmb_free_area
/*
* Find a free area with specified alignment in a specific range.
*/
u64 __init find_lmb_area(u64 start, u64 end, u64 size, u64 align)
{
int i;
for (i = 0; i < lmb.memory.cnt; i++) {
u64 ei_start = lmb.memory.region[i].base;
u64 ei_end = ei_start + lmb.memory.region[i].size;
addr = find_early_area(ei_start, ei_last, start, end,
size, align);
if (addr != -1ULL)
return addr;
}
return -1ULL;
}
also later we can use with active_range for bootmem replacement.
u64 __init find_memory_core_early(int nid, u64 size, u64 align,
u64 goal, u64 limit)
{
int i;
/* need to go over early_node_map to find out good range for node */
for_each_active_range_index_in_nid(i, nid) {
u64 addr;
u64 ei_start, ei_last;
ei_last = early_node_map[i].end_pfn;
ei_last <<= PAGE_SHIFT;
ei_start = early_node_map[i].start_pfn;
ei_start <<= PAGE_SHIFT;
addr = find_early_area(ei_start, ei_last,
goal, limit, size, align);
if (addr == -1ULL)
continue;
return addr;
}
return -1ULL;
}
Yinghai
--