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

Reply via email to