Linux内存管理相关宏和变量

1. #define VA_BITS (CONFIG_ARM64_VA_BITS)
虚拟地址宽度,最大值为48,比如配置为39,用户地址0- 0x0000007f_ffffffffff
内核空间地址为0xffffff80_00000000-0xfffffffff_fffffffff,分别为256G

#define VA_START (UL(0xffffffffffffffff) << VA_BITS)
内核虚拟地址起始地址:0xffffff80_00000000
#define PAGE_OFFSET (UL(0xffffffffffffffff) << (VA_BITS - 1))

内核镜像的起始地址0xffffffc0_00000000

2.

#define MODULES_END (PAGE_OFFSET)
#define MODULES_VADDR (MODULES_END - SZ_64M)

模块虚拟地址

//struct page 数组的大小
#define VMEMMAP_SIZE ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)

vmalloc 分配的起始地址
#define VMALLOC_START (KASAN_SHADOW_END + SZ_64K)


vmalloc分配结束地址
#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)


struct page数起始地址
#define VMEMMAP_START (VMALLOC_END + SZ_64K)

3.
memstart_addr为DDR的起始物理地址(base),vmemmap为什么减去起始ddr的物理地址 ?
在计算一个page的pfn时,都是基于系统的物理0地址,所以预先减去base,在进行page和pfn转换时,就可以直接相加/相减
pfn_to_page(pfn)  vmemmap + pfn ;如果不预先减去base,那么应该是vmemmap +(pfn- pfn_base)
#define vmemmap ((struct page *)VMEMMAP_START - \

SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT))//__va

ARM64_HW_PGTABLE_LEVELS(va_bits):根据内核支持最大虚拟地址来确定页表级数

由于每级页表占用9bit,所以 (va_bits-PAGE_SHIFT)/(PAGE_SHIFT-3)

向上取整:((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3))

 最后简化:(((va_bits) - 4) / (PAGE_SHIFT - 3))

所以就有 #define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))

ARM64_HW_PGTABLE_LEVEL_SHIFT(n) : 根据页表级n,计算出第n级页表bit偏移

#define PMD_SHIFT        ARM64_HW_PGTABLE_LEVEL_SHIFT(2) : PMD页表的偏移bit =21

#define PMD_SIZE        (_AC(1, UL) << PMD_SHIFT):一个PMD表项能标识的内存size = 2M

PGDIR_SIZE //一个PGD能表示的内存大小

PUD_SHIFT/PGDIR_SHIFT 类似PMD的理解.

pgd_offset_k(addr):根据虚拟地址addr获取对应的pgd项.

pmd_offset(addr): 根据虚拟地址addr,从pud中获取对应的pmd项

pmd_index(addr):根据虚拟地址addr,计算pmd的index

//把pud的物理地址设置到pgd项中.

static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
{
    set_pgd(pgd, __pgd(__pa(pud) | PUD_TYPE_TABLE));
}

//把pte的物理地址设置到pmd项中.

pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)

从上面可以看出pgd,pmd,pte中保存的内容都是物理地址

PTRS_PER_PGD: PGD项个数

PTRS_PER_PTE: PTE项个数

PTRS_PER_PMD:PMD项个数,这是三个一般都是相等且为(1<<9)

如果level为3,则PUD=1

 4.内存相关的debug目录
/proc/meminfo
/proc/pagetypeinfo
/proc/buddyinfo
/proc/slabinfo
/proc/vmstat                                                     
/proc/zoneinfo

/sys/kernel/slab    
5.早起分配内存接口

early_alloc

6.sparse 内存模型

   #define SECTION_SIZE_BITS    30 //一个section的大小2的30次方=1G

  #define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT)//一个secion中的page数量

#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)//把pfn转换成section号

#define NR_MEM_SECTIONS        (1UL << SECTIONS_SHIFT)//计算系统中section数量

猜你喜欢

转载自blog.csdn.net/bin_linux96/article/details/79326073