arch_efi_call_virt
arch_efi_call_virt_setup
arch_efi_call_virt_teardown
efi_create_mapping
efi_set_mapping_permissions
KEXEC_DESTINATION_MEMORY_LIMIT
ELF_EXEC_PAGESIZE
KEXEC_CONTROL_PAGE_SIZE
ARCH_SLAB_MINALIGN
ARCH_HAS_SETUP_ADDITIONAL_PAGES
arch_setup_additional_pages
vdso 相关
free_initmem
mem_init
copy_user_page
#define copy_user_page(vto, vfrom, vaddr, topg) memcpy((vto), (vfrom), PAGE_SIZE)
memmove
memset
memcpy
HPAGE_SHIFT
HPAGE_SIZE
HUGETLB_PAGE_ORDER
ARCH_PFN_OFFSET
__early_set_fixmap
__set_fixmap
fixed_addresses
FIXADDR_START
FIXADDR_TOP
NR_FIX_BTMAPS
VMALLOC_END
VMALLOC_START
FIX_BTMAP_BEGIN
FIX_BTMAPS_SLOTS
FIXMAP_PAGE_IO
FIX_EARLYCON_MEM_BASE
switch_mm
__swp_entry
__swp_entry_to_pte
__swp_offset
__swp_type
TASK_UNMAPPED_BASE
VM_DATA_DEFAULT_FLAGS
ZERO_PAGE
#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
__pa
#define __pa(x) __virt_to_phys((unsigned long)(x))
__va
#define __va(x) ((void *)__pa_to_va_nodebug((phys_addr_t)(x)))
page_to_phys
#define page_to_phys(page) (pfn_to_phys(page_to_pfn(page)))
__pa_symbol
#define __pa_symbol(x) __phys_addr_symbol(RELOC_HIDE((unsigned long)(x), 0))
virt_addr_valid
virt_to_pfn
#define virt_to_pfn(vaddr) (phys_to_pfn(__pa(vaddr)))
virt_to_page
#define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr)))
va <-> pa <-> pfn <-> page
| <---------->|
SECTION_SIZE_BITS
#define SECTION_SIZE_BITS 28
PAGE_KERNEL
PAGE_KERNEL_EXEC
PAGE_SHARED
PAGE_OFFSET
arm32 :#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)
arm64 :#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS))
rv64 :#define PAGE_OFFSET kernel_map.page_offset
PAGE_SHIFT
PAGE_SIZE
PAGE_MASK
PGDIR_MASK
PGDIR_SHIFT
PGDIR_SIZE
PMD_MASK
PMD_SHIFT
PMD_SIZE
---
PTRS_PER_PGD
PTRS_PER_PMD
PTRS_PER_PTE
__pgprot
pgprot_t
pgprot_val
pgtable_t
pgprot_t pgprot_val(type) __pgprot(uint)
页表项标志位 与 无符号 之间的转换
pte_t pte_val(type) __pte(uint)
页表项 与 无符号 之间的转换
对于一个五级页表寻址来说,VMA可以分解为如下
|PGDIR_SHIFT|P4D_SHIFT|PUD_SHIFT|PMD_SHIFT|PTE_SHIFT(PAGE_SHIFT)|OFFSET_IN_PAGE|
四级:
|PGDIR_SHIFT|PUD_SHIFT|PMD_SHIFT|PTE_SHIFT(PAGE_SHIFT)|OFFSET_IN_PAGE|
三级:
|PGDIR_SHIFT|PMD_SHIFT|PTE_SHIFT(PAGE_SHIFT)|OFFSET_IN_PAGE|
二级:
|PGDIR_SHIFT|PTE_SHIFT(PAGE_SHIFT)|OFFSET_IN_PAGE|
一级:
|PGDIR_SHIFT|OFFSET_IN_PAGE|
---
PAGE_SHIFT 一般为12 , 即 OFFSET_IN_PAGE 为 [11:0]
每一个 XXX_SHIFT 对应 一个 XXX_MASK XXX_SHIFT XXX_SIZE
5级页表寻址,对应 要存在 5种页表 和 一个物理页面,但是对应一个特定的虚拟地址,我们只关心 5个页表(每种一个) 和 一个物理页面
4级页表寻址,对应 要存在 4种页表 和 一个物理页面
...
1级页表寻址,1对应 要存在 1种页表 和 一个物理页面
每个页表都有一些要素
1. 名称(PGDT,P4DT,PUDT,PMDT,PT)
2. 基址
3. 有多少个表项
4. 一个表项(除了arm32-without-lpae为4字节,其他都是8字节)如何编码
究其根本来说,只存在两种事物(地址和值)
- 1 表示定义且为公共外部符号,2表示定义且不为公共外部符号
前后缀 | 前后缀字符串 | 类别 | pgd | p4d | pud | pmd | pte |
---|
suffix | _t | 变量 | 1 | 2 | 2 | 1 | 1 |
— | — | — | — | — | — | — | — |
suffix | _alloc | 增 | 2 | 2 | 2 | 2 | 2 |
— | — | — | — | — | — | — | — |
prefix | __xxx_free_tlb | 删 | | | 2 | 1 | 1 |
— | — | — | — | — | — | — | — |
prefix | set_ | 改1(初始化) | 2 | 1 | 1 | 2 | 2 |
suffix | _populate | 改1 | 2 | 1 | 1 | 1 | |
suffix | _populate_kernel | 改1 | | | | 1 | |
suffix | p_establish | 改1 | | | | 1 | |
suffix | _clear | 改2(清0) | 2 | 1 | 1 | 1 | 1 |
prefix | set_xxx_at | 改3(只初始pte) | | | 2 | 1 | 1 |
suffix | _mkclean | 改4(改属性) | | | 2 | 2 | 1 |
suffix | _mkdirty | 改4 | | | 2 | 2 | 1 |
suffix | _mkhuge | 改4 | | | 2 | 1 | 1 |
suffix | _mkinvalid | 改4 | | | | 1 | |
suffix | _mkold | 改4 | | | 2 | 2 | 1 |
suffix | _mkspecial | 改4 | | | 2 | | 1 |
suffix | _mkwrite | 改4 | | | 2 | 2 | 1 |
suffix | _mkyoung | 改4 | | | 2 | 2 | 1 |
— | — | — | — | — | — | — | — |
suffix | _val | 查1(查值) | 1 | 2 | 2 | 1 | 1 |
suffix | _none | 查2(查属性) | 2 | 1 | 1 | 1 | 1 |
suffix | _write | 查2 | | 2 | 2 | 1 | 1 |
suffix | _present | 查2 | 2 | 1 | 1 | 1 | 1 |
suffix | _bad | 查2 | 2 | 1 | 1 | 1 | |
suffix | _dirty | 查2 | | | 2 | 1 | 1 |
suffix | _leaf | 查2 | 2 | 2 | 2 | 1 | |
suffix | _modify | 查2 | | | | 2 | 1 |
suffix | _special | 查2 | | | | | 1 |
suffix | _trans_huge | 查2 | | | | 1 | |
suffix | _wrprotect | 查2 | | | 2 | 2 | 1 |
suffix | _young | 查2 | | | 2 | 1 | 1 |
prefix | __xxx_to_swp_entry | 查2 | | | | 2 | 1 |
| | | | | | | |
suffix | _page_vaddr | 查3 | | | | 1 | |
suffix | _pgtable | 查3 | | 2 | 1 | 2 | |
suffix | _page | 查3 | 2 | 1 | 1 | 1 | 1 |
suffix | _pfn | 查3 | 2 | 2 | 2 | 1 | 1 |
— | — | — | — | — | — | — | — |
prefix | mk_ | 组1 | | | | 1 | 1 |
prefix | __ | 组1 | 1 | 2 | 1 | 1 | 1 |
prefix | pfn_ | 组1 | 2 | 2 | 2 | 1 | 1 |
— | — | — | — | — | — | — | — |
suffix | _ERROR | show | 1 | 2 | 2 | 1 | 2 |
---查3
pgd_page(pgd_t) 获取pgd_t项关联的页描述符 ———— pud使用的页
pmd_page(pmd_t) 获取pmd_t项关联的页描述符 ———— pte使用的页
pte_pfn(pte_t) 获取pte_t项关联的页号,pmd、pud都有此函数
pgd_page_vaddr(pgd_t) 返回关联页的内核虚地址,pud、pmd都有此函数
pgd_pgtable 等同于 pgd_page_vaddr
---组1
__pte(uint) 将无符号值构造一个页表项
mk_pte(struct page*,pgprot_t) 将页描述符对应的页号和页表权限标志作为参数创建一个pte值
pfn_pte(phy, prot) 使用 prot ( _PAGE_RW 等) 页权限将 phy 构造为一个 pte 项。
p4d_bad
p4d_clear
p4d_none
p4d_page
p4d_pgtable
p4d_populate
p4d_present
set_p4d
mk_pmd
mk_pte
pfn_pmd
pfn_pte
__pgd
pgd_alloc
pgd_ERROR
pgd_t
pgd_val
__pmd
pmd_bad
pmd_clear
pmd_dirty
pmd_ERROR
__pmd_free_tlb
pmd_leaf
pmd_mkhuge
pmd_mkinvalid
pmd_none
pmd_page
pmd_page_vaddr
pmdp_establish
pmd_pfn
pmd_populate
pmd_populate_kernel
pmd_present
pmd_t
pmd_trans_huge
pmd_val
pmd_write
pmd_young
__pte
pte_clear
pte_dirty
__pte_free_tlb
pte_mkclean
pte_mkdirty
pte_mkhuge
pte_mkold
pte_mkspecial
pte_mkwrite
pte_mkyoung
pte_modify
pte_none
pte_page
pte_pfn
pte_present
pte_special
pte_t
__pte_to_swp_entry
pte_val
pte_write
pte_wrprotect
pte_young
pud_bad
pud_clear
pud_none
pud_page
pud_pgtable
pud_populate
pud_present
set_pmd_at
set_pte_at
set_pud
./${ARCH}/mm/pageattr.c
set_memory_nx
set_memory_ro
set_memory_rw
set_memory_x
mark_rodata_ro