源码为 2.6.37内核,x86_64架构,内存模型为Sparse Memory
paging_init函数在setup_arch函数中被调用,用于初始化所有节点的pg_data_t结构,以及节点对应的管理区zone结构,和page结构。
调用的大致过程为:
start_kernel()
--> setup_arch()
--> paging_init()
--> free_area_init_nodes()
--> free_area_init_node()
--> free_area_init_core()
--> memmap_init()
具体如下:
paging_init()在setup_arch()中被调用,定义为:
-
void __init paging_init(void)
-
{
-
unsigned long max_zone_pfns[MAX_NR_ZONES];
-
-
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-
max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
-
max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
-
max_zone_pfns[ZONE_NORMAL] = max_pfn;
-
-
-
-
-
-
-
-
-
sparse_memory_present_with_active_regions(MAX_NUMNODES);
-
sparse_init();
-
-
-
-
-
-
-
-
node_clear_state(0, N_NORMAL_MEMORY);
-
-
-
free_area_init_nodes(max_zone_pfns);
-
}
paging_init()调用了free_area_init_nodes函数初始化所有结点的pg_data_t和zone、page的数据,并打印了管理区信息:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
void __init free_area_init_nodes(unsigned long *max_zone_pfn)
-
{
-
unsigned long nid;
-
int i;
-
-
-
sort_node_map();
-
-
-
-
-
-
-
-
-
memset(arch_zone_lowest_possible_pfn, 0,
-
sizeof(arch_zone_lowest_possible_pfn));
-
memset(arch_zone_highest_possible_pfn, 0,
-
sizeof(arch_zone_highest_possible_pfn));
-
-
arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
-
arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
-
for (i = 1; i < MAX_NR_ZONES; i++) {
-
if (i == ZONE_MOVABLE)
-
continue;
-
arch_zone_lowest_possible_pfn[i] =
-
arch_zone_highest_possible_pfn[i-1];
-
arch_zone_highest_possible_pfn[i] =
-
max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
-
}
-
arch_zone_lowest_possible_pfn[ZONE_MOVABLE] = 0;
-
arch_zone_highest_possible_pfn[ZONE_MOVABLE] = 0;
-
-
-
-
-
-
-
-
-
-
-
memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
-
find_zone_movable_pfns_for_nodes(zone_movable_pfn);
-
-
-
-
printk("Zone PFN ranges:\n");
-
for (i = 0; i < MAX_NR_ZONES; i++) {
-
if (i == ZONE_MOVABLE)
-
continue;
-
printk(" %-8s ", zone_names[i]);
-
if (arch_zone_lowest_possible_pfn[i] ==
-
arch_zone_highest_possible_pfn[i])
-
printk("empty\n");
-
else
-
printk("%0#10lx -> %0#10lx\n",
-
arch_zone_lowest_possible_pfn[i],
-
arch_zone_highest_possible_pfn[i]);
-
}
-
-
-
-
printk("Movable zone start PFN for each node\n");
-
for (i = 0; i < MAX_NUMNODES; i++) {
-
if (zone_movable_pfn[i])
-
printk(" Node %d: %lu\n", i, zone_movable_pfn[i]);
-
}
-
-
-
-
printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
-
for (i = 0; i < nr_nodemap_entries; i++)
-
printk(" %3d: %0#10lx -> %0#10lx\n", early_node_map[i].nid,
-
early_node_map[i].start_pfn,
-
early_node_map[i].end_pfn);
-
-
-
mminit_verify_pageflags_layout();
-
setup_nr_node_ids();
-
-
-
for_each_online_node(nid) {
-
pg_data_t *pgdat = NODE_DATA(nid);
-
-
-
free_area_init_node(nid, NULL,
-
find_min_pfn_for_node(nid), NULL);
-
-
-
-
if (pgdat->node_present_pages)
-
node_set_state(nid, N_HIGH_MEMORY);
-
check_for_regular_memory(pgdat);
-
}
-
}
而在free_area_init_nodes函数中通过循环遍历各个节点,循环中调用了free_area_init_node函数初始化该节点对应的pg_data_t和zone、page的数据 :
-
-
-
-
-
-
-
void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
-
unsigned long node_start_pfn, unsigned long *zholes_size)
-
{
-
pg_data_t *pgdat = NODE_DATA(nid);
-
-
pgdat->node_id = nid;
-
pgdat->node_start_pfn = node_start_pfn;
-
-
-
-
-
-
calculate_node_totalpages(pgdat, zones_size, zholes_size);
-
-
-
alloc_node_mem_map(pgdat);
-
#ifdef CONFIG_FLAT_NODE_MEM_MAP
-
printk(KERN_DEBUG "free_area_init_node: node %d, pgdat %08lx, node_mem_map %08lx\n",
-
nid, (unsigned long)pgdat,
-
(unsigned long)pgdat->node_mem_map);
-
#endif
-
-
-
free_area_init_core(pgdat, zones_size, zholes_size);
-
}
继续调用free_area_init_core函数,继续初始化该节点的pg_data_t结构,初始化zone以及page结构 ,
free_area_init_core函数是初始化zone的核心:
-
-
-
-
-
-
-
-
static void __paginginit free_area_init_core(struct pglist_data *pgdat,
-
unsigned long *zones_size, unsigned long *zholes_size)
-
{
-
enum zone_type j;
-
int nid = pgdat->node_id;
-
unsigned long zone_start_pfn = pgdat->node_start_pfn;
-
int ret;
-
-
pgdat_resize_init(pgdat);
-
pgdat->nr_zones = 0;
-
init_waitqueue_head(&pgdat->kswapd_wait);
-
pgdat->kswapd_max_order = 0;
-
pgdat_page_cgroup_init(pgdat);
-
-
-
for (j = 0; j < MAX_NR_ZONES; j++) {
-
struct zone *zone = pgdat->node_zones + j;
-
unsigned long size, realsize, memmap_pages;
-
enum lru_list l;
-
-
-
size = zone_spanned_pages_in_node(nid, j, zones_size);
-
-
realsize = size - zone_absent_pages_in_node(nid, j,
-
zholes_size);
-
-
-
-
-
-
-
-
memmap_pages =
-
PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
-
if (realsize >= memmap_pages) {
-
realsize -= memmap_pages;
-
if (memmap_pages)
-
printk(KERN_DEBUG
-
" %s zone: %lu pages used for memmap\n",
-
zone_names[j], memmap_pages);
-
} else
-
printk(KERN_WARNING
-
" %s zone: %lu pages exceeds realsize %lu\n",
-
zone_names[j], memmap_pages, realsize);
-
-
-
-
if (j == 0 && realsize > dma_reserve) {
-
realsize -= dma_reserve;
-
printk(KERN_DEBUG " %s zone: %lu pages reserved\n",
-
zone_names[0], dma_reserve);
-
}
-
-
if (!is_highmem_idx(j))
-
nr_kernel_pages += realsize;
-
nr_all_pages += realsize;
-
-
zone->spanned_pages = size;
-
zone->present_pages = realsize;
-
#ifdef CONFIG_NUMA
-
zone->node = nid;
-
-
zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
-
/ 100;
-
-
zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
-
#endif
-
zone->name = zone_names[j];
-
-
-
spin_lock_init(&zone->lock);
-
spin_lock_init(&zone->lru_lock);
-
zone_seqlock_init(zone);
-
zone->zone_pgdat = pgdat;
-
-
zone_pcp_init(zone);
-
-
-
for_each_lru(l) {
-
INIT_LIST_HEAD(&zone->lru[l].list);
-
zone->reclaim_stat.nr_saved_scan[l] = 0;
-
}
-
zone->reclaim_stat.recent_rotated[0] = 0;
-
zone->reclaim_stat.recent_rotated[1] = 0;
-
zone->reclaim_stat.recent_scanned[0] = 0;
-
zone->reclaim_stat.recent_scanned[1] = 0;
-
-
zap_zone_vm_stats(zone);
-
zone->flags = 0;
-
if (!size)
-
continue;
-
-
set_pageblock_order(pageblock_default_order());
-
setup_usemap(pgdat, zone, size);
-
-
-
-
-
-
ret = init_currently_empty_zone(zone, zone_start_pfn,
-
size, MEMMAP_EARLY);
-
BUG_ON(ret);
-
memmap_init(size, nid, j, zone_start_pfn);
-
zone_start_pfn += size;
-
}
-
}
free_area_init_core函数调用memmap_init函数来初始化page结构:
-
#define memmap_init(size, nid, zone, start_pfn) \
-
memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
-
-
-
-
-
-
-
void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
-
unsigned long start_pfn, enum memmap_context context)
-
{
-
struct page *page;
-
unsigned long end_pfn = start_pfn + size;
-
unsigned long pfn;
-
struct zone *z;
-
-
if (highest_memmap_pfn < end_pfn - 1)
-
highest_memmap_pfn = end_pfn - 1;
-
-
z = &NODE_DATA(nid)->node_zones[zone];
-
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
-
-
-
-
-
-
if (context == MEMMAP_EARLY) {
-
if (!early_pfn_valid(pfn))
-
continue;
-
if (!early_pfn_in_nid(pfn, nid))
-
continue;
-
}
-
page = pfn_to_page(pfn);
-
set_page_links(page, zone, nid, pfn);
-
-
mminit_verify_page_links(page, zone, nid, pfn);
-
init_page_count(page);
-
reset_page_mapcount(page);
-
SetPageReserved(page);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
if ((z->zone_start_pfn <= pfn)
-
&& (pfn < z->zone_start_pfn + z->spanned_pages)
-
&& !(pfn & (pageblock_nr_pages - 1)))
-
set_pageblock_migratetype(page, MIGRATE_MOVABLE);
-
-
INIT_LIST_HEAD(&page->lru);
-
#ifdef WANT_PAGE_VIRTUAL
-
-
if (!is_highmem_idx(zone))
-
-
set_page_address(page, __va(pfn << PAGE_SHIFT));
-
#endif
-
}
-
}
这样经过paging_init函数,pg_data_t、zone、page等结构完成了初始化。
阅读(1736) | 评论(0) | 转发(0) |