#[allow(dead_code)]
const CACHE_LINE: usize = 64;
#[cfg(all(
target_arch = "riscv64",
target_feature = "zicbom",
feature = "c906"
))]
compile_error!(
"feature `c906` 与 RISC-V `zicbom` 标准缓存指令冲突,请二选一(C906 仅支持自定义编码)。"
);
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
#[inline(always)]
unsafe fn dcache_cva(va: usize) {
unsafe {
core::arch::asm!(".insn i 0x0b, 0, x0, {0}, 0x025", in(reg) va);
}
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
#[inline(always)]
unsafe fn dcache_iva(va: usize) {
unsafe {
core::arch::asm!(".insn i 0x0b, 0, x0, {0}, 0x026", in(reg) va);
}
}
#[cfg(not(all(target_arch = "riscv64", feature = "c906")))]
#[inline(always)]
#[allow(dead_code)]
unsafe fn dcache_cva(_va: usize) {}
#[cfg(not(all(target_arch = "riscv64", feature = "c906")))]
#[inline(always)]
#[allow(dead_code)]
unsafe fn dcache_iva(_va: usize) {}
#[inline]
pub fn dcache_clean_range(start: usize, size: usize) {
if size == 0 {
return;
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
{
let mut addr = start & !(CACHE_LINE - 1);
let end = start + size;
while addr < end {
unsafe { dcache_cva(addr) };
addr += CACHE_LINE;
}
unsafe { core::arch::asm!("fence iorw, iorw") };
}
#[cfg(all(target_arch = "riscv64", not(feature = "c906")))]
{
let _ = (start, size);
unsafe { core::arch::asm!("fence iorw, iorw") };
}
#[cfg(not(target_arch = "riscv64"))]
{
let _ = (start, size);
}
}
#[inline]
pub fn dcache_invalidate_range(start: usize, size: usize) {
if size == 0 {
return;
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
{
let mut addr = start & !(CACHE_LINE - 1);
let end = start + size;
while addr < end {
unsafe { dcache_iva(addr) };
addr += CACHE_LINE;
}
unsafe { core::arch::asm!("fence iorw, iorw") };
}
#[cfg(all(target_arch = "riscv64", not(feature = "c906")))]
{
let _ = (start, size);
unsafe { core::arch::asm!("fence iorw, iorw") };
}
#[cfg(not(target_arch = "riscv64"))]
{
let _ = (start, size);
}
}
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
enum DcacheOp {
Clean,
Invalidate,
}
#[cfg(target_arch = "aarch64")]
unsafe fn dcache_op_range(mut addr: usize, end: usize, op: DcacheOp) {
addr &= !(CACHE_LINE - 1);
while addr < end {
let a = addr as u64;
unsafe {
match op {
DcacheOp::Clean => core::arch::asm!("dc cvac, {}", in(reg) a, options(nostack)),
DcacheOp::Invalidate => core::arch::asm!("dc ivac, {}", in(reg) a, options(nostack)),
}
}
addr = addr.saturating_add(CACHE_LINE);
}
unsafe {
core::arch::asm!("dsb sy", options(nostack));
}
}
#[cfg(target_arch = "aarch64")]
pub unsafe fn dcache_clean_for_dma(ptr: *const u8, len: usize) {
if len == 0 {
return;
}
unsafe { dcache_op_range(ptr as usize, ptr as usize + len, DcacheOp::Clean) }
}
#[cfg(target_arch = "aarch64")]
pub unsafe fn dcache_invalidate_after_dma(ptr: *mut u8, len: usize) {
if len == 0 {
return;
}
unsafe { dcache_op_range(ptr as usize, ptr as usize + len, DcacheOp::Invalidate) }
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
#[inline(always)]
unsafe fn riscv64_c906_dcache_ciall() {
unsafe {
core::arch::asm!(
".long 0x0030000b",
"fence rw, rw",
options(nostack),
);
}
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
pub unsafe fn dcache_clean_for_dma(_ptr: *const u8, _len: usize) {
let _ = (_ptr, _len);
unsafe { riscv64_c906_dcache_ciall() }
}
#[cfg(all(target_arch = "riscv64", feature = "c906"))]
pub unsafe fn dcache_invalidate_after_dma(_ptr: *mut u8, _len: usize) {
let _ = (_ptr, _len);
unsafe { riscv64_c906_dcache_ciall() }
}
#[cfg(all(target_arch = "riscv64", not(feature = "c906")))]
pub unsafe fn dcache_clean_for_dma(_ptr: *const u8, _len: usize) {
unsafe { core::arch::asm!("fence rw, rw", options(nostack)) }
}
#[cfg(all(target_arch = "riscv64", not(feature = "c906")))]
pub unsafe fn dcache_invalidate_after_dma(_ptr: *mut u8, _len: usize) {
unsafe { core::arch::asm!("fence rw, rw", options(nostack)) }
}
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
pub unsafe fn dcache_clean_for_dma(_ptr: *const u8, _len: usize) {}
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
pub unsafe fn dcache_invalidate_after_dma(_ptr: *mut u8, _len: usize) {}