walk up pagetables on ARM
Oscar Salvador
osalvador.vilardaga at gmail.com
Thu Oct 6 10:09:21 EDT 2016
Hi all,
for learning purposes, I wanted to emulate "lookup_address" function for
ARM platforms, but I'm having some troubles which I don't know how to get
over them.
I'll explain it:
I start by retrieving the value of swapper_pg_dir from TTBR1 register
(during head.S executions the physical address of swapper_pg_dir is being
saved in this register).
So far this works, I can compare it with gdb:
(gdb) p swapper_pg_dir
Cannot access memory at address 0xc0004000
(gdb) p init_mm.pgd
$5 = (pgd_t *) 0xc0004000
(gdb)
And from my code:
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 &= ~0x3fff;
pgd = phys_to_virt (ttb_reg);
return pgd;
}
and the output:
kernel: [18604.342604] mod: get_global_pgd: 0x0 - c0004000
So far, it's ok, but now the fun begins.
I'm walking the page table to get the PTE related to an X address:
static pte_t *lookup_address (unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pgd = get_global_pgd() + pgd_index (addr);
pud = pud_offset (pgd, addr);
pmd = pmd_offset (pud, addr);
if (pmd == NULL || pmd_none (*pmd)) {
pr_info ("%s: pmd == NULL\n", r2_devname);
return NULL;
}
return pte_offset_kernel (pmd, addr);
}
After that, I'd to check if the PTE has the PRESENT flag. Since ARM
processor doesn't provide those flags Linux had to workaround that by
adding
these flags: (f.i:
http://lxr.free-electrons.com/source/arch/arm/include/asm/pgtable-2level.h#L123
)
I'm checking the flags with
pte_present
or
pte_write
But I think I'm getting the wrong PTE's because I've tried with some
address from /proc/kallsyms, and it's saying that the page is not
present, and I'm getting diferent values for different pages
in the same range.
For instance:
for: 0xc0009244:
bananapi kernel: [18604.419142] mod: pte_present: 0
bananapi kernel: [18604.428025] mod: pte_write: 0
bananapi kernel: [18604.436592] mod: pte_young: 2
bananapi kernel: [18604.445318] mod: pte_dirty: 0
and for 0xc0012904:
bananapi kernel: [18883.095749] r2k: pte_present: 0
bananapi kernel: [18883.104607] r2k: pte_write: 1
bananapi kernel: [18883.113159] r2k: pte_young: 0
bananapi kernel: [18883.121670] r2k: pte_dirty: 0
It's saying that is not present, but I can read from those addresses with gdb:
(gdb) x/2x 0xc0009244
0xc0009244 <vfp_flush_hwstate>: 0xe92d4010 0xe1a04000
(gdb) x/2x 0xc0012904
0xc0012904 <__readwrite_bug>: 0xe1a01000 0xe30505ec
(gdb)
What am I doing wrong?
Thanks in advance
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20161006/a024c702/attachment.html
More information about the Kernelnewbies
mailing list