71 stable releases (24 major)

new 27.0.0 Nov 20, 2024
26.0.1 Nov 5, 2024
26.0.0 Oct 22, 2024
25.0.3 Nov 5, 2024
2.0.0 Nov 21, 2022

#525 in WebAssembly

Download history 82144/week @ 2024-07-31 95483/week @ 2024-08-07 93486/week @ 2024-08-14 86843/week @ 2024-08-21 96593/week @ 2024-08-28 99860/week @ 2024-09-04 96358/week @ 2024-09-11 98948/week @ 2024-09-18 98566/week @ 2024-09-25 101465/week @ 2024-10-02 100077/week @ 2024-10-09 106188/week @ 2024-10-16 110664/week @ 2024-10-23 108083/week @ 2024-10-30 108360/week @ 2024-11-06 96180/week @ 2024-11-13

443,911 downloads per month
Used in 541 crates (7 directly)

Apache-2.0 WITH LLVM-exception

17KB
152 lines

This crate provides utilities for instruction cache maintenance for JIT authors.

In self modifying codes such as when writing a JIT, special care must be taken when marking the code as ready for execution. On fully coherent architectures (X86, S390X) the data cache (D-Cache) and the instruction cache (I-Cache) are always in sync. However this is not guaranteed for all architectures such as AArch64 where these caches are not coherent with each other.

When writing new code there may be a I-cache entry for that same address which causes the processor to execute whatever was in the cache instead of the new code.

See the ARM Community - Caches and Self-Modifying Code blog post that contains a great explanation of the above. (It references AArch32 but it has a high level overview of this problem).

Usage

You should call [clear_cache] on any pages that you write with the new code that you're intending to execute. You can do this at any point in the code from the moment that you write the page up to the moment where the code is executed.

You also need to call [pipeline_flush_mt] to ensure that there isn't any invalid instruction currently in the pipeline if you are running in a multi threaded environment.

For single threaded programs you are free to omit [pipeline_flush_mt], otherwise you need to call both [clear_cache] and [pipeline_flush_mt] in that order.

Example:

#
#
#
// Invalidate the cache for all the newly written pages where we wrote our new code.
for page in newly_written_pages {
    clear_cache(page.addr, page.len)?;
}

// Once those are invalidated we also need to flush the pipeline
pipeline_flush_mt()?;

// We can now safely execute our new code.
run_code();

Warning: In order to correctly use this interface you should always call [clear_cache]. A followup call to [pipeline_flush_mt] is required if you are running in a multi-threaded environment.

Dependencies

~0.1–8MB
~62K SLoC