接着上节讲解页表项操作函数
- pgd_index,pud_index,pmd_index,pte_index用于从内存指针和页表项取得下一级页表的地址
- #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
- static inline unsigned long pud_index(unsigned long address)
- {
- return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
- }
- static inline unsigned long pmd_index(unsigned long address)
- {
- return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
- }
- static inline unsigned long pte_index(unsigned long address)
- {
- return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
- }
可以看到这几个函数的形式都是XXX_index(address) = (address >> XXX_SHIFT) & (PTRS_PER_XXX-1)
其中,XXX是pgd,pud,pmd,pte其中一项,XXX_SHIFT表示到XXX表项需要移动的位数,PTRS_PER_XXX表示XXX表项能够容纳的表项的多少。
例如pgd_index,PGDIR_SHIFT为15位,先将address右移15位,得到PGD和PUD的部分,然后和PTRS_PER_PMD-1想与,取得PUD的值,并返回,这个函数的作用是返回address对应的pmd。
2、pgd_present,pud_present,pmd_present,pte_present的作用是检查对应的_PRESENT位是否置位
- static inline int pgd_present(pgd_t pgd)
- {
- return pgd_flags(pgd) & _PAGE_PRESENT;
- }
- static inline int pud_present(pud_t pud)
- {
- return pud_flags(pud) & _PAGE_PRESENT;
- }
- static inline int pmd_present(pmd_t pmd)
- {
- return pmd_flags(pmd) & _PAGE_PRESENT;
- }
- static inline int pte_present(pte_t a)
- {
- return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
- }
这几个函数的实现基本都一致,都是先取得flags,然后和_PAGE_PRESENT相与。
下面是pte_flags的实现
- static inline pteval_t pte_flags(pte_t pte)
- {
- return native_pte_val(pte) & PTE_FLAGS_MASK;
- }
这里通过native_pte_val取得pte,然后用PTE_FLAGS_MASK取得flags
下面是native_pte_val的实现
- static inline pteval_t native_pte_val(pte_t pte)
- {
- return pte.pte;
- }
这里直接返回pte.pte,pte_t的定义如下:
- typedef union {
- pteval_t pte;
- pteval_t pte_low;
- } pte_t;
3、pgd_none,pud_none,pmd_none,pte_none,和上面的函数作用相反
4、pgd_clear,pud_clear,pmd_clear,pte_clear删除传递的页表项
- static inline void pgd_clear(pgd_t *pgdp)
- {
- set_pgd(pgdp, __pgd(0));
- }
这里调用set_pgd设置pgdp指向的pgd项为__pgd(0)
set_pgd的定义如下:
- static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
- {
- pgdval_t val = native_pgd_val(pgd);
- if (sizeof(pgdval_t) > sizeof(long))
- PVOP_VCALL3(pv_mmu_ops.set_pgd, pgdp,
- val, (u64)val >> 32);
- else
- PVOP_VCALL2(pv_mmu_ops.set_pgd, pgdp,
- val);
- }
这里又出现了那个神奇的调用,纠结~~
__pgd(val)的定义如下:
- static inline pgd_t __pgd(pgdval_t val)
- {
- pgdval_t ret;
- if (sizeof(pgdval_t) > sizeof(long))
- ret = PVOP_CALLEE2(pgdval_t, pv_mmu_ops.make_pgd,
- val, (u64)val >> 32);
- else
- ret = PVOP_CALLEE1(pgdval_t, pv_mmu_ops.make_pgd,
- val);
- return (pgd_t) { ret };
- }
5、pgd_bad,pud_bad,pmd_bad检查中间页表项、上层页表项、全局页表项是否无效
- static inline int pud_bad(pud_t pud)
- {
- return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0;
- }
6、pmd_page,pud_page,pte_page返回保存页数据的page结构活着中间页目录的项
- #define pmd_page(pmd) pfn_to_page((pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT)
- #define pud_page(pud) pfn_to_page(pud_val(pud) >> PAGE_SHIFT)
- #define pte_page(pte) pfn_to_page(pte_pfn(pte))
这里都调用了pfn_to_page函数
- #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))
阅读(3884) | 评论(0) | 转发(0) |