Skip to content

Commit

Permalink
riscv: add a data fence for CMODX in the kernel mode
Browse files Browse the repository at this point in the history
[ Upstream commit ca35869 ]

RISC-V spec explicitly calls out that a local fence.i is not enough for
the code modification to be visble from a remote hart. In fact, it
states:

To make a store to instruction memory visible to all RISC-V harts, the
writing hart also has to execute a data FENCE before requesting that all
remote RISC-V harts execute a FENCE.I.

Although current riscv drivers for IPI use ordered MMIO when sending IPIs
in order to synchronize the action between previous csd writes, riscv
does not restrict itself to any particular flavor of IPI. Any driver or
firmware implementation that does not order data writes before the IPI
may pose a risk for code-modifying race.

Thus, add a fence here to order data writes before making the IPI.

Signed-off-by: Andy Chiu <andybnac@gmail.com>
Reviewed-by: Björn Töpel <bjorn@rivosinc.com>
Link: https://lore.kernel.org/r/20250407180838.42877-8-andybnac@gmail.com
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Andy Chiu authored and Greg Kroah-Hartman committed Jul 6, 2025
1 parent 0fe76b1 commit 03f0516
Showing 1 changed file with 14 additions and 1 deletion.
15 changes: 14 additions & 1 deletion arch/riscv/mm/cacheflush.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,20 @@ void flush_icache_all(void)

if (num_online_cpus() < 2)
return;
else if (riscv_use_sbi_for_rfence())

/*
* Make sure all previous writes to the D$ are ordered before making
* the IPI. The RISC-V spec states that a hart must execute a data fence
* before triggering a remote fence.i in order to make the modification
* visable for remote harts.
*
* IPIs on RISC-V are triggered by MMIO writes to either CLINT or
* S-IMSIC, so the fence ensures previous data writes "happen before"
* the MMIO.
*/
RISCV_FENCE(w, o);

if (riscv_use_sbi_for_rfence())
sbi_remote_fence_i(NULL);
else
on_each_cpu(ipi_remote_fence_i, NULL, 1);
Expand Down

0 comments on commit 03f0516

Please sign in to comment.