Expand description

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.

Functions