Linux/ARM 通过软件方法遍历页表

翻译地址、遍历页表本是硬件MMU所做的工作。如何用软件来模拟出来呢?之前曾经写过一个简单的伪码实现:

unsigned long va2pa(unsigned long address)
{
pgd_t * pgd;
pud_t * pud;
pmd_t * pmd;
pte_t * pte;

pgd=cpu_get_pgd();
pud=pud_offset(pgd,address);
pmd=pmd_offset(pud,address);
pte=pte_offset_map(pmd,address);
pa=(*pte->pte>>12)<<12;

return pa;
}

不曾想,Kernel内部已经有此实现了^_^.
arch/arm/mm/fault.c

 1 /*
 2  * This is useful to dump out the page tables associated with
 3  * 'addr' in mm 'mm'.
 4  */
 5 void show_pte(struct mm_struct *mm, unsigned long addr)
 6 {
 7         pgd_t *pgd;
 8 
 9         if (!mm)
10                 mm = &init_mm;
11 
12         printk(KERN_ALERT "pgd = %p\n", mm->pgd);
13         pgd = pgd_offset(mm, addr);
14         printk(KERN_ALERT "[%08lx] *pgd=%08llx",
15                         addr, (long long)pgd_val(*pgd));
16 
17         do {
18                 pud_t *pud;
19                 pmd_t *pmd;
20                 pte_t *pte;
21 
22                 if (pgd_none(*pgd))
23                         break;
24 
25                 if (pgd_bad(*pgd)) {
26                         printk("(bad)");
27                         break;
28                 }
29 
30                 pud = pud_offset(pgd, addr);
31                 if (PTRS_PER_PUD != 1)
32                         printk(", *pud=%08llx", (long long)pud_val(*pud));
33 
34                 if (pud_none(*pud))
35                         break;
36 
37                 if (pud_bad(*pud)) {
38                         printk("(bad)");
39                         break;
40                 }
41 
42                 pmd = pmd_offset(pud, addr);
43                 if (PTRS_PER_PMD != 1)
44                         printk(", *pmd=%08llx", (long long)pmd_val(*pmd));
45 
46                 if (pmd_none(*pmd))
47                         break;
48 
49                 if (pmd_bad(*pmd)) {
50                         printk("(bad)");
51                         break;
52                 }
53 
54                 /* We must not map this if we have highmem enabled */
55                 if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
56                         break;
57 
58                 pte = pte_offset_map(pmd, addr);
59                 printk(", *pte=%08llx", (long long)pte_val(*pte));
60 #ifndef CONFIG_ARM_LPAE
61                 printk(", *ppte=%08llx",
62                        (long long)pte_val(pte[PTE_HWTABLE_PTRS]));
63 #endif
64                 pte_unmap(pte);
65         } while(0);
66 
67         printk("\n");
68 }

评论

  1. 一些体系结构只有software table walk,如mips。一些两者都支持,如ia64。

    回复删除
    回复
    1. 啊,如此这般,系统运行的速度岂不像蜗牛一样^_^

      删除
    2. hardware table walk并不比software的快多少,因为做的事情差不多,都是把找到的memory中的页表写到TLB里面。

      删除
    3. 噢,我以为是translation walk呢。呵呵

      删除

发表评论

此博客中的热门博文

Linux/ARM Page Table Entry 属性设置分析

提交了30次才AC ---【附】POJ 2488解题报告

笔记