I early_calculate_totalpages
从early_node_map 来计算页面的总数
page = early_node_map[i].end_pfn - early_node_map[i].start_pfn;
totalpage += page;
将required_movablecore roundup为MAX_ORDER_NR_PAGES的整数倍,
corepages = 总页数 - required_movablecore
required_kernelcore =corepages if只定义了 required_movablecore
required_kernelcore = max(required_kernelcore, corepages) else
反应了优先保证内核空间的思想。
if (required_movablecore) {
unsigned long corepages;
/*
* Round-up so that ZONE_MOVABLE is at least as large as what
* was requested by the user
*/
required_movablecore =
roundup(required_movablecore, MAX_ORDER_NR_PAGES);
corepages = totalpages - required_movablecore;
required_kernelcore = max(required_kernelcore, corepages);
}
接下来是
find_usable_zone_for_movable();
usable_startpfn = arch_zone_lowest_possible_pfn[movable_zone];
find_usable_zone_for_movable这个函数就是寻找低于ZONE_MOVABLE的最高的内存域。
当然内存域的页数不能为0. usable_startpfn是这个最高内存域的起始页。
void __init find_usable_zone_for_movable(void)
{
int zone_index;
for (zone_index = MAX_NR_ZONES - 1; zone_index >= 0; zone_index--) {
if (zone_index == ZONE_MOVABLE)
continue;
if (arch_zone_highest_possible_pfn[zone_index] >
arch_zone_lowest_possible_pfn[zone_index])
break;
}
VM_BUG_ON(zone_index == -1);
movable_zone = zone_index;
}
然后是将kernelcore_node 尽量平均分配到各个节点 node,对于我们只有一个节点的,
就比较简单了。
kernelcore_node = required_kernelcore / usable_nodes;
for_each_node_state(nid, N_HIGH_MEMORY)
a 如果不是最高内存域(除ZONE_MOVABLE外
这该内存域全部归于kernel_pages,
计算内核还需要多少页面
kernelcore_remaining = kernelcore_remaining - kernel_pages;
required_kernelcore = required_kernelcore - kernel_pages;
required_kernelcore 是计算所有节点还需要多少kernel 页面,
kernelcore_remaining是计算 本节点还需要多少内存页,初始化的时候,
kernelcore_remaining = required_kernelcore / usable_nodes
当然如果这个非最高内存域,包含的页面已经能够满足kernel 的需要,即kernel_pages
要比kernelcore_remaining 大,那么 kernelcore_remaining 为0,即不再需要kernel page
同时记录 zone_movable_pfn[nid] = end_pfn = early_node_map[i].end_pfn.
b 如果是最高内存域
start_pfn = usable_startpfn
end_pfn = early_node_map[i].end_pfn;
size_pages = end_pfn - start_pfn;
如果最高内存域的页面总数大于kernelcore_remaining
size_pages = kernelcore_remaining;
zone_movable_pfn[nid] = start_pfn + size_pages;
如果低的内存域就大于kernelcore_remaining,那么,zone_movable_pfn[nid] = usable_startpfn,
换句话说,就是,整个最高内存域都是ZONE_MOVABLE。
如果低端内存域大小低于kernelcore_remaining,那么最高内存域一部分是kernel page,另一部分是
ZONE_MOVABLE。
zone_movable_pfn[nid]记录了ZONE_MOVABLE的起始页。
总结:概括的说如果节点的内存非常多,低端的内存域就足以满足kernel需要的page,那么
zone_movable_pfn[nid] = 最高内存域的起始页
否则,如果内存比较少, 加上最高内存域的所有页也不够用
zone_movable_pfn[nid] = 最高内存域的最后一页
如果最高内存域比较多,那么
zone_movable_pfn[nid] = 最高内存域中间的某一页。
如果总体需要的required_kernelcore 还需要kernel page,再次扫描剩下的节点。
最后将zone_movable_pfn[nid],可以roundup 到MAX_ORDER_NR_PAGES的整数倍。