[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