我试图为arm平台(仅针对内核页表)模拟函数lookup_address(http://lxr.free-electrons.com/source/arch/x86/mm/pageattr.c#L373)。在ARM上跳转页表
重点是我从TTBR1获取swapper_pg_dir的地址,到目前为止这工作。 我用gdb检查了它:
(gdb) file vmlinux
Reading symbols from vmlinux...done.
(gdb) p init_mm.pgd
$1 = (pgd_t *) 0xc0004000
(gdb)
,并从我的模块代码:
static pgd_t *get_global_pgd (void)
{
pgd_t *pgd;
unsigned int ttb_reg;
asm volatile (
" mrc p15, 0, %0, c2, c0, 1"
: "=r" (ttb_reg));
ttb_reg &= TTBR_MASK;
pgd = __va (ttb_reg);
pr_info ("get_global_pgd: %p\n", pgd);
return pgd;
}
和输出:
bananapi kernel: [ 5665.358139] mod: get_global_pgd: c0004000
到目前为止,这是匹配。 现在我计算正确的PGD的地址,这样做的:
pgd = get_global_pgd() + pgd_index (addr);
而且,由于(地址>> 21)是0x600,我得到0xc0007000。 然后我继续:
pud = pud_offset (pgd, addr);
pr_info ("pud: 0x%0x - %p\n",pud_val (*pud), pud);
pmd = pmd_offset (pud, addr);
pr_info ("pmd: 0x%0x - %p\n", pmd_val (*pmd), pmd);
if (pmd == NULL || pmd_none (*pmd)) {
return NULL;
}
return pte_offset_kernel (pmd, addr);
输出:
bananapi kernel: [ 5665.390391] mod: pud: 0x4001140e - c0007000
bananapi kernel: [ 5665.401603] mod: pmd: 0x4001140e - c0007000
bananapi kernel: [ 5665.423838] mod: pte: 0xe59f119c - c0011020
的问题是,我得到的PTE似乎并没有被罚款,因为该PTE的属性不匹配。 让我们的地址从/ proc/kallsyms:
c0008054 t __create_page_tables
我可以使用gdb阅读:
(gdb) x/2x 0xc0008054
0xc0008054 <__create_page_tables>: 0xe2884901 0xe1a00004
(gdb)
但是我从这个地址获得PTE,不具有本旗:
我与检查它(PTE是一个我从我的lookup_address了):
ret = pte_present (*pte);
pr_info ("pte_present: %d\n", ret);
pte_present是0(它检查L_PTE_PRESENT标志定义的include/asm/pgtable-2level.h),但只要我可以在GDB中读取它就不应该为0。
我已经与其他一些测试的地址,例如:0xc0035618:
c0035618 T __put_task_struct
而对于这一个L_PTE_PRESENT大设置。
我很确定我错过了什么,或者我错了。
提前致谢!
'L_ *'属性是Linux特有的,不一定是硬件。这里已经有很多关于ARM Linux [为这些维护第二组影子页表的问题]的问题(http://lxr.free-electrons.com/source/arch/arm/include/asm/pgtable-2level)。 H)。 – Notlikethat
是的,我知道。实际上我认为ARM不提供这些位,所以linux必须通过添加这些位来解决它。但是,当页面错误被触发时,Linux正在检查这些位,所以我认为它们是正确的。谢谢 – leberus
[ARM表的内核中的[页表入口(PTE)描述符的可能的重复](http://stackoverflow.com/questions/16909101/page-table-entry-pte-descriptor-in-linux-kernel-for- arm) –