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

 

posted @ 2022-04-03 22:09  张志伟122  阅读(164)  评论(0编辑  收藏  举报