[PATCH v5 01/14] riscv: only use IPIs to handle cache-flushes on remote cpus

Heiko Stuebner
2022-01-21T16:37:22Z

Right now, the flush_icache functions always use the SBI remote-fence
when SBI is available, leaving using IPIs as a fallback mechanism.

IPIs on the other hand are more flexible, as the ipi_ops are initially
set to go through SBI but later will be overwritten to go through the
ACLINT/CLINT.

In a discussion we had, Nick was of the opinion that "In general we
should prefer doing IPIs on S-mode through CLINT instead of going
through SBI/M-mode, so IMHO we should only be using
on_each_cpu_mask(ipi_remote_fence_i) on flush_icache_all()/
flush_icache_mm() and remove any explicit calls to sbi_remote_fence_i(),
because this way we continue using SBI for doing remote fences even after
CLINT/ACLINT driver is registered, instead of using direct IPIs through
CLINT/ACLINT."

So follow this suggestion and just do ipi calls to have the proper kernel
parts do them,

This also fixes the null-ptr dereference happening when flush_icache_all()
is called before sbi_init().

Suggested-by: Nick Kossifidis <mick@ics.forth.gr>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/riscv/mm/cacheflush.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c
index 6cb7d96ad9c7..c35375cd52ec 100644
--- a/arch/riscv/mm/cacheflush.c
+++ b/arch/riscv/mm/cacheflush.c
@@ -17,11 +17,7 @@ static void ipi_remote_fence_i(void *info)
void flush_icache_all(void)
{
local_flush_icache_all();
-
- if (IS_ENABLED(CONFIG_RISCV_SBI))
- sbi_remote_fence_i(NULL);
- else
- on_each_cpu(ipi_remote_fence_i, NULL, 1);
+ on_each_cpu(ipi_remote_fence_i, NULL, 1);
}
EXPORT_SYMBOL(flush_icache_all);

@@ -66,8 +62,6 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
* with flush_icache_deferred().
*/
smp_mb();
- } else if (IS_ENABLED(CONFIG_RISCV_SBI)) {
- sbi_remote_fence_i(&others);
} else {
on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
}
--
2.30.2