~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/arch/riscv/cmodx.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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, PR_RISCV_CTX_SW_FENCEI_ON, 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, PR_RISCV_CTX_SW_FENCEI_OFF, 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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php