arm64記憶體-sparsemem-巨集定義和指標陣列空間分配
阿新 • • 發佈:2022-04-03
相關的巨集定義
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 11601161#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,說明已經分配了,不再分配。