1. 程式人生 > 其它 >arm64記憶體-sparsemem-巨集定義和指標陣列空間分配

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 到 section idx 的mask 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,說明已經分配了,不再分配。