Skip to contentSkip to conversation

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

PATCH New Leo Yan 2 participants 3 messages Apr 1, 2014 2 messages not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

Leo Yan

author
#2 lore raw

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

hi David,

I have checked the ARMv8's Architecture Reference Manual DDI0487A_a_armv8_arm.pdf chapter "C4.4.1
DC CISW, Data or unified Cache line Clean and Invalidate by Set/Way", u can see the description as below:

SetWay, bits [31:4]
Contains two fields:
? Way, bits[31:32-A], the number of the way to operate on.
? Set, bits[B-1:L], the number of the set to operate on. Bits[L-1:4] are RES0.
A = Log2(ASSOCIATIVITY), L = Log2(LINELEN), B = (L + S), S = Log2(NSETS). ASSOCIATIVITY, LINELEN (line length, in bytes), and NSETS (number of sets) have their usual meanings and are the values for the cache level being operated on. The values of A and S are rounded up to the next integer.

Also we have tested on ARMv8's soc, we found this issue will introduce the cache cannot flush properly into DDR so that kernel cannot boot up successfully.

BTW, i compared with Linux kernel's code for flushing operations and just commit this patch to align with it.

Thx,
Leo Yan

Quoted 39 lines · fenghua at phytium.com.cn

hi Leo,
Please reference ARMv8-TRM, the associativity field does not have
to be a power of 2. I made the same mistake with you previously and
scott identify this.

*???:* Leo Yan <mailto:[email protected]>
*????:* ?2014???3???31??, ???? ?9?:?11
*???:* u-boot <mailto:[email protected]>, David Feng <mailto:[email protected]>, Scott Wood <mailto:[email protected]> *??:* Leo Yan <mailto:[email protected]>

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 -4
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 */
--

1.7.9.5

author
#3 lore raw

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

hi David,

Quoted 32 lines · fenghua at phytium.com.cn
Quoted 31 lines

hi Leo,
Please reference ARMv8-TRM, the associativity field does not have
to be a power of 2. I made the same mistake with you previously and
scott identify this.

*???:* Leo Yan <mailto:[email protected]>
*????:* ?2014???3???31??, ???? ?9?:?11
*???:* u-boot <mailto:[email protected]>, David Feng <mailto:[email protected]>, Scott Wood <mailto:[email protected]> *??:* Leo Yan <mailto:[email protected]>

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 -2
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) */
Quoted 8 lines
Quoted 8 lines
arch/arm/cpu/armv8/cache.S +1 -2
- 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 */
--

1.7.9.5

Apologize for top post in previous email, resend the email again.

I have checked the ARMv8's Architecture Reference Manual DDI0487A_a_armv8_arm.pdf chapter "C4.4.1 DC CISW, Data or unified Cache line Clean and Invalidate by Set/Way", u can see the description as below:

SetWay, bits [31:4]
Contains two fields:
? Way, bits[31:32-A], the number of the way to operate on. ? Set, bits[B-1:L], the number of the set to operate on.
Bits[L-1:4] are RES0.
A = Log2(ASSOCIATIVITY), L = Log2(LINELEN), B = (L + S), S = Log2(NSETS). ASSOCIATIVITY, LINELEN (line length, in bytes), and NSETS (number of sets) have their usual meanings and are the values for the cache level being operated on. The values of A and S are rounded up to the next integer.

Also we have tested on ARMv8's soc, we found this issue will introduce the cache cannot flush properly into DDR so that kernel cannot boot up successfully.

BTW, i compared with Linux kernel's code for flushing operations and just commit this patch to align with it.

Thx,
Leo Yan

#4 lore raw

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

In reply to a message not in the archive
Quoted 38 lines

-----Original Messages-----
From: "Leo Yan" <[email protected]>
Sent Time: 2014-03-31 09:11:47 (Monday)
To: u-boot at lists.denx.de, "David Feng" <[email protected]>, "Scott Wood" <[email protected]>
Cc: "Leo Yan" <[email protected]>
Subject: [PATCH] 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

Thank you.

Best Wishes.