arm64内存-build_all_zonelists
上一篇: zone sizes init - free area init
https://www.cnblogs.com/zhangzhiwei122/p/16098846.html
start_kernel -> build_all_zonelist(NULL)
848asmlinkage __visible void __init __no_sanitize_address start_kernel(void) 849{ 850 char *command_line; 851 char *after_dashes; 878 build_all_zonelists(NULL); 879 page_alloc_init();
build_all_zonelist
pglist_data 结构体里面有 node_zonelists 数组,数组中的每个 zoneref 对象 ,指向一个 zone 对象。
build all zonelist 就是初始化 各个 pglist_data 对象(在UMA 下,也就只有 1 个 pglist_data 对象)里面的 node_zonelists 数组。
mm/page_alloc.c
5987void __ref build_all_zonelists(pg_data_t *pgdat) 5988{ 5989 unsigned long vm_total_pages; 5990 5991 if (system_state == SYSTEM_BOOTING) { 5992 build_all_zonelists_init(); 5993 } else { 5994 __build_all_zonelists(pgdat); 5995 /* cpuset refresh routine should be here */ 5996 } 5997 /* Get the number of free pages beyond high watermark in all zones. */ 5998 vm_total_pages = nr_free_zone_pages(gfp_zone(GFP_HIGHUSER_MOVABLE)); 6006 if (vm_total_pages < (pageblock_nr_pages * MIGRATE_TYPES)) 6007 page_group_by_mobility_disabled = 1; 6008 else 6009 page_group_by_mobility_disabled = 0; 6010 6018}
5992 - 在 SYSTEM_BOOTING 阶段,调用 build_all_zonelists_init
5998 ~ 6009 如果 free pages 不够多,就把 page group by mobility 功能给关闭。
build_all_zonelists_init
mm/page_alloc.c
5954static noinline void __init 5955build_all_zonelists_init(void) 5956{ 5959 __build_all_zonelists(NULL); 5974 for_each_possible_cpu(cpu) 5975 setup_pageset(&per_cpu(boot_pageset, cpu), 0); 5977 mminit_verify_zonelist(); 5978 cpuset_init_current_mems_allowed(); 5979}
5959 - 调用 __build_all_zonelists - 传入参数为 NULL,表示对所有 online 的 node 的 pglist_data 对象的 node_zonelists 进行初始化。(下面分析)
5974 ~ 5975 对每个 cpu 的 boot_pageset 对象进行初始化,并将他设置到 。 per_cpu_pageset 结构体在 include/linux/mmzone.h (下面分析)
5977 mminit_verify_zonelis 对 初始化后的 zonelists 进行验证,出错打印log 信息。 略
5978 cpuset_init_current_mems_allowed , 将 current->mems_allowed 这个 nodemask 都置位 。 略
__build_all_zonelists
5911static void __build_all_zonelists(void *data)
5912{
5915 pg_data_t *self = data;
5928 if (self && !node_online(self->node_id)) {
5929 build_zonelists(self);
5930 } else {
5931 for_each_online_node(nid) {
5932 pg_data_t *pgdat = NODE_DATA(nid);
5934 build_zonelists(pgdat);
5935 }
5936
5952}
传入的 data 为NULL, 则对所有 online 的node 都调用 build_zonelists( pgdat );
build_zonelists 在 UMA 和 NUMA 下面有不同实现,只分析 UMA 下的实现。
5853static void build_zonelists(pg_data_t *pgdat) 5854{ 5855 int node, local_node; 5856 struct zoneref *zonerefs; 5857 int nr_zones; 5858 5859 local_node = pgdat->node_id; 5861 zonerefs = pgdat->node_zonelists[ZONELIST_FALLBACK]._zonerefs; 5862 nr_zones = build_zonerefs_node(pgdat, zonerefs); 5863 zonerefs += nr_zones; 5873 for (node = local_node + 1; node < MAX_NUMNODES; node++) { 5874 if (!node_online(node)) 5875 continue; 5876 nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs); 5877 zonerefs += nr_zones; 5878 } 5879 for (node = 0; node < local_node; node++) { 5880 if (!node_online(node)) 5881 continue; 5882 nr_zones = build_zonerefs_node(NODE_DATA(node), zonerefs); 5883 zonerefs += nr_zones; 5884 } 5885 5886 zonerefs->zone = NULL; 5887 zonerefs->zone_idx = 0; 5888}
5861 行取得 pgdat 的node_zonelist[ 0 ] 这个对象的 _zonerefs 成员,这个成员是 一个 数组。 所以用指针 struct zoneref * 指针 zonerefs 表示它。
5862 将 pgdat 里面的 zone (地址,idx ) 都 set 到 zonerefs 数组里面。返回 nr_zones 表示 pgdat 里面具有的 zone 个数。
5863 zonerefs 向后跳过 nr_zones 个。
5873 ~ 5884 对其他的 node 的 pgdat 里面的 zone ( 地址 和 idx )也 set 到 zonerefs 数组里面。
5886 ~ 5887 zonerefs 最后一个 元素 设置为 空。
boot_cpuset 初始化
319struct per_cpu_pages { 320 int count; /* number of pages in the list */ 321 int high; /* high watermark, emptying needed */ 322 int batch; /* chunk size for buddy add/remove */ 323 324 /* Lists of pages, one per migrate type stored on the pcp-lists */ 325 struct list_head lists[MIGRATE_PCPTYPES]; 326}; 328struct per_cpu_pageset { 329 struct per_cpu_pages pcp; 335 s8 stat_threshold; 336 s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; 338};
boot_pageset 对象在 mm/page_alloc.c
5908static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset); 5909static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);
setup_pageset - 根据 batch 初始化 给定的 per_cpu_pageset 对象。 batch 给定为0 , 则 pcp 对象的 batch 为 1, high 为 0 ;
6302static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) 6303{ 6304 pageset_init(p); 6305 pageset_set_batch(p, batch); 6306}