walk up pagetables on ARM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux