aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGilbert Gilb's <gilbsgilbert@gmail.com>2023-11-13 12:36:24 +0100
committerHan Gao/Revy/Rabenda <rabenda.cn@gmail.com>2023-12-15 23:35:31 +0800
commitadec30ace4cebb0554bb246b52eebaf37c1545c4 (patch)
treee704f5a68664c7968c3e379cc478e4b2d3ff0d90 /arch
parent76320896523519fceedd9f347b6cf6aeabf91eb7 (diff)
fix(c9xx): don't flush dcache when invalidating
The data cache invalidation function for c9xx CPUs uses `dcache.cipa` instruction. According to T-Head extension specification[1] section 3.1.5, this instruction also performs a cache clean along with the invalidation. On top of being incorrect, this leads to a serious issue on the designware ethernet driver, where stalled cache may get flushed each time we handle a new received packet[2]. As a result, received packet are randomly corrupted with old cached data. This can easily be reproduced by sending an ARP request to the device during a TFTP transfer. The last TFTP block is treated as the ARP reply we just sent, which makes U-Boot hang on the block. Always use `dcache.ipa` instruction to invalidate dcache. Replace existing usages of `dcache.ipa` with our implementation. Note that this fix is slightly intrusive as it changes the cache invalidation behavior in all drivers. However, I have not noticed any side-effect during my tests. [1] https://github.com/T-head-Semi/thead-extension-spec/releases/download/2.3.0/xthead-2023-11-10-2.3.0.pdf [2] https://github.com/revyos/thead-u-boot/blob/918a8c89e056e3462031d6a498bb4fcc0c3526ce/drivers/net/designware.c#L475
Diffstat (limited to 'arch')
-rw-r--r--arch/riscv/cpu/c9xx/cpu.c10
1 files changed, 0 insertions, 10 deletions
diff --git a/arch/riscv/cpu/c9xx/cpu.c b/arch/riscv/cpu/c9xx/cpu.c
index e5eaed94..a93a3060 100644
--- a/arch/riscv/cpu/c9xx/cpu.c
+++ b/arch/riscv/cpu/c9xx/cpu.c
@@ -105,16 +105,6 @@ void invalidate_dcache_range(unsigned long start, unsigned long end)
register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE)
- asm volatile(".long 0x02b5000b"); /* dcache.cipa a0 */
-
- sync_is();
-}
-
-void invalid_dcache_range(unsigned long start, unsigned long end)
-{
- register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1);
-
- for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE)
asm volatile(".long 0x02a5000b"); /* dcache.ipa a0 */
sync_is();