summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Belsare <[email protected]>2026-07-08 16:47:10 +0530
committerTom Rini <[email protected]>2026-07-23 15:16:29 -0600
commitd7ef23c07b8e34f65b3e15e3b4e7f58d074923c8 (patch)
tree05ef6b6eff0cec6ce929208b0dd23472111250a2
parent64ce0f86ab9ce931013195b68276770d8e02b40f (diff)
arm: armv8: mmu: fix DCACHE_OFF incorrectly unmapping region
DCACHE_OFF is defined as (0 << 2) = 0, and PTE_TYPE_FAULT is defined as (0 << 0) = 0. In mmu_set_region_dcache_behaviour(), the cache attribute passed to set_regions() is computed as: attrs = PMD_ATTRINDX(option >> 2) For DCACHE_OFF=0 this evaluates to PMD_ATTRINDX(0) = 0, which equals PTE_TYPE_FAULT. Commit 6468ca13ffd6f ("armv8: mmu: fix and optimise explicitly unmapping regions") added an unmap path to set_one_region() that triggers when attrs == PTE_TYPE_FAULT. Because DCACHE_OFF and PTE_TYPE_FAULT share the same numerical value (0), any call to mmu_set_region_dcache_behaviour() with DCACHE_OFF silently unmaps the target region instead of changing its cache attributes to non-cached. The subsequent flush_dcache_range() call at the end of mmu_set_region_dcache_behaviour() then crashes with a Level 3 translation fault because the region it tries to flush has just been unmapped. The existing flag parameter already distinguishes the two callers: - mmu_set_region_dcache_behaviour() always passes flag=false - mmu_change_region_attr_nobreak() always passes flag=true, and is the only legitimate caller that passes PTE_TYPE_FAULT to unmap a region Guard the unmap path with flag so that DCACHE_OFF attribute changes take the correct else branch, which ORs in the ATTRINDX bits only, leaving the PTE valid. This was observed as a boot crash on Versal, Versal Net, and ZynqMP platforms during network initialisation. The zynq_gem driver calls mmu_set_region_dcache_behaviour() with DCACHE_OFF to make its BD descriptor ring non-cached. With the bug the BD memory is unmapped, and the subsequent dcache flush inside mmu_set_region_dcache_behaviour() faults. Fixes: 6468ca13ffd6f ("armv8: mmu: fix and optimise explicitly unmapping regions") Signed-off-by: Akshay Belsare <[email protected]> Reviewed-by: Ilias Apalodimas <[email protected]>
-rw-r--r--arch/arm/cpu/armv8/cache_v8.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
index e59528e576e..ad232435eb2 100644
--- a/arch/arm/cpu/armv8/cache_v8.c
+++ b/arch/arm/cpu/armv8/cache_v8.c
@@ -1006,7 +1006,7 @@ static u64 set_one_region(u64 start, u64 size, u64 attrs, bool flag, int level)
/* Can we can just modify the current level block/page? */
if (is_aligned(start, size, levelsize)) {
- if (attrs == PTE_TYPE_FAULT) {
+ if (attrs == PTE_TYPE_FAULT && flag) {
if (pte_type(pte) == PTE_TYPE_TABLE && level < 3)
*pte = 0;
else