The PTE_USER bit (AP[1]) in a page entry means that lower privilege levels (EL0, on arm64, or PL0, on arm) can read and write from that memory location [1][2]. On arm64, it also implies PXN (Privileged execute-never) when is set [3]. Add a function to clear the bit which we can use when we want to execute code from that page or the prevent access from lower exception levels. Make it available to arm too, in case someone needs it at some point. [1] ARM DDI 0406C.d, Table B3-6 [2] ARM DDI 0487E.a, table D5-28 [3] ARM DDI 0487E.a, table D5-33 Signed-off-by: Alexandru Elisei <alexandru.elisei@xxxxxxx> --- lib/arm/asm/mmu-api.h | 1 + lib/arm/mmu.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/arm/asm/mmu-api.h b/lib/arm/asm/mmu-api.h index df3ccf7bc7e0..8fe85ba31ec9 100644 --- a/lib/arm/asm/mmu-api.h +++ b/lib/arm/asm/mmu-api.h @@ -22,4 +22,5 @@ extern void mmu_set_range_sect(pgd_t *pgtable, uintptr_t virt_offset, extern void mmu_set_range_ptes(pgd_t *pgtable, uintptr_t virt_offset, phys_addr_t phys_start, phys_addr_t phys_end, pgprot_t prot); +extern void mmu_clear_user(unsigned long vaddr); #endif diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 3d38c8397f5a..78db22e6af14 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -217,3 +217,18 @@ unsigned long __phys_to_virt(phys_addr_t addr) assert(!mmu_enabled() || __virt_to_phys(addr) == addr); return addr; } + +void mmu_clear_user(unsigned long vaddr) +{ + pgd_t *pgtable; + pteval_t *pte; + + if (!mmu_enabled()) + return; + + pgtable = current_thread_info()->pgtable; + pte = get_pte(pgtable, vaddr); + + *pte &= ~PTE_USER; + flush_tlb_page(vaddr); +} -- 2.20.1