Skip to content

Commit 6a08e47

Browse files
charlie-rivospalmer-dabbelt
authored andcommitted
documentation: Document PR_RISCV_SET_ICACHE_FLUSH_CTX prctl
Provide documentation that explains how to properly do CMODX in riscv. Signed-off-by: Charlie Jenkins <[email protected]> Reviewed-by: Atish Patra <[email protected]> Reviewed-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 6b9391b commit 6a08e47

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

Documentation/arch/riscv/cmodx.rst

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
==============================================================================
4+
Concurrent Modification and Execution of Instructions (CMODX) for RISC-V Linux
5+
==============================================================================
6+
7+
CMODX is a programming technique where a program executes instructions that were
8+
modified by the program itself. Instruction storage and the instruction cache
9+
(icache) are not guaranteed to be synchronized on RISC-V hardware. Therefore, the
10+
program must enforce its own synchronization with the unprivileged fence.i
11+
instruction.
12+
13+
However, the default Linux ABI prohibits the use of fence.i in userspace
14+
applications. At any point the scheduler may migrate a task onto a new hart. If
15+
migration occurs after the userspace synchronized the icache and instruction
16+
storage with fence.i, the icache on the new hart will no longer be clean. This
17+
is due to the behavior of fence.i only affecting the hart that it is called on.
18+
Thus, the hart that the task has been migrated to may not have synchronized
19+
instruction storage and icache.
20+
21+
There are two ways to solve this problem: use the riscv_flush_icache() syscall,
22+
or use the ``PR_RISCV_SET_ICACHE_FLUSH_CTX`` prctl() and emit fence.i in
23+
userspace. The syscall performs a one-off icache flushing operation. The prctl
24+
changes the Linux ABI to allow userspace to emit icache flushing operations.
25+
26+
As an aside, "deferred" icache flushes can sometimes be triggered in the kernel.
27+
At the time of writing, this only occurs during the riscv_flush_icache() syscall
28+
and when the kernel uses copy_to_user_page(). These deferred flushes happen only
29+
when the memory map being used by a hart changes. If the prctl() context caused
30+
an icache flush, this deferred icache flush will be skipped as it is redundant.
31+
Therefore, there will be no additional flush when using the riscv_flush_icache()
32+
syscall inside of the prctl() context.
33+
34+
prctl() Interface
35+
---------------------
36+
37+
Call prctl() with ``PR_RISCV_SET_ICACHE_FLUSH_CTX`` as the first argument. The
38+
remaining arguments will be delegated to the riscv_set_icache_flush_ctx
39+
function detailed below.
40+
41+
.. kernel-doc:: arch/riscv/mm/cacheflush.c
42+
:identifiers: riscv_set_icache_flush_ctx
43+
44+
Example usage:
45+
46+
The following files are meant to be compiled and linked with each other. The
47+
modify_instruction() function replaces an add with 0 with an add with one,
48+
causing the instruction sequence in get_value() to change from returning a zero
49+
to returning a one.
50+
51+
cmodx.c::
52+
53+
#include <stdio.h>
54+
#include <sys/prctl.h>
55+
56+
extern int get_value();
57+
extern void modify_instruction();
58+
59+
int main()
60+
{
61+
int value = get_value();
62+
printf("Value before cmodx: %d\n", value);
63+
64+
// Call prctl before first fence.i is called inside modify_instruction
65+
prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX_ON, PR_RISCV_CTX_SW_FENCEI, PR_RISCV_SCOPE_PER_PROCESS);
66+
modify_instruction();
67+
// Call prctl after final fence.i is called in process
68+
prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX_OFF, PR_RISCV_CTX_SW_FENCEI, PR_RISCV_SCOPE_PER_PROCESS);
69+
70+
value = get_value();
71+
printf("Value after cmodx: %d\n", value);
72+
return 0;
73+
}
74+
75+
cmodx.S::
76+
77+
.option norvc
78+
79+
.text
80+
.global modify_instruction
81+
modify_instruction:
82+
lw a0, new_insn
83+
lui a5,%hi(old_insn)
84+
sw a0,%lo(old_insn)(a5)
85+
fence.i
86+
ret
87+
88+
.section modifiable, "awx"
89+
.global get_value
90+
get_value:
91+
li a0, 0
92+
old_insn:
93+
addi a0, a0, 0
94+
ret
95+
96+
.data
97+
new_insn:
98+
addi a0, a0, 1

Documentation/arch/riscv/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ RISC-V architecture
1313
patch-acceptance
1414
uabi
1515
vector
16+
cmodx
1617

1718
features
1819

0 commit comments

Comments
 (0)