Skip to main content

ax_cpu/arch/aarch64/
cache.rs

1//! Local cache operations.
2
3pub use super::asm::{dcache_line_size_from_ctr, flush_icache_all, icache_line_size_from_ctr};
4
5/// Data-cache maintenance performed to the point of coherency.
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum DataCacheOperation {
8    /// Writes dirty data back while retaining valid cache lines.
9    Clean,
10    /// Discards cached contents without writing them back.
11    Invalidate,
12    /// Writes dirty contents back and discards the cache lines.
13    CleanInvalidate,
14}
15
16/// Maintains every cache line intersecting a checked virtual byte range.
17/// Completion includes a system DSB and instruction synchronization.
18///
19/// # Safety
20/// Every intersected cache line must be mapped and owned for the operation.
21/// Invalidation must not discard live dirty data or race CPU/device accesses.
22/// The caller owns DMA transfer direction, aliases and platform coherency.
23pub unsafe fn maintain_dcache_to_poc(
24    operation: DataCacheOperation,
25    range: crate::cache::CacheRange,
26) {
27    if range.is_empty() {
28        return;
29    }
30    range.for_each_line(dcache_line_size_from_ctr(), |line| {
31        // SAFETY: the caller retains every complete intersected line and the
32        // checked range iterator cannot wrap into an unrelated address region.
33        unsafe {
34            match operation {
35                DataCacheOperation::Clean => core::arch::asm!("dc cvac, {}", in(reg) line),
36                DataCacheOperation::Invalidate => core::arch::asm!("dc ivac, {}", in(reg) line),
37                DataCacheOperation::CleanInvalidate => {
38                    core::arch::asm!("dc civac, {}", in(reg) line)
39                }
40            }
41        }
42    });
43    // SAFETY: complete the cache operations before returning ownership.
44    unsafe { core::arch::asm!("dsb sy; isb", options(nostack)) };
45}
46
47/// Cleans the checked range to the point of unification and completes the writes.
48/// Call `flush_icache_all` before executing the modified instructions.
49///
50/// # Safety
51/// Every intersected cache line must remain mapped and accessible until completion.
52/// The caller must coordinate concurrent modifications and instruction execution.
53pub unsafe fn clean_dcache_range_to_pou(range: crate::cache::CacheRange) {
54    if range.is_empty() {
55        return;
56    }
57    range.for_each_line(dcache_line_size_from_ctr(), |line| {
58        // SAFETY: the caller retains the mapped lines; the checked iterator
59        // visits the final line without rounding the endpoint past usize::MAX.
60        unsafe { core::arch::asm!("dc cvau, {}", in(reg) line, options(nostack)) };
61    });
62    // SAFETY: complete the data-side publication before instruction invalidation.
63    unsafe { core::arch::asm!("dsb ish", options(nostack)) };
64}