内核中一个内存页对应了几个基本概念:
这些数据的地址间,可以互相转化和访问。
Linear Mapping
整个Kernel的VA地址空间的总体划分 memory.h
,使用ptdump(address_markers)可以把这个layout dump出来。
PAGE_OFFSET
~ PAGE_END
这段VA区间,对全部物理内存做了完整的一一映射,这个映射叫做Linear Mapping。
Linear Mapping的VA与PA间,可以进行线性转换(计算时,只需要计算PA在物理内存的内部偏移址,在PAGE_OFFSET基础上做同样偏移,就得到了VA地址)
Linear Mapping,使用了一个pgd:pgd[0],在 paging_init
map_mem
过程中完成。
利用Linear Mapping这个映射,我们就可以在内核中,去操作物理内存,或是找到物理地址的句柄指针。
Page Table Entry
这里的转换,不包括页表Entry的访问,访问页表Entry,见 mm/pgtable
- /arch/arm64/include/asm/memory.h
- /arch/arm64/mm/mmu.c
- /include/asm-generic/memory_model.h
virt_to_phys
phys_to_virt
__virt_to_phys
__phys_to_virt
__va
__pa
__pa_symbol
虚拟地址与物理地址通过Linear Mapping转换。
这几个接口功能相同,支持的VA地址范围包括:
在开启CONFIG_DEBUG_VIRTUAL的情况下,传入Kernel Image符号VA会打印WARNING,所以不建议使用这些接口转化内核符号地址。
virt_addr_valid
__is_lm_address
要检查一个vaddr是否属于Linear Mapping的范围,可以使用这类接口。
__pa_symbol
用于kernel image符号转换为物理地址
__kimg_to_phys
__phys_to_kimg
__pa_symbol
Kernel镜像内符号的虚拟地址与物理地址转换(Buildtime VA <=> Runtime PA)
使用这个接口的原因,是Kernel镜像内的符号虚拟地址不在Linear Mapping的VA范围内。
内核符号建议使用这类接口转换。
virt_to_page
page_to_virt
虚拟地址与其所映射的物理页对应的page struct之间转换。
virt_to_pfn
虚拟地址与其所映射的物理页的PFN转换。
page_to_phys
phys_to_page
物理地址与其对应的物理页的page struct之间转换。
__phys_to_pfn
__pfn_to_phys
物理地址与其对应的物理页的PFN之间转换。
page_to_pfn
pfn_to_page
物理页对应的page struct与PFN转换。
页表的访问和修改,见 mm/pgtable
CONFIG_DEBUG_VIRTUAL
启用VA地址参数是否在Linear Mapping范围的监测,传入了不在范围内的addr会报oops warning。