[PATCH] arm: armv8: mmu: fix DCACHE_OFF incorrectly unmapping region
Ilias Apalodimas
ilias.apalodimas at linaro.org
Wed Jul 8 13:47:59 CEST 2026
Hi Akshay
On Wed, 8 Jul 2026 at 14:17, Akshay Belsare <akshay.belsare at amd.com> 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 <ilias.apalodimas at linaro.org>
>
> 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 <akshay.belsare at amd.com>
> ---
> 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
>
More information about the U-Boot
mailing list