Hi Akshay On Wed, 8 Jul 2026 at 14:17, Akshay Belsare <[email protected]> wrote: > > 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.
I don't really love the 'flag' attribute that distinguishes between preserving or overwriting the permission bits... However, this does fix an issue. Reviewed-by: Ilias Apalodimas <[email protected]> > > 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]> > --- > arch/arm/cpu/armv8/cache_v8.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > 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 > -- > 2.25.1 >

