walk up pagetables on ARM
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#L... ) 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
participants (1)
-
Oscar Salvador