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}