From 21401f714491cf0f3654c82b036c060184254365 Mon Sep 17 00:00:00 2001 From: Stanislav Date: Fri, 12 Jul 2024 10:39:20 +0100 Subject: [PATCH] ARCv3: L2$ fix flush/invalidate address range {CACHE_ADDR_HI1, CACHE_ADDR_HI0} registers determine the final address of the requested L2$ operation. This address specifies the end of the range, and it is inclusive. Prior to this fix, one cache line outside of the requested range could be mistakenly flushed or invalidated. --- arch/arc/mm/cache-arcv3.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arc/mm/cache-arcv3.c b/arch/arc/mm/cache-arcv3.c index c4de4ac2c014f7..aab8db688286e3 100644 --- a/arch/arc/mm/cache-arcv3.c +++ b/arch/arc/mm/cache-arcv3.c @@ -181,8 +181,12 @@ static void dcache_op_rgn(phys_addr_t paddr, int sz, const int op) unsigned long end; unsigned long flags; + if (sz <= 0) + return; + local_irq_save(flags); + /* The line specified by DC_ENDR is excluded for L1$ */ end = paddr + sz + L1_CACHE_BYTES - 1; dc_op_before(op); @@ -214,6 +218,9 @@ static void scm_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) unsigned int cmd; u64 end; + if (sz == 0) + return; + cmd = ARC_CLN_CACHE_CMD_INCR; /* Iterate over all available ways */ if (op == OP_INV) { /* Invalidate any line in the cache whose block address is in the range */ @@ -229,9 +236,10 @@ static void scm_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) /* * Lower bits are ignored, no need to clip - * END can't be same as START, so add (l2_info.line_len - 1) to sz + * The range specified by [{CACHE_ADDR_LO1, CACHE_ADDR_LO0,}, + * {CACHE_ADDR_HI1, CACHE_ADDR_HI0}] is inclusive for L2$ */ - end = paddr + sz + l2_info.line_len - 1; + end = paddr + sz - 1; spin_lock_irqsave(&lock, flags);