<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>Hi all,<br><br></div>I'm writing here because after been reading a lot of papers regarding this topic, I still can't get the point with it.<br></div>Let me explain it:<br><br></div>I'm writing a module, and within this module I'm trying to emulate the lookup_address from x86, but on arm.<br><br></div>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).<br></div><br>Then, since I'm working on arm32 without LPAE, Linux is just using PMD (pgd and pud are gone).<br><br></div>As it explains here: include/asm/pgtable-2level.h<br></div>The layout pte page tables looks like:<br><br></div>- linux_pte_0<br></div>- linux_pte_1<br></div>- arm_pte_0<br></div>- arm_pte_1<br><br></div><div>That's within a page.<br></div><div><br></div>linux_pte_* are being used in order that linux can check for dirty/young bits since ARM does not provide such bits.<br><br></div>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[]).<br><br></div>For example:<br><br></div>In function alloc_init_pte we call arm_pte_alloc in order:<br><br></div>- Allocate PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE bytes (4096bytes)<br></div>- populate pmd with (function __pmd_populate):<br></div>       - physical memory of space allocated before + PTE_HWTABLE_OFF (2048bytes) | protecion_bits<br></div>        - this ends up with: pmdval of this pmd stores: physical_address_of_arm_pte|<wbr>protection_bits<br><br></div>code from __pmd_populate:<br><br> pmdval_t pmdval = (pte + PTE_HWTABLE_OFF) | prot;<br> pmdp[0] = __pmd(pmdval);<br><br></div>Once this is done, arm_pte_alloc returns with pte_offset_kernel, which does this steps:<br><br></div> - ANDs the value of this pmd with PHYS_MASK && PAGE_MASK<br></div> - return the virtual address of the value stored before (returns vaddrr of the top of page=<br> - adds virtual_address of this page + pte_index (addr)<br><br></div><div>Once this is done, the arm page tables permissions are being set with:<br><br>set_pte_ext function, that in my case is going to call cpu_v7_set_pte_ext function from mm/proc-v7-2level.S.<br></div><div>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).<br></div><div><br></div>Given this explanation I'll what I'm doing:<br><br></div><div>Let's say I want to get the pte of X (X is a linear address)<br></div><div><br></div>pgd = get_global_pgd_from_ttbr1 (same value as swapper_pg_dir)<br></div>pgd += pgd_index (X)<br></div>pud = pud_offset (pgd, X)<br></div>pmd = pmd_offset (pud, X)<br><br></div>At this point, pmd should contain: (pte + PTE_HWTABLE_OFF) | prot  (since it was populated with this value).<br><br></div>Then:<br><br></div>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))<br><br></div>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.<br><br><br></div><div>I hope I could explain my question as clear as I wanted.<br><br></div><div>Thank you very much<br></div><div>Oscar Salvador<br></div></div>