mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
hexagon: Implement __clear_cache using inline assembly
Implement `__clear_cache` for Hexagon targets in Rust. Hexagon has separate instruction and data caches, so this flushes dirty data cache lines with `dccleaninva`, invalidates stale instruction cache lines with `icinva`, then issues an `isync` barrier. Based on the compiler-rt implementation from llvm/llvm-project#188411.
This commit is contained in:
@@ -1,5 +1,49 @@
|
||||
use core::arch::global_asm;
|
||||
|
||||
// Hexagon L1 cache line size in bytes (Hexagon PRM sections 5.10.3-5.10.4).
|
||||
const CACHE_LINE_SIZE: usize = 32;
|
||||
|
||||
intrinsics! {
|
||||
pub unsafe extern "C" fn __clear_cache(start: *mut u8, end: *mut u8) {
|
||||
// Hexagon has separate instruction and data caches.
|
||||
let mask = !(CACHE_LINE_SIZE - 1);
|
||||
let start_line = start.addr() & mask;
|
||||
let end_addr = end.addr();
|
||||
|
||||
// Clean and invalidate data cache to push new code to memory and
|
||||
// invalidate stale lines in the L2 cache.
|
||||
let mut addr = start_line;
|
||||
while addr < end_addr {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"dccleaninva({addr})",
|
||||
addr = in(reg) addr,
|
||||
options(nostack, preserves_flags),
|
||||
);
|
||||
}
|
||||
addr += CACHE_LINE_SIZE;
|
||||
}
|
||||
|
||||
// Invalidate instruction cache so it re-fetches from memory.
|
||||
addr = start_line;
|
||||
while addr < end_addr {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"icinva({addr})",
|
||||
addr = in(reg) addr,
|
||||
options(nostack, preserves_flags),
|
||||
);
|
||||
}
|
||||
addr += CACHE_LINE_SIZE;
|
||||
}
|
||||
|
||||
// Instruction sync barrier ensures subsequent fetches see the new code.
|
||||
unsafe {
|
||||
core::arch::asm!("isync", options(nostack, preserves_flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global_asm!(include_str!("hexagon/func_macro.s"), options(raw));
|
||||
|
||||
global_asm!(
|
||||
|
||||
Reference in New Issue
Block a user