use core::sync::atomic::{AtomicUsize, Ordering};
static DCACHE_LINE_SIZE: AtomicUsize = AtomicUsize::new(64);
static ICACHE_LINE_SIZE: AtomicUsize = AtomicUsize::new(64);
#[inline(always)]
pub(super) fn arch_cache_init() {
let ctr: usize;
unsafe { core::arch::asm!("mrs {}, ctr_el0", out(reg) ctr) };
DCACHE_LINE_SIZE.store(4 << ((ctr >> 16) & 0xf), Ordering::Relaxed);
ICACHE_LINE_SIZE.store(4 << (ctr & 0xf), Ordering::Relaxed);
}
#[inline(always)]
pub(super) fn arch_dcache_line_size() -> usize {
DCACHE_LINE_SIZE.load(Ordering::Relaxed)
}
#[inline(always)]
fn icache_line_size() -> usize {
ICACHE_LINE_SIZE.load(Ordering::Relaxed)
}
pub(super) fn arch_clean_dcache_area(addr: usize, size: usize) {
let line = arch_dcache_line_size();
let end = addr + size;
let mut cur = addr & !(line - 1);
while cur < end {
unsafe { core::arch::asm!("dc cvac, {}", in(reg) cur) };
cur += line;
}
unsafe { core::arch::aarch64::__dsb(core::arch::aarch64::SY) };
}
pub(super) fn arch_inval_dcache_area(addr: usize, size: usize) {
let line = arch_dcache_line_size();
let mask = line - 1;
let end = addr + size;
let end_aligned = end & !mask;
if end & mask != 0 {
unsafe { core::arch::asm!("dc civac, {}", in(reg) end_aligned) };
}
let mut cur = addr & !mask;
if addr & mask != 0 {
unsafe { core::arch::asm!("dc civac, {}", in(reg) cur) };
cur += line;
}
while cur < end_aligned {
unsafe { core::arch::asm!("dc ivac, {}", in(reg) cur) };
cur += line;
}
unsafe { core::arch::aarch64::__dsb(core::arch::aarch64::SY) };
}
pub(super) fn arch_flush_dcache_area(addr: usize, size: usize) {
let line = arch_dcache_line_size();
let end = addr + size;
let mut cur = addr & !(line - 1);
while cur < end {
unsafe { core::arch::asm!("dc civac, {}", in(reg) cur) };
cur += line;
}
unsafe { core::arch::aarch64::__dsb(core::arch::aarch64::SY) };
}
#[inline(always)]
pub(super) fn arch_flush_icache_all() {
unsafe {
core::arch::asm!("ic iallu");
core::arch::aarch64::__dsb(core::arch::aarch64::NSH);
core::arch::aarch64::__isb(core::arch::aarch64::SY);
}
}
pub(super) fn arch_flush_icache_range(start: usize, end: usize) {
let dline = arch_dcache_line_size();
let mut cur = start & !(dline - 1);
while cur < end {
unsafe { core::arch::asm!("dc cvau, {}", in(reg) cur) };
cur += dline;
}
unsafe { core::arch::aarch64::__dsb(core::arch::aarch64::ISH) };
let iline = icache_line_size();
cur = start & !(iline - 1);
while cur < end {
unsafe { core::arch::asm!("ic ivau, {}", in(reg) cur) };
cur += iline;
}
unsafe {
core::arch::aarch64::__dsb(core::arch::aarch64::ISH);
core::arch::aarch64::__isb(core::arch::aarch64::SY);
}
}