Skip to main content

aarch32_cpu/
cache.rs

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