Device memory needs to be set along with PXN and UNX bits. Normal memory must clear these bits. To support modification of PXN, UXN bits, extend existing function mmu_set_region_dcache_behaviour() to accept attributes directly. Also fix parsing d-cache option by removing extra shifting.
Signed-off-by: York Sun <york....@nxp.com> CC: Alexander Graf <ag...@suse.de> --- Looks like original function mmu_set_region_dcache_behaviour() was written to support changing d-cache option. However the PMD_ATTRINDX(option) shifts it further higher. Maybe this function wasn't really used for ARMv8. I have a need to update existing MMU table with a little bit more than d-cache options. With a recent debug on memory barrier, it came to my attention that code should run on "normal" memory, while "device" memory should have PXN and UXN bits set. A new function mmu_set_region_attr() is hence introduced and mmu_set_region_dcache_behaviour() becomes a wrapper. BTW, if we don't plan to use "read_start" and "real_size" variables, they should be removed. arch/arm/cpu/armv8/cache_v8.c | 28 +++++++++++++++++++--------- arch/arm/include/asm/armv8/mmu.h | 1 + arch/arm/include/asm/system.h | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index afa76c1..3b2f3f8 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -509,8 +509,8 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, int level) /* Can we can just modify the current level block PTE? */ if (is_aligned(start, size, levelsize)) { - *pte &= ~PMD_ATTRINDX_MASK; - *pte |= attrs; + *pte &= ~PMD_ATTRMASK; + *pte |= attrs & PMD_ATTRMASK; debug("Set attrs=%llx pte=%p level=%d\n", attrs, pte, level); return levelsize; @@ -532,13 +532,8 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, int level) return 0; } -void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, - enum dcache_option option) +void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs) { - u64 attrs = PMD_ATTRINDX(option); - u64 real_start = start; - u64 real_size = size; - debug("start=%lx size=%lx\n", (ulong)start, (ulong)size); if (!gd->arch.tlb_emerg) @@ -572,7 +567,19 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, } /* We're done modifying page tables, switch back to our primary ones */ + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); __asm_switch_ttbr(gd->arch.tlb_addr); +} + +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ + u64 attrs = option; + u64 real_start = start; + u64 real_size = size; + + mmu_set_region_attr(start, size, attrs); /* * Make sure there's nothing stale in dcache for a region that might @@ -580,7 +587,6 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, */ flush_dcache_range(real_start, real_start + real_size); } - #else /* CONFIG_SYS_DCACHE_OFF */ /* @@ -613,6 +619,10 @@ int dcache_status(void) return 0; } +void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs) +{ +} + void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, enum dcache_option option) { diff --git a/arch/arm/include/asm/armv8/mmu.h b/arch/arm/include/asm/armv8/mmu.h index 58aecb9..c1cff23 100644 --- a/arch/arm/include/asm/armv8/mmu.h +++ b/arch/arm/include/asm/armv8/mmu.h @@ -86,6 +86,7 @@ */ #define PMD_ATTRINDX(t) ((t) << 2) #define PMD_ATTRINDX_MASK (7 << 2) +#define PMD_ATTRMASK (PTE_BLOCK_PXN | PTE_BLOCK_UXN | PMD_ATTRINDX_MASK) /* * TCR flags. diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index dc4c991..81709ec 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -224,6 +224,7 @@ void protect_secure_region(void); void smp_kick_all_cpus(void); void flush_l3_cache(void); +void mmu_set_region_attr(phys_addr_t start, size_t size, u64 attrs); /* *Issue a secure monitor call in accordance with ARM "SMC Calling convention", -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot