aarch32_cpu/cache.rs
1use arbitrary_int::u3;
2
3use crate::register::{Dccimvac, Dccisw, Dccmvac, Dccsw, Dcimvac, Dcisw, SysRegWrite};
4
5/// Invalidate the full L1 data cache.
6///
7/// ## Generics
8///
9/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way
10/// associative cache will have a value of 2 and a 8-way associative cache will have a value of
11/// 3.
12/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of
13/// 5.
14/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be
15/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`.
16/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will
17/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8.
18#[inline]
19pub fn invalidate_l1_data_cache<const A: usize, const N: usize, const S: usize>() {
20 let ways = 1 << A;
21 let sets = 1 << S;
22
23 for set in 0..sets {
24 for way in 0..ways {
25 unsafe { Dcisw::write(Dcisw::new::<A, N>(way, set, u3::new(0))) };
26 }
27 }
28}
29
30/// Clean the full L1 data cache.
31///
32/// ## Generics
33///
34/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way
35/// associative cache will have a value of 2 and a 8-way associative cache will have a value of
36/// 3.
37/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of
38/// 5.
39/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be
40/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`.
41/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will
42/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8.
43#[inline]
44pub fn clean_l1_data_cache<const A: usize, const N: usize, const S: usize>() {
45 let ways = 1 << A;
46 let sets = 1 << S;
47
48 for set in 0..sets {
49 for way in 0..ways {
50 unsafe { Dccsw::write(Dccsw::new::<A, N>(way, set, u3::new(0))) };
51 }
52 }
53}
54
55/// Clean and Invalidate the full L1 data cache.
56///
57/// ## Generics
58///
59/// - A: log2(ASSOCIATIVITY) rounded up to the next integer if necessary. For example, a 4-way
60/// associative cache will have a value of 2 and a 8-way associative cache will have a value of
61/// 3.
62/// - N: log2(LINE LENGTH). For example, a 32-byte line length (4 words) will have a value of
63/// 5.
64/// - S: log2(NUM OF SETS). For systems with a fixed cache size, the number of sets can be
65/// calculated using `CACHE SIZE / (LINE LENGTH * ASSOCIATIVITY)`.
66/// For example, a 4-way associative 32kB L1 cache with a 32-byte line length (4 words) will
67/// have 32768 / (32 * 4) == 256 sets and S will have a value of 8.
68#[inline]
69pub fn clean_and_invalidate_l1_data_cache<const A: usize, const N: usize, const S: usize>() {
70 let ways = 1 << A;
71 let sets = 1 << S;
72
73 for set in 0..sets {
74 for way in 0..ways {
75 unsafe { Dccisw::write(Dccisw::new::<A, N>(way, set, u3::new(0))) };
76 }
77 }
78}
79
80/// Invalidates a data cache line to the point of coherence.
81///
82/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information.
83#[inline]
84pub fn invalidate_data_cache_line_to_poc(addr: u32) {
85 unsafe {
86 Dcimvac::write_raw(addr);
87 }
88}
89
90/// Cleans a data cache line to the point of coherence.
91///
92/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information.
93#[inline]
94pub fn clean_data_cache_line_to_poc(addr: u32) {
95 unsafe {
96 Dccmvac::write_raw(addr);
97 }
98}
99
100/// Cleans and invalidates a data cache line to the point of coherence.
101///
102/// See p.1735 of the ARMv7-A Architecture Reference Manual for more information.
103#[inline]
104pub fn clean_and_invalidate_data_cache_line_to_poc(addr: u32) {
105 unsafe {
106 Dccimvac::write_raw(addr);
107 }
108}