【发布时间】:2018-11-14 03:43:02
【问题描述】:
目前我正在开发一些与研究相关的程序,我需要找到一些特定地址的pte。我的开发环境是 Juno r1 板(CPU 是 A53 和 A57 ),它运行 arm64 Linux 内核。
我使用一些典型的页表遍历代码,如下所示:
int find_physical_pte(void *addr)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *ptep;
unsigned long long address;
address = (unsigned long long)addr;
pgd = pgd_offset(current->mm, address);
printk(KERN_INFO "\npgd is: %p\n", (void *)pgd);
printk(KERN_INFO "pgd value: %llx\n", *pgd);
if (pgd_none(*pgd) || pgd_bad(*pgd))
return -1;
pud = pud_offset(pgd, address);
printk(KERN_INFO "\npud is: %p\n", (void *)pud);
printk(KERN_INFO "pud value: %llx\n", (*pud).pgd);
if (pud_none(*pud) || pud_bad(*pud))
return -2;
pmd = pmd_offset(pud, address);
printk(KERN_INFO "\npmd is: %p\n", (void *)pmd);
printk(KERN_INFO "pmd value: %llx\n",*pmd);
if (pmd_none(*pmd) || pmd_bad(*pmd))
return -3;
ptep = pte_offset_kernel(pmd, address);
printk(KERN_INFO "\npte is: %p\n", (void *)ptep);
printk(KERN_INFO "pte value: %llx\n",*ptep);
if (!ptep)
return -4;
return 1;
}
但是,当程序检查pte 的地址(0xffffffc0008b2000)时,它总是返回一个空的pmd。
我的猜测是我在第一步中弄错了pgd。我看到Tims Notes 说使用current->mm 只能获取pgd of TTBR0(用户空间pgd),而我检查的地址是内核空间地址,所以我应该尝试获取pgd of TTBR1。
所以我的问题是:如果我想获取内核空间地址的pte,我可以使用current->mm 来获取pgd吗?
如果我做不到,还有什么我可以尝试的吗?
欢迎提出任何建议!谢谢。
西蒙
【问题讨论】:
-
编写一个使用
TTBCR并根据目标地址返回TTBR0或TTBR1的例程。这比current->mm好,但您处理的是物理 ARM PTE 值,而不是 Linux 变体。 TTBR1 用于内核空间(在较新的 Linux 版本 ~3.xx+ 中),因为它在用户空间上下文切换时永远不会改变。注意:Linux armv8 对 TTBR0 使用 EL0,对 TTBR1 使用 EL1。还有物理地址的CP15查询unsigned int pa; asm("\t mcr p15, 0, %0, c7, c8, 2\n" "\t isb\n" "\t mrc p15, 0, %0, c7, c4, 0\n" : "=r" (pa) : "0" (0xffff0000));。 -
如果地址在内核空间,可以使用pgd_offset_k(address)
标签: linux linux-kernel arm arm64 page-tables