nsphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget$/translations/zh_CN/arch/riscv/cmodxmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/zh_TW/arch/riscv/cmodxmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/it_IT/arch/riscv/cmodxmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ja_JP/arch/riscv/cmodxmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/ko_KR/arch/riscv/cmodxmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget$/translations/sp_SP/arch/riscv/cmodxmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhh>/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx.rsthKubhsection)}(hhh](htitle)}(hNConcurrent Modification and Execution of Instructions (CMODX) for RISC-V Linuxh]hNConcurrent Modification and Execution of Instructions (CMODX) for RISC-V Linux}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hXHCMODX is a programming technique where a program executes instructions that were modified by the program itself. Instruction storage and the instruction cache (icache) are not guaranteed to be synchronized on RISC-V hardware. Therefore, the program must enforce its own synchronization with the unprivileged fence.i instruction.h]hXHCMODX is a programming technique where a program executes instructions that were modified by the program itself. Instruction storage and the instruction cache (icache) are not guaranteed to be synchronized on RISC-V hardware. Therefore, the program must enforce its own synchronization with the unprivileged fence.i instruction.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hXHowever, the default Linux ABI prohibits the use of fence.i in userspace applications. At any point the scheduler may migrate a task onto a new hart. If migration occurs after the userspace synchronized the icache and instruction storage with fence.i, the icache on the new hart will no longer be clean. This is due to the behavior of fence.i only affecting the hart that it is called on. Thus, the hart that the task has been migrated to may not have synchronized instruction storage and icache.h]hXHowever, the default Linux ABI prohibits the use of fence.i in userspace applications. At any point the scheduler may migrate a task onto a new hart. If migration occurs after the userspace synchronized the icache and instruction storage with fence.i, the icache on the new hart will no longer be clean. This is due to the behavior of fence.i only affecting the hart that it is called on. Thus, the hart that the task has been migrated to may not have synchronized instruction storage and icache.}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK hhhhubh)}(hX4There are two ways to solve this problem: use the riscv_flush_icache() syscall, or use the ``PR_RISCV_SET_ICACHE_FLUSH_CTX`` prctl() and emit fence.i in userspace. The syscall performs a one-off icache flushing operation. The prctl changes the Linux ABI to allow userspace to emit icache flushing operations.h](h[There are two ways to solve this problem: use the riscv_flush_icache() syscall, or use the }(hhhhhNhNubhliteral)}(h!``PR_RISCV_SET_ICACHE_FLUSH_CTX``h]hPR_RISCV_SET_ICACHE_FLUSH_CTX}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhubh prctl() and emit fence.i in userspace. The syscall performs a one-off icache flushing operation. The prctl changes the Linux ABI to allow userspace to emit icache flushing operations.}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hX As an aside, "deferred" icache flushes can sometimes be triggered in the kernel. At the time of writing, this only occurs during the riscv_flush_icache() syscall and when the kernel uses copy_to_user_page(). These deferred flushes happen only when the memory map being used by a hart changes. If the prctl() context caused an icache flush, this deferred icache flush will be skipped as it is redundant. Therefore, there will be no additional flush when using the riscv_flush_icache() syscall inside of the prctl() context.h]hXAs an aside, “deferred” icache flushes can sometimes be triggered in the kernel. At the time of writing, this only occurs during the riscv_flush_icache() syscall and when the kernel uses copy_to_user_page(). These deferred flushes happen only when the memory map being used by a hart changes. If the prctl() context caused an icache flush, this deferred icache flush will be skipped as it is redundant. Therefore, there will be no additional flush when using the riscv_flush_icache() syscall inside of the prctl() context.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(hprctl() Interfaceh]hprctl() Interface}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK#ubh)}(hCall prctl() with ``PR_RISCV_SET_ICACHE_FLUSH_CTX`` as the first argument. The remaining arguments will be delegated to the riscv_set_icache_flush_ctx function detailed below.h](hCall prctl() with }(hj(hhhNhNubh)}(h!``PR_RISCV_SET_ICACHE_FLUSH_CTX``h]hPR_RISCV_SET_ICACHE_FLUSH_CTX}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj(ubh| as the first argument. The remaining arguments will be delegated to the riscv_set_icache_flush_ctx function detailed below.}(hj(hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK%hjhhubhindex)}(hhh]h}(h]h ]h"]h$]h&]entries](single'riscv_set_icache_flush_ctx (C function)c.riscv_set_icache_flush_ctxhNtauh1jHhjhhhNhNubhdesc)}(hhh](hdesc_signature)}(hGint riscv_set_icache_flush_ctx (unsigned long ctx, unsigned long scope)h]hdesc_signature_line)}(hFint riscv_set_icache_flush_ctx(unsigned long ctx, unsigned long scope)h](hdesc_sig_keyword_type)}(hinth]hint}(hjlhhhNhNubah}(h]h ]ktah"]h$]h&]uh1jjhjfhhh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKubhdesc_sig_space)}(h h]h }(hj~hhhNhNubah}(h]h ]wah"]h$]h&]uh1j|hjfhhhj{hKubh desc_name)}(hriscv_set_icache_flush_ctxh]h desc_sig_name)}(hriscv_set_icache_flush_ctxh]hriscv_set_icache_flush_ctx}(hjhhhNhNubah}(h]h ]nah"]h$]h&]uh1jhjubah}(h]h ](sig-namedescnameeh"]h$]h&]hhuh1jhjfhhhj{hKubhdesc_parameterlist)}(h((unsigned long ctx, unsigned long scope)h](hdesc_parameter)}(hunsigned long ctxh](jk)}(hunsignedh]hunsigned}(hjhhhNhNubah}(h]h ]jwah"]h$]h&]uh1jjhjubj})}(h h]h }(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1j|hjubjk)}(hlongh]hlong}(hjhhhNhNubah}(h]h ]jwah"]h$]h&]uh1jjhjubj})}(h h]h }(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1j|hjubj)}(hctxh]hctx}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]noemphhhuh1jhjubj)}(hunsigned long scopeh](jk)}(hunsignedh]hunsigned}(hj hhhNhNubah}(h]h ]jwah"]h$]h&]uh1jjhjubj})}(h h]h }(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1j|hjubjk)}(hlongh]hlong}(hj%hhhNhNubah}(h]h ]jwah"]h$]h&]uh1jjhjubj})}(h h]h }(hj3hhhNhNubah}(h]h ]jah"]h$]h&]uh1j|hjubj)}(hscopeh]hscope}(hjAhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]noemphhhuh1jhjubeh}(h]h ]h"]h$]h&]hhuh1jhjfhhhj{hKubeh}(h]h ]h"]h$]h&]hh add_permalinkuh1jdsphinx_line_type declaratorhj`hhhj{hKubah}(h]jWah ](sig sig-objecteh"]h$]h&] is_multiline _toc_parts) _toc_namehuh1j^hj{hKhj[hhubh desc_content)}(hhh]h)}(h9Enable/disable icache flushing instructions in userspace.h]h9Enable/disable icache flushing instructions in userspace.}(hjuhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjrhhubah}(h]h ]h"]h$]h&]uh1jphj[hhhj{hKubeh}(h]h ](cfunctioneh"]h$]h&]domainjobjtypejdesctypejnoindex noindexentrynocontentsentryuh1jYhhhjhNhNubh container)}(hX)**Parameters** ``unsigned long ctx`` Set the type of icache flushing instructions permitted/prohibited in userspace. Supported values described below. ``unsigned long scope`` Set scope of where icache flushing instructions are allowed to be emitted. Supported values described below. **Description** Supported values for ctx: * ``PR_RISCV_CTX_SW_FENCEI_ON``: Allow fence.i in user space. * ``PR_RISCV_CTX_SW_FENCEI_OFF``: Disallow fence.i in user space. All threads in a process will be affected when ``scope == PR_RISCV_SCOPE_PER_PROCESS``. Therefore, caution must be taken; use this flag only when you can guarantee that no thread in the process will emit fence.i from this point onward. Supported values for scope: * ``PR_RISCV_SCOPE_PER_PROCESS``: Ensure the icache of any thread in this process is coherent with instruction storage upon migration. * ``PR_RISCV_SCOPE_PER_THREAD``: Ensure the icache of the current thread is coherent with instruction storage upon migration. When ``scope == PR_RISCV_SCOPE_PER_PROCESS``, all threads in the process are permitted to emit icache flushing instructions. Whenever any thread in the process is migrated, the corresponding hart's icache will be guaranteed to be consistent with instruction storage. This does not enforce any guarantees outside of migration. If a thread modifies an instruction that another thread may attempt to execute, the other thread must still emit an icache flushing instruction before attempting to execute the potentially modified instruction. This must be performed by the user-space program. In per-thread context (eg. ``scope == PR_RISCV_SCOPE_PER_THREAD``) only the thread calling this function is permitted to emit icache flushing instructions. When the thread is migrated, the corresponding hart's icache will be guaranteed to be consistent with instruction storage. On kernels configured without SMP, this function is a nop as migrations across harts will not occur.h](h)}(h**Parameters**h]hstrong)}(hjh]h Parameters}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubhdefinition_list)}(hhh](hdefinition_list_item)}(h``unsigned long ctx`` Set the type of icache flushing instructions permitted/prohibited in userspace. Supported values described below. h](hterm)}(h``unsigned long ctx``h]h)}(hjh]hunsigned long ctx}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh definition)}(hhh]h)}(hqSet the type of icache flushing instructions permitted/prohibited in userspace. Supported values described below.h]hqSet the type of icache flushing instructions permitted/prohibited in userspace. Supported values described below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhjubj)}(h``unsigned long scope`` Set scope of where icache flushing instructions are allowed to be emitted. Supported values described below. h](j)}(h``unsigned long scope``h]h)}(hjh]hunsigned long scope}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubj)}(hhh]h)}(hlSet scope of where icache flushing instructions are allowed to be emitted. Supported values described below.h]hlSet scope of where icache flushing instructions are allowed to be emitted. Supported values described below.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhjhKhjubeh}(h]h ]h"]h$]h&]uh1jhjubh)}(h**Description**h]j)}(hj?h]h Description}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1jhj=ubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh)}(hSupported values for ctx:h]hSupported values for ctx:}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh bullet_list)}(hhh](h list_item)}(h<``PR_RISCV_CTX_SW_FENCEI_ON``: Allow fence.i in user space. h]h)}(h;``PR_RISCV_CTX_SW_FENCEI_ON``: Allow fence.i in user space.h](h)}(h``PR_RISCV_CTX_SW_FENCEI_ON``h]hPR_RISCV_CTX_SW_FENCEI_ON}(hjshhhNhNubah}(h]h ]h"]h$]h&]uh1hhjoubh: Allow fence.i in user space.}(hjohhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjkubah}(h]h ]h"]h$]h&]uh1jihjfubjj)}(hX,``PR_RISCV_CTX_SW_FENCEI_OFF``: Disallow fence.i in user space. All threads in a process will be affected when ``scope == PR_RISCV_SCOPE_PER_PROCESS``. Therefore, caution must be taken; use this flag only when you can guarantee that no thread in the process will emit fence.i from this point onward. h]h)}(hX+``PR_RISCV_CTX_SW_FENCEI_OFF``: Disallow fence.i in user space. All threads in a process will be affected when ``scope == PR_RISCV_SCOPE_PER_PROCESS``. Therefore, caution must be taken; use this flag only when you can guarantee that no thread in the process will emit fence.i from this point onward.h](h)}(h``PR_RISCV_CTX_SW_FENCEI_OFF``h]hPR_RISCV_CTX_SW_FENCEI_OFF}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubhQ: Disallow fence.i in user space. All threads in a process will be affected when }(hjhhhNhNubh)}(h'``scope == PR_RISCV_SCOPE_PER_PROCESS``h]h#scope == PR_RISCV_SCOPE_PER_PROCESS}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh. Therefore, caution must be taken; use this flag only when you can guarantee that no thread in the process will emit fence.i from this point onward.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubah}(h]h ]h"]h$]h&]uh1jihjfubeh}(h]h ]h"]h$]h&]bullet*uh1jdhjhKhjubh)}(hSupported values for scope:h]hSupported values for scope:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubje)}(hhh](jj)}(h``PR_RISCV_SCOPE_PER_PROCESS``: Ensure the icache of any thread in this process is coherent with instruction storage upon migration. h]j)}(hhh]j)}(h``PR_RISCV_SCOPE_PER_PROCESS``: Ensure the icache of any thread in this process is coherent with instruction storage upon migration. h](j)}(hO``PR_RISCV_SCOPE_PER_PROCESS``: Ensure the icache of any thread in this processh](h)}(h``PR_RISCV_SCOPE_PER_PROCESS``h]hPR_RISCV_SCOPE_PER_PROCESS}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh1: Ensure the icache of any thread in this process}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubj)}(hhh]h)}(h4is coherent with instruction storage upon migration.h]h4is coherent with instruction storage upon migration.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhj ubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhj hKhjubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jihjubjj)}(h``PR_RISCV_SCOPE_PER_THREAD``: Ensure the icache of the current thread is coherent with instruction storage upon migration. h]j)}(hhh]j)}(h|``PR_RISCV_SCOPE_PER_THREAD``: Ensure the icache of the current thread is coherent with instruction storage upon migration. h](j)}(hI``PR_RISCV_SCOPE_PER_THREAD``: Ensure the icache of the current thread ish](h)}(h``PR_RISCV_SCOPE_PER_THREAD``h]hPR_RISCV_SCOPE_PER_THREAD}(hjFhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjBubh,: Ensure the icache of the current thread is}(hjBhhhNhNubeh}(h]h ]h"]h$]h&]uh1jh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhj>ubj)}(hhh]h)}(h1coherent with instruction storage upon migration.h]h1coherent with instruction storage upon migration.}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhj_ubah}(h]h ]h"]h$]h&]uh1jhj>ubeh}(h]h ]h"]h$]h&]uh1jhj^hKhj;ubah}(h]h ]h"]h$]h&]uh1jhj7ubah}(h]h ]h"]h$]h&]uh1jihjubeh}(h]h ]h"]h$]h&]jjuh1jdh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh)}(hXJWhen ``scope == PR_RISCV_SCOPE_PER_PROCESS``, all threads in the process are permitted to emit icache flushing instructions. Whenever any thread in the process is migrated, the corresponding hart's icache will be guaranteed to be consistent with instruction storage. This does not enforce any guarantees outside of migration. If a thread modifies an instruction that another thread may attempt to execute, the other thread must still emit an icache flushing instruction before attempting to execute the potentially modified instruction. This must be performed by the user-space program.h](hWhen }(hjhhhNhNubh)}(h'``scope == PR_RISCV_SCOPE_PER_PROCESS``h]h#scope == PR_RISCV_SCOPE_PER_PROCESS}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubhX , all threads in the process are permitted to emit icache flushing instructions. Whenever any thread in the process is migrated, the corresponding hart’s icache will be guaranteed to be consistent with instruction storage. This does not enforce any guarantees outside of migration. If a thread modifies an instruction that another thread may attempt to execute, the other thread must still emit an icache flushing instruction before attempting to execute the potentially modified instruction. This must be performed by the user-space program.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh)}(hXIn per-thread context (eg. ``scope == PR_RISCV_SCOPE_PER_THREAD``) only the thread calling this function is permitted to emit icache flushing instructions. When the thread is migrated, the corresponding hart's icache will be guaranteed to be consistent with instruction storage.h](hIn per-thread context (eg. }(hjhhhNhNubh)}(h&``scope == PR_RISCV_SCOPE_PER_THREAD``h]h"scope == PR_RISCV_SCOPE_PER_THREAD}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh) only the thread calling this function is permitted to emit icache flushing instructions. When the thread is migrated, the corresponding hart’s icache will be guaranteed to be consistent with instruction storage.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubh)}(hdOn kernels configured without SMP, this function is a nop as migrations across harts will not occur.h]hdOn kernels configured without SMP, this function is a nop as migrations across harts will not occur.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hh[/var/lib/git/docbuild/linux/Documentation/arch/riscv/cmodx:41: ./arch/riscv/mm/cacheflush.chKhjubeh}(h]h ] kernelindentah"]h$]h&]uh1jhjhhhNhNubh)}(hExample usage:h]hExample usage:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK,hjhhubh)}(hThe following files are meant to be compiled and linked with each other. The modify_instruction() function replaces an add with 0 with an add with one, causing the instruction sequence in get_value() to change from returning a zero to returning a one.h]hThe following files are meant to be compiled and linked with each other. The modify_instruction() function replaces an add with 0 with an add with one, causing the instruction sequence in get_value() to change from returning a zero to returning a one.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK.hjhhubh)}(h cmodx.c::h]hcmodx.c:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhK3hjhhubh literal_block)}(hX#include #include extern int get_value(); extern void modify_instruction(); int main() { int value = get_value(); printf("Value before cmodx: %d\n", value); // Call prctl before first fence.i is called inside modify_instruction prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_ON, PR_RISCV_SCOPE_PER_PROCESS); modify_instruction(); // Call prctl after final fence.i is called in process prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_OFF, PR_RISCV_SCOPE_PER_PROCESS); value = get_value(); printf("Value after cmodx: %d\n", value); return 0; }h]hX#include #include extern int get_value(); extern void modify_instruction(); int main() { int value = get_value(); printf("Value before cmodx: %d\n", value); // Call prctl before first fence.i is called inside modify_instruction prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_ON, PR_RISCV_SCOPE_PER_PROCESS); modify_instruction(); // Call prctl after final fence.i is called in process prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_OFF, PR_RISCV_SCOPE_PER_PROCESS); value = get_value(); printf("Value after cmodx: %d\n", value); return 0; }}hjsbah}(h]h ]h"]h$]h&]hhuh1jhhhK5hjhhubh)}(h cmodx.S::h]hcmodx.S:}(hj"hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKKhjhhubj)}(hX .option norvc .text .global modify_instruction modify_instruction: lw a0, new_insn lui a5,%hi(old_insn) sw a0,%lo(old_insn)(a5) fence.i ret .section modifiable, "awx" .global get_value get_value: li a0, 0 old_insn: addi a0, a0, 0 ret .data new_insn: addi a0, a0, 1h]hX .option norvc .text .global modify_instruction modify_instruction: lw a0, new_insn lui a5,%hi(old_insn) sw a0,%lo(old_insn)(a5) fence.i ret .section modifiable, "awx" .global get_value get_value: li a0, 0 old_insn: addi a0, a0, 0 ret .data new_insn: addi a0, a0, 1}hj0sbah}(h]h ]h"]h$]h&]hhuh1jhhhKMhjhhubeh}(h]prctl-interfaceah ]h"]prctl() interfaceah$]h&]uh1hhhhhhhhK#ubeh}(h]Lconcurrent-modification-and-execution-of-instructions-cmodx-for-risc-v-linuxah ]h"]Nconcurrent modification and execution of instructions (cmodx) for risc-v linuxah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjqerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jKjHjCj@u nametypes}(jKjCuh}(jHhj@jjWj`u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages] transformerN include_log] decorationNhhub.