arm64内存-zone_sizes_init
zone sizes init
各个zone 中 size 相关信息的初始化
setup_arch -> bootmem_init -> zone_sizes_init
arch/arm64/mm/init.c
188static void __init zone_sizes_init(unsigned long min, unsigned long max) 189{ 190 unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; 191 193 max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit); 198 max_zone_pfns[ZONE_NORMAL] = max; 199 200 free_area_init(max_zone_pfns); 201}
long 数组 max_zone_pfns 数组里面记录了 各个 zone 的 max pfn 。 丢给 free_area_init 函数
zone 相关结构体、宏、全局变量
MAX_NUMNODES - 最大 node idx
在 UMA 上面,为 1 ; 在NUMA 上面,由 menuconfig - CONFIG_NODES_SHIFT 决定, 1 , 2, 4, 8
include/linux/numa.h
6#ifdef CONFIG_NODES_SHIFT 7#define NODES_SHIFT CONFIG_NODES_SHIFT 8#else 9#define NODES_SHIFT 0 10#endif 11 12#define MAX_NUMNODES (1 << NODES_SHIFT) 13
NODE_DATA(nid) - 通过node idx 取得 node 的 pg_data_t (struct pglist_data)
在 UMA 上面
include/linux/mmzone.h
1001#define NODE_DATA(nid) (&contig_page_data)
contig_page_data 在 mm/memblock.c
95#ifndef CONFIG_NEED_MULTIPLE_NODES 96struct pglist_data __refdata contig_page_data; 97EXPORT_SYMBOL(contig_page_data); 98#endif
NUMA 上面在
arch/arm64/include/asm/mmzone.h
9extern struct pglist_data *node_data[]; 10#define NODE_DATA(nid) (node_data[(nid)])
arch/arm64/mm/numa.c
19struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; 20EXPORT_SYMBOL(node_data);
struct pglist_data - pg_data_t
include/linux/mmzone.h
726typedef struct pglist_data { 732 struct zone node_zones[MAX_NR_ZONES]; // 对应node 里面 的ZONE区域,比如ZONE_DMA,ZONE_NORMAL等 739 struct zonelist node_zonelists[MAX_ZONELISTS]; // UMA MAX zonelists 为1,只有1个 zonelist 对象。
// NUMA max_zonelists 为2,有两个zonelist对象,node_zonelists[0] fallback 使用,node_zonelist[1] __GFP_THISNODE 使用
741 int nr_zones; //number of populated zones in this node 763 unsigned long node_start_pfn; //节点的起始内存页面帧号 764 unsigned long node_present_pages; /* total number of physical pages */ 765 unsigned long node_spanned_pages; /* total size of physical page 766 range, including holes */ 767 int node_id; 768 wait_queue_head_t kswapd_wait; 769 wait_queue_head_t pfmemalloc_wait; 770 struct task_struct *kswapd; /* Protected by 771 mem_hotplug_begin/end() */ 772 int kswapd_order; 773 enum zone_type kswapd_highest_zoneidx; // kernel swapper daemon highest zone idx 774 775 int kswapd_failures; /* Number of 'reclaimed == 0' runs */ 776 783 /* 784 * This is a per-node reserve of pages that are not available 785 * to userspace allocations. 786 */ 787 unsigned long totalreserve_pages; 788 799 spinlock_t lru_lock; 808 815 /* 816 * NOTE: THIS IS UNUSED IF MEMCG IS ENABLED. 817 * 818 * Use mem_cgroup_lruvec() to look up lruvecs. 819 */ 820 struct lruvec __lruvec; 821 822 unsigned long flags; 825 826 /* Per-node vmstats */ 827 struct per_cpu_nodestat __percpu *per_cpu_nodestats; 828 atomic_long_t vm_stat[NR_VM_NODE_STAT_ITEMS]; 829} pg_data_t;
732 - 一个node 内的 各个zone 对象数组. node_zones
739 - 一个node 内的 zonelist 对象数组, node_zonelists
770 - node kernel swapper daemon task
struct zone - free_area
include/linux/mmzone.h
27#define MAX_ORDER 11
448struct zone { 452 unsigned long _watermark[NR_WMARK]; //这个 zone 的水位值-配置值,WMARK_MIN/WMARK_LOW/WMARK_HIGH ,页面分配器和kswapd页面回收中会用到 453 unsigned long watermark_boost; 455 unsigned long nr_reserved_highatomic; 466 long lowmem_reserve[MAX_NR_ZONES]; // zone dma/ zone normal 里面的 lowmem reserve 471 struct pglist_data *zone_pgdat; // 指向 zone 所属的 pglist_data 对象 472 struct per_cpu_pageset __percpu *pageset; // 指向per cpu 的 per_cpu_pageset 对象。为每个cpu 的page 483 unsigned long zone_start_pfn; /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ 520 atomic_long_t managed_pages; // managed_pages = present_pages - reserved_pages; 521 unsigned long spanned_pages; //spanned_pages = zone_end_pfn - zone_start_pfn; 522 unsigned long present_pages; // present_pages = spanned_pages - absent_pages(pages in holes); 524 const char *name; 540 int initialized; 546 struct free_area free_area[MAX_ORDER]; //free areas of different sizes 549 unsigned long flags; //zone flags, 590 bool contiguous; 593 /* Zone statistics */ 594 atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; 595 atomic_long_t vm_numa_stat[NR_VM_NUMA_STAT_ITEMS]; }
546 - MAX_ORDER 为 11。 free_area 对象数组。数组中每个对象 在 include/linux/mmzone.h 如下
96struct free_area { 97 struct list_head free_list[MIGRATE_TYPES]; 98 unsigned long nr_free; // 空闲的 页 数 99};
每个对象内由 nr_free 记录 这个area 内 空闲的 页 数
freelist 又是一个对象数组,数组个数为 MIGRATE_TYPES , 在 include/linux/mmzone.h ,如下
41enum migratetype { 42 MIGRATE_UNMOVABLE, 43 MIGRATE_MOVABLE, 44 MIGRATE_RECLAIMABLE, 45 MIGRATE_PCPTYPES, /* the number of types on the pcp lists */ 46 MIGRATE_HIGHATOMIC = MIGRATE_PCPTYPES, 61 MIGRATE_CMA, 64 MIGRATE_ISOLATE, /* can't allocate from here */ 66 MIGRATE_TYPES 67};
则 一个 free_area 对象里面有 : free_list[ MIGRATE_UNMOVABLE ] free_list[ MIGRATE_MOVABLE ] ...... free_list[ MIGRATE_ISOLATE ]
各种类型的 空闲 页块 按照类别 组成 list . list 中 每个页块 的大小 为 2^idx 个 页 。
举例:
free_area[ 0 ] 中,每个页块的大小为 2^0 = 1 , 即 1 个页,4K
free_area[ 10 ] 中,每个页块的大小为 2^10 = 1024 , 即 1024 个页,4M
struct zonelist - zoneref
682struct zoneref { 683 struct zone *zone; /* Pointer to actual zone */ 684 int zone_idx; /* zone_idx(zoneref->zone) */ 685}; 663/* Maximum number of zones on a zonelist */ 664#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES) // uma 上面,max_numnodes = 1,max zones per list = max nr zones 701struct zonelist { 702 struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1]; // 里面放一个 数组,确实是一个 list。 list 里面可以存放所有节点的 zone 的 zoneref 703};
参考: https://www.cnblogs.com/LoyenWang/p/11568481.html , 这儿有很好的图示。
下一篇:free area init 过程分析
https://www.cnblogs.com/zhangzhiwei122/p/16098846.html