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 }
一些体系结构只有software table walk,如mips。一些两者都支持,如ia64。
回复删除啊,如此这般,系统运行的速度岂不像蜗牛一样^_^
删除hardware table walk并不比software的快多少,因为做的事情差不多,都是把找到的memory中的页表写到TLB里面。
删除噢,我以为是translation walk呢。呵呵
删除