ARMv8: fix bug for flush data cache by set/way
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
@@ -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
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.Signed-off-by Leo Yan <[email protected]>--- arch/arm/cpu/armv8/cache.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/arm/cpu/armv8/cache.S +0
-0
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.
PATCH 1/1 ARMv8: fix bug for flush data cache by set/way
In reply to Leo YanQuoted 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
Signed-off-by Leo Yan <[email protected]>--- arch/arm/cpu/armv8/cache.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/arm/cpu/armv8/cache.S +0
-0
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