arm64内存-zone_sizes_init-free_area_init

上一篇: https://www.cnblogs.com/zhangzhiwei122/p/16097591.html

 

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}

将各个zone的 max pfn 数组丢给 free_area_init 函数

 

free_area_init

mm/page_alloc.c

 

 369static unsigned long arch_zone_lowest_possible_pfn[MAX_NR_ZONES] __initdata;
 370static unsigned long arch_zone_highest_possible_pfn[MAX_NR_ZONES] __initdata;
 
 375static unsigned long zone_movable_pfn[MAX_NUMNODES] __initdata;

7427void __init free_area_init(unsigned long *max_zone_pfn)
7428{
7429        unsigned long start_pfn, end_pfn;
7430        int i, nid, zone;
7431        bool descending;
7432
7433        /* Record where the zone boundaries are */
7434        memset(arch_zone_lowest_possible_pfn, 0,
7435                                sizeof(arch_zone_lowest_possible_pfn));
7436        memset(arch_zone_highest_possible_pfn, 0,
7437                                sizeof(arch_zone_highest_possible_pfn));
7438
7439        start_pfn = find_min_pfn_with_active_regions();
7440        descending = arch_has_descending_max_zone_pfns();
7441
7442        for (i = 0; i < MAX_NR_ZONES; i++) {
7443                if (descending)
7444                        zone = MAX_NR_ZONES - i - 1;
7445                else
7446                        zone = i;
7447
7448                if (zone == ZONE_MOVABLE)
7449                        continue;
7450
7451                end_pfn = max(max_zone_pfn[zone], start_pfn);
7452                arch_zone_lowest_possible_pfn[zone] = start_pfn;
7453                arch_zone_highest_possible_pfn[zone] = end_pfn;
7454
7455                start_pfn = end_pfn;
7456        }
7457
7458        /* Find the PFNs that ZONE_MOVABLE begins at in each node */
7459        memset(zone_movable_pfn, 0, sizeof(zone_movable_pfn));
7460        find_zone_movable_pfns_for_nodes();

7500        /* Initialise every node */
7501        mminit_verify_pageflags_layout();
7502        setup_nr_node_ids();
7503        init_unavailable_mem();
7504        for_each_online_node(nid) {
7505                pg_data_t *pgdat = NODE_DATA(nid);
7506                free_area_init_node(nid);
7507
7508                /* Any memory on that node */
7509                if (pgdat->node_present_pages)
7510                        node_set_state(nid, N_MEMORY);
7511                check_for_memory(pgdat, nid);
7512        }
7513}

369 ~ 375 定义文件中使用的 全局变量 arch_zone_lowest_possible_pfn   arch_zone_highest_possible_pfn   zone_movable_pfn

             arch_zone_lowest_possible_pfn   arch_zone_highest_possible_pfn 分别记录 zone idx 对应的 lowest pfn 和 hignest pfn

             zone_movable_pfn 记录各个 node 中的 movable zone 的start pfn .

7434 ~ 7456 先将 arch_zone_lowest_possible_pfn   arch_zone_highest_possible_pfn 清零,然后 for 循环,填充里面的值。

        7439 - 从memblock 得到当前 node 的最小 pfn , 给 start_pfn 。

        for 循环中,默认 前一个 zone 的 end pfn 是下一个zone 的 start pfn .

 

7459 ~ 7460 ~ 先将 zone_movable_pfn 清零, 然后调用 find zone movable pfn for nodes ,给各个node的 zone_movable_pfn 进行赋值。即  zone_movable_pfn 被初始化了。

7501 verify flag

7502  setup_nr_node_ids  设置系统的  node 数目。 UMA 上面为空函数。

7503 init unavailable memory

7504 开始for 循环遍历 每一个 node , UMA 上面 就是 1 个 node 。 for 循环 1 次。

    7505 取得 node  的 pglist_data 指针, UMA 上面只有全局唯一的一个 palist_data 对象 ,见 上一篇: https://www.cnblogs.com/zhangzhiwei122/p/16097591.html

    7506 free_area_init_node (nid) 对指定的 node idx 作 free area 的初始化。

 

free_area_init_node

mm/page_alloc.c

6967static void __init free_area_init_node(int nid)
6968{
6969        pg_data_t *pgdat = NODE_DATA(nid);
6970        unsigned long start_pfn = 0;
6971        unsigned long end_pfn = 0;

6976        get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);

6978        pgdat->node_id = nid;
6979        pgdat->node_start_pfn = start_pfn;
6980        pgdat->per_cpu_nodestats = NULL;

6985        calculate_node_totalpages(pgdat, start_pfn, end_pfn);

6987        alloc_node_mem_map(pgdat);
6988        pgdat_set_deferred_range(pgdat);

6990        free_area_init_core(pgdat);
6991}

6976 - 遍历 memblock 中的 node idx 下面的 mem region 信息,得到 这个node 的start pfn 和 end pfn

6978 ~ 6980 - 赋值初始化 node 的 pg_data_t 对象 的 node_id  , start pfn, per_cpu_nodestats

 

6985 - 计算 node 上面的  node_spanned_pages   node_present_pages  ,

            计算 node 内各个 zone 的 start pfn ,  spanned pages ; present pages - 后面的 free area init core 里面会使用这儿设置的值。

             使用 arch_zone_lowest_possible_pfn   arch_zone_highest_possible_pfn   zone_movable_pfn 和 memblock 信息得到,然后给 pgdat 里面的成员 赋值 。

 

6987 alloc node mem map  - 在 FLAG 内存模型下面, 给 pgdat 的 node_mem_map 指针分配内存。在 sparse内存模型下面,为空。

6988 deferred range 不用关心。

6990 free area init core  - free area init 的核心代码

 

free_area_init_core

mm/page_alloc.c

6843static void __init free_area_init_core(struct pglist_data *pgdat)
6844{
6845        enum zone_type j;
6846        int nid = pgdat->node_id;
6847
6848        pgdat_init_internals(pgdat);
6849        pgdat->per_cpu_nodestats = &boot_nodestats;
6850
6851        for (j = 0; j < MAX_NR_ZONES; j++) {
6852                struct zone *zone = pgdat->node_zones + j;
6853                unsigned long size, freesize, memmap_pages;
6854                unsigned long zone_start_pfn = zone->zone_start_pfn;
6855
6856                size = zone->spanned_pages;
6857                freesize = zone->present_pages;
6858
6859                /*
6860                 * Adjust freesize so that it accounts for how much memory
6861                 * is used by this zone for memmap. This affects the watermark
6862                 * and per-cpu initialisations
6863                 */
6864                memmap_pages = calc_memmap_size(size, freesize);
6865                if (!is_highmem_idx(j)) {
6866                        if (freesize >= memmap_pages) {
6867                                freesize -= memmap_pages;
6868                                if (memmap_pages)
6869                                        printk(KERN_DEBUG
6870                                               "  %s zone: %lu pages used for memmap\n",
6871                                               zone_names[j], memmap_pages);
6872                        } else
6873                                pr_warn("  %s zone: %lu pages exceeds freesize %lu\n",
6874                                        zone_names[j], memmap_pages, freesize);
6875                }
6876
6877                /* Account for reserved pages */
6878                if (j == 0 && freesize > dma_reserve) {
6879                        freesize -= dma_reserve;
6880                        printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
6881                                        zone_names[0], dma_reserve);
6882                }
6883
6884                if (!is_highmem_idx(j))
6885                        nr_kernel_pages += freesize;
6886                /* Charge for highmem memmap if there are enough kernel pages */
6887                else if (nr_kernel_pages > memmap_pages * 2)
6888                        nr_kernel_pages -= memmap_pages;
6889                nr_all_pages += freesize;
6890
6891                /*
6892                 * Set an approximate value for lowmem here, it will be adjusted
6893                 * when the bootmem allocator frees pages into the buddy system.
6894                 * And all highmem pages will be managed by the buddy system.
6895                 */
6896                zone_init_internals(zone, j, nid, freesize);
6897
6898                if (!size)
6899                        continue;
6900
6901                set_pageblock_order();
6902                setup_usemap(pgdat, zone, zone_start_pfn, size);
6903                init_currently_empty_zone(zone, zone_start_pfn, size);
6904                memmap_init(size, nid, j, zone_start_pfn);
6905        }
6906}

 

请参考: https://www.cnblogs.com/LoyenWang/p/11568481.html  里面有示例图,便于理解。

 

6848 ~ 6849 设置 pgdat 里面的一些成员变量的初始值 。    per_cpu_nodestats 设置为 boot_nodestats 的地址。

 boot_nodestats 是一个 per cpu 对象,在 mm/page_alloc.c 中。

5908static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset);
5909static DEFINE_PER_CPU(struct per_cpu_nodestat, boot_nodestats);

 

6851 开始 for 循环 处理 每个  zone 

          6856 ~ 6889 通过zone 的 spanned pages 和 present pages 计算得到 freesize ,然后更新  全局变量 nr_all_pages   nr_kernel_pages

          6896 zone 对象内,各种成员的初始值设定。比如各种锁的初始值。

          6901 set pageblock order 设置 pageblock_order 这个变量,表示  页块 由 多少个 页 组成 (2 ^ order 为 页 数)。 ARM64 上面,这个函数为空, pageblock_order 为常量 -   PMD_SHIFT - PAGE_SHIFT  =  9

include/linux/pageblock-flags.h

  40/* Huge pages are a constant size */
  41#define pageblock_order         HUGETLB_PAGE_ORDER
  42

arch/arm64/include/asm/pgtable.h

 

 332#define HPAGE_SHIFT             PMD_SHIFT

 335#define HUGETLB_PAGE_ORDER      (HPAGE_SHIFT - PAGE_SHIFT)

            6902  在 FLAT 内存模型,给  zone->pageblock_flags 指针  分配内存。 在SPARSE 内存模型上面,为空函数。

 

            6903  init_currently_empty_zone 在,同文件中,设置zone 的 zone_start_pfn ; initialized ;   free_area[MAX_ORDER] ( free_list[xx] ) 。 nr_free 都设置的为 0 。

6396void __meminit init_currently_empty_zone(struct zone *zone,
6397                                        unsigned long zone_start_pfn,
6398                                        unsigned long size)
6399{
6400        struct pglist_data *pgdat = zone->zone_pgdat;
6401        int zone_idx = zone_idx(zone) + 1;

6403        if (zone_idx > pgdat->nr_zones)
6404                pgdat->nr_zones = zone_idx;
6405
6406        zone->zone_start_pfn = zone_start_pfn;

6414        zone_init_free_lists(zone);
6415        zone->initialized = 1;
6416}
6179static void __meminit zone_init_free_lists(struct zone *zone)
6180{
6181        unsigned int order, t;
6182        for_each_migratetype_order(order, t) {
6183                INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
6184                zone->free_area[order].nr_free = 0;
6185        }
6186}

           6904  memmap_init ,同文件中

                  根据PFN,通过pfn_to_page找到对应的struct page结构,并将该结构进行初始化处理,并设置MIGRATE_MOVABLE标志

6188void __meminit __weak memmap_init(unsigned long size, int nid,
6189                                  unsigned long zone,
6190                                  unsigned long range_start_pfn)
6191{
6192        unsigned long start_pfn, end_pfn;
6193        unsigned long range_end_pfn = range_start_pfn + size;
6194        int i;
6195
6196        for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
6197                start_pfn = clamp(start_pfn, range_start_pfn, range_end_pfn);
6198                end_pfn = clamp(end_pfn, range_start_pfn, range_end_pfn);
6199
6200                if (end_pfn > start_pfn) {
6201                        size = end_pfn - start_pfn;
6202                        memmap_init_zone(size, nid, zone, start_pfn,
6203                                         MEMINIT_EARLY, NULL, MIGRATE_MOVABLE);
6204                }
6205        }
6206}

            pfn_to_page  include/asm-generic/memory_model.h 中,各种 内存模型下面,有不同实现  。 下面是 sparse 的实现

    

  57#elif defined(CONFIG_SPARSEMEM)

  68#define __pfn_to_page(pfn)                              \
  69({      unsigned long __pfn = (pfn);                    \
  70        struct mem_section *__sec = __pfn_to_section(__pfn);    \
  71        __section_mem_map_addr(__sec) + __pfn;          \
  72})
  73#endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */

  81#define page_to_pfn __page_to_pfn
  82#define pfn_to_page __pfn_to_page

      __section_mem_map_addr()  在 include/linux/mmzone.h 中。mem_section 结构体中, section_mem_map 记录了struct  page 对象的地址。 sparse 相关信息,

见 1  https://www.cnblogs.com/zhangzhiwei122/p/16096272.html ; 2.   https://www.cnblogs.com/zhangzhiwei122/p/16096641.html

1298static inline struct page *__section_mem_map_addr(struct mem_section *section)
1299{
1300        unsigned long map = section->section_mem_map;
1301        map &= SECTION_MAP_MASK;
1302        return (struct page *)map;
1303}

 

下一篇: build all zonelists

https://www.cnblogs.com/zhangzhiwei122/p/16099490.html

 

posted @ 2022-04-04 12:31  张志伟122  阅读(238)  评论(0编辑  收藏  举报