[Elinux-discuss] doubt regarding page tables layout on arm

Bird, Timothy Tim.Bird at am.sony.com
Tue Oct 11 18:05:12 UTC 2016


This is not really the list for a technical discussion like this.  The elinux-discuss list is
for discussion of issues affecting the elinux wiki.  I recommend you post your
issue on the Linux kernel ARM mailing list. 
 -- Tim


> -----Original Message-----
> From: Elinux-discuss [mailto:elinux-discuss-bounces at lists.elinux.org] On
> Behalf Of Oscar Salvador
> Sent: Tuesday, October 11, 2016 12:38 PM
> To: elinux-discuss at lists.elinux.org
> Subject: [Elinux-discuss] doubt regarding page tables layout on arm
> 
> Hi all,
> 
> 
> I'm writing here because after been reading a lot of papers regarding this
> topic, I still can't get the point with it.
> 
> Let me explain it:
> 
> 
> I'm writing a module, and within this module I'm trying to emulate the
> lookup_address from x86, but on arm.
> 
> 
> I'm getting the value of swapper_pg_dir through the TTBR1 (which is the
> same value I get if I try to print the memory address of swapper_pg_dir with
> GDB).
> 
> 
> Then, since I'm working on arm32 without LPAE, Linux is just using PMD (pgd
> and pud are gone).
> 
> 
> As it explains here: include/asm/pgtable-2level.h
> 
> The layout pte page tables looks like:
> 
> 
> - linux_pte_0
> 
> - linux_pte_1
> 
> - arm_pte_0
> 
> - arm_pte_1
> 
> 
> That's within a page.
> 
> 
> linux_pte_* are being used in order that linux can check for dirty/young bits
> since ARM does not provide such bits.
> 
> 
> When creating the mappings through __create_mapping function, we set up
> the page table permissions of arm page tables depending of the permissions
> this type of memory has (this flags are being set in static struct mem_type
> mem_types[]).
> 
> 
> For example:
> 
> 
> In function alloc_init_pte we call arm_pte_alloc in order:
> 
> 
> - Allocate PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE bytes (4096bytes)
> 
> - populate pmd with (function __pmd_populate):
> 
>        - physical memory of space allocated before + PTE_HWTABLE_OFF
> (2048bytes) | protecion_bits
> 
>         - this ends up with: pmdval of this pmd stores:
> physical_address_of_arm_pte|protection_bits
> 
> 
> code from __pmd_populate:
> 
>  pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;
>  pmdp[0] = __pmd(pmdval);
> 
> 
> Once this is done, arm_pte_alloc returns with pte_offset_kernel, which does
> this steps:
> 
> 
>  - ANDs the value of this pmd with PHYS_MASK && PAGE_MASK
> 
>  - return the virtual address of the value stored before (returns vaddrr of the
> top of page=
>  - adds virtual_address of this page + pte_index (addr)
> 
> 
> Once this is done, the arm page tables permissions are being set with:
> 
> set_pte_ext function, that in my case is going to call cpu_v7_set_pte_ext
> function from mm/proc-v7-2level.S.
> 
> There r3 is being set depending of L_PTE_* bits, and then r3 is being written
> in linux_pte + 2048 (whete it points the arm_pte).
> 
> 
> Given this explanation I'll what I'm doing:
> 
> 
> Let's say I want to get the pte of X (X is a linear address)
> 
> 
> pgd = get_global_pgd_from_ttbr1 (same value as swapper_pg_dir)
> 
> pgd += pgd_index (X)
> 
> pud = pud_offset (pgd, X)
> 
> pmd = pmd_offset (pud, X)
> 
> 
> At this point, pmd should contain: (pte + PTE_HWTABLE_OFF) | prot  (since it
> was populated with this value).
> 
> 
> Then:
> 
> 
> pte = pte_offset_kernel (pmd, X) (gets virtual address of pmd_val masked
> with PHYS_MASK && PAGE_MASK and adds it the pte_index (X))
> 
> 
> Here I should get a pointer of the pte related to X address, and since I points
> to the top (where Linux PTE are), I should be able to check L_PTE_ bits, but
> I'm afraid i'm getting weird values here.
> 
> 
> 
> I hope I could explain my question as clear as I wanted.
> 
> 
> Thank you very much
> 
> Oscar Salvador



More information about the Elinux-discuss mailing list