1pub use crate::arch::current::cache::*;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8struct ByteRange {
9 start: usize,
10 last: Option<usize>,
11}
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
15pub struct CacheRangeOverflow;
16
17impl core::fmt::Display for CacheRangeOverflow {
18 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19 f.write_str("cache range wraps the address space")
20 }
21}
22impl core::error::Error for CacheRangeOverflow {}
23
24impl ByteRange {
25 const fn new(start: usize, bytes: usize) -> Result<Self, CacheRangeOverflow> {
27 let last = if bytes == 0 {
28 None
29 } else {
30 match start.checked_add(bytes - 1) {
31 Some(last) => Some(last),
32 None => return Err(CacheRangeOverflow),
33 }
34 };
35 Ok(Self { start, last })
36 }
37
38 #[cfg(any(
39 target_arch = "aarch64",
40 target_arch = "loongarch64",
41 all(target_arch = "riscv64", feature = "riscv-thead-mae")
42 ))]
43 pub(crate) fn for_each_line(self, line_size: usize, mut operation: impl FnMut(usize)) {
44 let Some(last) = self.last else { return };
45 let mask = line_size - 1;
46 let last_line = last & !mask;
47 let mut line = self.start & !mask;
48 loop {
49 operation(line);
50 if line == last_line {
51 break;
52 }
53 line += line_size;
54 }
55 }
56}
57
58#[derive(Clone, Copy, Debug, Eq, PartialEq)]
60pub struct CacheRange(ByteRange);
61impl CacheRange {
62 pub const fn new(start: crate::VirtAddr, bytes: usize) -> Result<Self, CacheRangeOverflow> {
64 match ByteRange::new(start.as_usize(), bytes) {
65 Ok(range) => Ok(Self(range)),
66 Err(error) => Err(error),
67 }
68 }
69 pub const fn start(self) -> crate::VirtAddr {
71 crate::VirtAddr::from_usize(self.0.start)
72 }
73 pub const fn is_empty(self) -> bool {
75 self.0.last.is_none()
76 }
77 #[cfg(any(target_arch = "aarch64", target_arch = "loongarch64"))]
78 pub(crate) fn for_each_line(self, size: usize, operation: impl FnMut(usize)) {
79 self.0.for_each_line(size, operation);
80 }
81}
82
83#[cfg(all(target_arch = "riscv64", feature = "riscv-thead-mae"))]
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
86pub struct PhysicalCacheRange(ByteRange);
87#[cfg(all(target_arch = "riscv64", feature = "riscv-thead-mae"))]
88impl PhysicalCacheRange {
89 pub const fn new(start: crate::PhysAddr, bytes: usize) -> Result<Self, CacheRangeOverflow> {
91 match ByteRange::new(start.as_usize(), bytes) {
92 Ok(range) => Ok(Self(range)),
93 Err(error) => Err(error),
94 }
95 }
96 pub const fn start(self) -> crate::PhysAddr {
98 crate::PhysAddr::from_usize(self.0.start)
99 }
100 pub const fn is_empty(self) -> bool {
102 self.0.last.is_none()
103 }
104 pub(crate) fn for_each_line(self, size: usize, operation: impl FnMut(usize)) {
105 self.0.for_each_line(size, operation);
106 }
107}
108
109pub fn sync_kernel_text(start: crate::VirtAddr, size: usize) {
113 crate::mmu::flush_tlb_range(start, size);
114 flush_icache_all();
115}