Currently I'm developing some research-related programs and I need to find the pte
of some specific addresses. My development environment is Juno r1 board (CPUs are A53 and A57 ) and it's running arm64 Linux kernel.
I use some typical page table walk codes like this:
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;
}
However, when the program checks the pte
for the address(0xffffffc0008b2000), it always returns an empty pmd
.
My guess is that I got the wrong pgd
in the first step. I saw Tims Notes said that using current->mm
only could get the pgd of TTBR0
(user space pgd
) while the address I checked is a kernel space address so I should try to get the pgd of TTBR1
.
So my question is: If I want to get the pte
of a kernel space address, can I use current->mm
to get the pgd
?
If I can't, is there anything else I could try instead?
Any suggestion is welcome! Thank you.
Simon
TTBCR
and returns eitherTTBR0
orTTBR1
based on the target address. This is better thancurrent->mm
, but you are dealing with physical ARM PTE values as opposed to the Linux variants. TTBR1 is used for kernel space (in newer Linux versions ~3.xx+) as it never changes on a user space context switch. Note: Linux armv8 uses EL0 for TTBR0 and EL1 for TTBR1. There is also the CP15 queryunsigned 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));
for physical addresses. – Audet