arm64内存-sparsemem-宏定义和指针数组空间分配

相关的宏定义

arch/arm64/include/asm/sparsemem.h

   9#define MAX_PHYSMEM_BITS        CONFIG_ARM64_PA_BITS
  10#define SECTION_SIZE_BITS       30

MAX_PHYSMEM_BIT 最大物理内存地址bits - 通常 CONFIG_ARM64_PA_BITS 为 48

SECTION_SIZE_BITS  一个section 大小,1G

 

include/linux/page-flags-layout.h

  30/* SECTION_SHIFT        #bits space required to store a section # */
  31#define SECTIONS_SHIFT  (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)

48 - 30 = 18 ,物理地址的 30 ~ 47 bit 表示 section idx。 section idx 占用的 bits 数 。

 

include/linux/mmzone.h

1158#define PA_SECTION_SHIFT        (SECTION_SIZE_BITS) // 30
1159#define PFN_SECTION_SHIFT       (SECTION_SIZE_BITS - PAGE_SHIFT) // 30 - 12  = 18   bit 12 ~ 29 这 18 个bits 表示 pfn 的idx
1160
1161#define NR_MEM_SECTIONS         (1UL << SECTIONS_SHIFT) // 最大的 section idx 值
1162
1163#define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT) // 最大的 pfn 值
1164#define PAGE_SECTION_MASK       (~(PAGES_PER_SECTION-1))   // pfn idx round down 到 pfn 所在的 section 的第一个 pfn 使用的mask。
// pfn = pfn & PAGE_SECTION_MASK 即round down, 到 pfn 对应的 section 的 第 0 个 pfn 1165 1244#define SECTIONS_PER_ROOT (PAGE_SIZE / sizeof (struct mem_section)) // 一页 可以存放的 mem_section 对象个数 1249#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT) // mem_section idx 转 root idx 1250#define NR_SECTION_ROOTS DIV_ROUND_UP(NR_MEM_SECTIONS, SECTIONS_PER_ROOT) // root idx 最大值 1251#define SECTION_ROOT_MASK (SECTIONS_PER_ROOT - 1) // 取 root idx 使用的 mask 1254extern struct mem_section **mem_section; // mem_section 指向 指针数组 .

 

结构体定义

include/linux/mmzone.h

CONFIG_PAGE_EXTENSION 没有 设置的情况下

1213struct mem_section {
1226        unsigned long section_mem_map;   // 这个是一个 地址 + 额外信息。 地址 存在 高位,额外信息存低位。地址处放 struct page 对象数组,数组个数 PAGES_PER_SECTION
1228 struct mem_section_usage *usage; 1241};

对齐之后,arm64 上面占用 16 个字节的大小。

一页 4K ,可以存放 256 个 mem_section 对象。

 

mem_section 空间分配

sparse_init -> memblocks_present -> memory_present

 252static void __init memory_present(int nid, unsigned long start, unsigned long end)
 253{
 254        unsigned long pfn;
 255
 256#ifdef CONFIG_SPARSEMEM_EXTREME
 257        if (unlikely(!mem_section)) {
 258                unsigned long size, align;
 259
 260                size = sizeof(struct mem_section*) * NR_SECTION_ROOTS;
 261                align = 1 << (INTERNODE_CACHE_SHIFT);
 262                mem_section = memblock_alloc(size, align);
 263                if (!mem_section)
 264                        panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
 265                              __func__, size, align);
 266        }
 267#endif


 292static void __init memblocks_present(void)
 293{
 294        unsigned long start, end;
 295        int i, nid;
 296
 297        for_each_mem_pfn_range(i, MAX_NUMNODES, &start, &end, &nid)
 298                memory_present(nid, start, end);
 299}
 300


 575void __init sparse_init(void)
 576{
 577        unsigned long pnum_end, pnum_begin, map_count = 1;
 578        int nid_begin;
 579
 580        memblocks_present();

 

257  - mem_section 如果为 0 ,则使用 memblock 分配 空间,存放 指针数组,数组个数为  NR_SECTION_ROOTS

         如果 mem_section 非0,说明已经分配了,不再分配。

 

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