Skip to contentSkip to conversation

ARMv8: fix bug for flush data cache by set/way

PATCH New Leo Yan 3 participants 3 messages Mar 31, 2014 – Apr 7, 2014 Arm (32-bit)

lore
Share & tools
lore

Leo Yan

author
#0 lore raw

PATCH 1/1 ARMv8: fix bug for flush data cache by set/way

When flush the d$ with set/way instruction, it need calculate the way's offset = log2(Associativity); but in current uboot's code, it use below formula to calculate the offset: log2(Associativity * 2 - 1), so finally it cannot flush data cache properly.

---
 arch/arm/cpu/armv8/cache.S |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
arch/arm/cpu/armv8/cache.S +1 -3
index 546a83e..256d2e2 100644
@@ -30,9 +30,7 @@ ENTRY(__asm_flush_dcache_level)
 	add	x2, x2, #4		/* x2 <- log2(cache line size) */
 	mov	x3, #0x3ff
 	and	x3, x3, x6, lsr #3	/* x3 <- max number of #ways */
-	add	w4, w3, w3
-	sub	w4, w4, 1		/* round up log2(#ways + 1) */
-	clz	w5, w4			/* bit position of #ways */
+	clz	w5, w3			/* bit position of #ways */
 	mov	x4, #0x7fff
 	and	x4, x4, x6, lsr #13	/* x4 <- max number of #sets */
 	/* x1 <- cache level << 1 */
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 1/1 ARMv8: fix bug for flush data cache by set/way

Hi Leo,

Quoted 15 lines · Leo Yan

When flush the d$ with set/way instruction, it need calculate the way's offset = log2(Associativity); but in current uboot's code, it use below formula to calculate the offset: log2(Associativity * 2 - 1), so finally it cannot flush data cache properly.

---
 arch/arm/cpu/armv8/cache.S |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
arch/arm/cpu/armv8/cache.S +0 -0
index 546a83e..256d2e2 100644

arch/arm/cpu/armv8/cache.S ENTRY(__asm_flush_dcache_level) · line 36

Quoted 10 lines
arch/arm/cpu/armv8/cache.S +1 -3
@@ -30,9 +30,7 @@ ENTRY(__asm_flush_dcache_level)
 	add	x2, x2, #4		/* x2 <- log2(cache line size) */
 	mov	x3, #0x3ff
 	and	x3, x3, x6, lsr #3	/* x3 <- max number of #ways */
-	add	w4, w3, w3
-	sub	w4, w4, 1		/* round up log2(#ways + 1) */
-	clz	w5, w4			/* bit position of #ways */
+	clz	w5, w3			/* bit position of #ways */
 	mov	x4, #0x7fff
 	and	x4, x4, x6, lsr #13	/* x4 <- max number of #sets */
 	/* x1 <- cache level << 1 */

Applied to u-boot-arm/master, thanks!

Amicalement,

Signature · 1 line
Albert.
#2 lore raw

PATCH 1/1 ARMv8: fix bug for flush data cache by set/way

In reply to Leo Yan
Quoted 4 lines · Leo Yan

When flush the d$ with set/way instruction, it need calculate the way's offset = log2(Associativity); but in current uboot's code, it use below formula to calculate the offset: log2(Associativity * 2 - 1), so finally it cannot flush data cache properly.

More specifically, the "Associativity" above is actually "Associativity
- 1", and clz isn't quite log2().

Quoted 10 lines
---
 arch/arm/cpu/armv8/cache.S |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
arch/arm/cpu/armv8/cache.S +0 -0
index 546a83e..256d2e2 100644

arch/arm/cpu/armv8/cache.S ENTRY(__asm_flush_dcache_level) · line 36

Quoted 10 lines
arch/arm/cpu/armv8/cache.S +1 -3
@@ -30,9 +30,7 @@ ENTRY(__asm_flush_dcache_level)
 	add	x2, x2, #4		/* x2 <- log2(cache line size) */
 	mov	x3, #0x3ff
 	and	x3, x3, x6, lsr #3	/* x3 <- max number of #ways */
-	add	w4, w3, w3
-	sub	w4, w4, 1		/* round up log2(#ways + 1) */
-	clz	w5, w4			/* bit position of #ways */
+	clz	w5, w3			/* bit position of #ways */
 	mov	x4, #0x7fff
 	and	x4, x4, x6, lsr #13	/* x4 <- max number of #sets */
 	/* x1 <- cache level << 1 */

I believe the new code will fail on a cache with associativity 1. x3 would be 0, since it's actually associativity minus one, and thus w5 would be 32. w5 is later interpreted as x5, so it would actually do a 32-bit shift rather than whatever behavior ARM specifies for shift counts larger than the word size.

-Scott