Skip to main content

islet_rmm/
pmu.rs

1use aarch64_cpu::registers::*;
2use armv9a::regs::pmu::*;
3use armv9a::PMCR_EL0;
4
5pub const MAX_EVCNT: usize = 31;
6
7#[allow(non_upper_case_globals)]
8const FEAT_PMUv3p7: u64 = 7;
9#[cfg(not(feature = "qemu"))]
10const PMU_MIN_VER: u64 = FEAT_PMUv3p7;
11#[cfg(feature = "qemu")]
12const PMU_MIN_VER: u64 = 5; // FEAT_PMUv3p5
13
14// ID_AA64DFR0_EL1
15// HPMN0, bits [63:60] :
16// Zero PMU event counters for a Guest operating system.
17const HPMN0_MASK: u64 = 0xF << 60;
18
19pub fn pmu_present() -> bool {
20    trace!(
21        "PMUVer: v3p{:?}",
22        ID_AA64DFR0_EL1.read(ID_AA64DFR0_EL1::PMUVer)
23    );
24    ID_AA64DFR0_EL1.read(ID_AA64DFR0_EL1::PMUVer) >= PMU_MIN_VER
25}
26
27pub fn hpmn0_present() -> bool {
28    trace!(
29        "FEAT_HPMN0: {:?}",
30        (ID_AA64DFR0_EL1.get() & HPMN0_MASK) >> 60
31    );
32    ID_AA64DFR0_EL1.get() & HPMN0_MASK != 0
33}
34
35pub fn pmu_num_ctrs() -> u64 {
36    trace!("PMU # counters: {:?}", PMCR_EL0.read(PMCR_EL0::N));
37    PMCR_EL0.read(PMCR_EL0::N)
38}
39
40fn store_pmev(n: usize, pmevcntr_el0: &mut [u64; MAX_EVCNT], pmevtyper_el0: &mut [u64; MAX_EVCNT]) {
41    match n {
42        0 => {
43            pmevcntr_el0[0] = PMEVCNTR0_EL0.get();
44            pmevtyper_el0[0] = PMEVTYPER0_EL0.get();
45        }
46        1 => {
47            pmevcntr_el0[1] = PMEVCNTR1_EL0.get();
48            pmevtyper_el0[1] = PMEVTYPER1_EL0.get();
49        }
50        2 => {
51            pmevcntr_el0[2] = PMEVCNTR2_EL0.get();
52            pmevtyper_el0[2] = PMEVTYPER2_EL0.get();
53        }
54        3 => {
55            pmevcntr_el0[3] = PMEVCNTR3_EL0.get();
56            pmevtyper_el0[3] = PMEVTYPER3_EL0.get();
57        }
58        4 => {
59            pmevcntr_el0[4] = PMEVCNTR4_EL0.get();
60            pmevtyper_el0[4] = PMEVTYPER4_EL0.get();
61        }
62        5 => {
63            pmevcntr_el0[5] = PMEVCNTR5_EL0.get();
64            pmevtyper_el0[5] = PMEVTYPER5_EL0.get();
65        }
66        6 => {
67            pmevcntr_el0[6] = PMEVCNTR6_EL0.get();
68            pmevtyper_el0[6] = PMEVTYPER6_EL0.get();
69        }
70        7 => {
71            pmevcntr_el0[7] = PMEVCNTR7_EL0.get();
72            pmevtyper_el0[7] = PMEVTYPER7_EL0.get();
73        }
74        8 => {
75            pmevcntr_el0[8] = PMEVCNTR8_EL0.get();
76            pmevtyper_el0[8] = PMEVTYPER8_EL0.get();
77        }
78        9 => {
79            pmevcntr_el0[9] = PMEVCNTR9_EL0.get();
80            pmevtyper_el0[9] = PMEVTYPER9_EL0.get();
81        }
82        10 => {
83            pmevcntr_el0[10] = PMEVCNTR10_EL0.get();
84            pmevtyper_el0[10] = PMEVTYPER10_EL0.get();
85        }
86        11 => {
87            pmevcntr_el0[11] = PMEVCNTR11_EL0.get();
88            pmevtyper_el0[11] = PMEVTYPER11_EL0.get();
89        }
90        12 => {
91            pmevcntr_el0[12] = PMEVCNTR12_EL0.get();
92            pmevtyper_el0[12] = PMEVTYPER12_EL0.get();
93        }
94        13 => {
95            pmevcntr_el0[13] = PMEVCNTR13_EL0.get();
96            pmevtyper_el0[13] = PMEVTYPER13_EL0.get();
97        }
98        14 => {
99            pmevcntr_el0[14] = PMEVCNTR14_EL0.get();
100            pmevtyper_el0[14] = PMEVTYPER14_EL0.get();
101        }
102        15 => {
103            pmevcntr_el0[15] = PMEVCNTR15_EL0.get();
104            pmevtyper_el0[15] = PMEVTYPER15_EL0.get();
105        }
106        16 => {
107            pmevcntr_el0[16] = PMEVCNTR16_EL0.get();
108            pmevtyper_el0[16] = PMEVTYPER16_EL0.get();
109        }
110        17 => {
111            pmevcntr_el0[17] = PMEVCNTR17_EL0.get();
112            pmevtyper_el0[17] = PMEVTYPER17_EL0.get();
113        }
114        18 => {
115            pmevcntr_el0[18] = PMEVCNTR18_EL0.get();
116            pmevtyper_el0[18] = PMEVTYPER18_EL0.get();
117        }
118        19 => {
119            pmevcntr_el0[19] = PMEVCNTR19_EL0.get();
120            pmevtyper_el0[19] = PMEVTYPER19_EL0.get();
121        }
122        20 => {
123            pmevcntr_el0[20] = PMEVCNTR20_EL0.get();
124            pmevtyper_el0[20] = PMEVTYPER20_EL0.get();
125        }
126        21 => {
127            pmevcntr_el0[21] = PMEVCNTR21_EL0.get();
128            pmevtyper_el0[21] = PMEVTYPER21_EL0.get();
129        }
130        22 => {
131            pmevcntr_el0[22] = PMEVCNTR22_EL0.get();
132            pmevtyper_el0[22] = PMEVTYPER22_EL0.get();
133        }
134        23 => {
135            pmevcntr_el0[23] = PMEVCNTR23_EL0.get();
136            pmevtyper_el0[23] = PMEVTYPER23_EL0.get();
137        }
138        24 => {
139            pmevcntr_el0[24] = PMEVCNTR24_EL0.get();
140            pmevtyper_el0[24] = PMEVTYPER24_EL0.get();
141        }
142        25 => {
143            pmevcntr_el0[25] = PMEVCNTR25_EL0.get();
144            pmevtyper_el0[25] = PMEVTYPER25_EL0.get();
145        }
146        26 => {
147            pmevcntr_el0[26] = PMEVCNTR26_EL0.get();
148            pmevtyper_el0[26] = PMEVTYPER26_EL0.get();
149        }
150        27 => {
151            pmevcntr_el0[27] = PMEVCNTR27_EL0.get();
152            pmevtyper_el0[27] = PMEVTYPER27_EL0.get();
153        }
154        28 => {
155            pmevcntr_el0[28] = PMEVCNTR28_EL0.get();
156            pmevtyper_el0[28] = PMEVTYPER28_EL0.get();
157        }
158        29 => {
159            pmevcntr_el0[29] = PMEVCNTR29_EL0.get();
160            pmevtyper_el0[29] = PMEVTYPER29_EL0.get();
161        }
162        30 => {
163            pmevcntr_el0[30] = PMEVCNTR30_EL0.get();
164            pmevtyper_el0[30] = PMEVTYPER30_EL0.get();
165        }
166        _ => warn!("Invalid PMEV index"),
167    }
168}
169
170fn load_pmev(n: usize, cntr_val: u64, typer_val: u64) {
171    match n {
172        0 => {
173            PMEVCNTR0_EL0.set(cntr_val);
174            PMEVTYPER0_EL0.set(typer_val);
175        }
176        1 => {
177            PMEVCNTR1_EL0.set(cntr_val);
178            PMEVTYPER1_EL0.set(typer_val);
179        }
180        2 => {
181            PMEVCNTR2_EL0.set(cntr_val);
182            PMEVTYPER2_EL0.set(typer_val);
183        }
184        3 => {
185            PMEVCNTR3_EL0.set(cntr_val);
186            PMEVTYPER3_EL0.set(typer_val);
187        }
188        4 => {
189            PMEVCNTR4_EL0.set(cntr_val);
190            PMEVTYPER4_EL0.set(typer_val);
191        }
192        5 => {
193            PMEVCNTR5_EL0.set(cntr_val);
194            PMEVTYPER5_EL0.set(typer_val);
195        }
196        6 => {
197            PMEVCNTR6_EL0.set(cntr_val);
198            PMEVTYPER6_EL0.set(typer_val);
199        }
200        7 => {
201            PMEVCNTR7_EL0.set(cntr_val);
202            PMEVTYPER7_EL0.set(typer_val);
203        }
204        8 => {
205            PMEVCNTR8_EL0.set(cntr_val);
206            PMEVTYPER8_EL0.set(typer_val);
207        }
208        9 => {
209            PMEVCNTR9_EL0.set(cntr_val);
210            PMEVTYPER9_EL0.set(typer_val);
211        }
212        10 => {
213            PMEVCNTR10_EL0.set(cntr_val);
214            PMEVTYPER10_EL0.set(typer_val);
215        }
216        11 => {
217            PMEVCNTR11_EL0.set(cntr_val);
218            PMEVTYPER11_EL0.set(typer_val);
219        }
220        12 => {
221            PMEVCNTR12_EL0.set(cntr_val);
222            PMEVTYPER12_EL0.set(typer_val);
223        }
224        13 => {
225            PMEVCNTR13_EL0.set(cntr_val);
226            PMEVTYPER13_EL0.set(typer_val);
227        }
228        14 => {
229            PMEVCNTR14_EL0.set(cntr_val);
230            PMEVTYPER14_EL0.set(typer_val);
231        }
232        15 => {
233            PMEVCNTR15_EL0.set(cntr_val);
234            PMEVTYPER15_EL0.set(typer_val);
235        }
236        16 => {
237            PMEVCNTR16_EL0.set(cntr_val);
238            PMEVTYPER16_EL0.set(typer_val);
239        }
240        17 => {
241            PMEVCNTR17_EL0.set(cntr_val);
242            PMEVTYPER17_EL0.set(typer_val);
243        }
244        18 => {
245            PMEVCNTR18_EL0.set(cntr_val);
246            PMEVTYPER18_EL0.set(typer_val);
247        }
248        19 => {
249            PMEVCNTR19_EL0.set(cntr_val);
250            PMEVTYPER19_EL0.set(typer_val);
251        }
252        20 => {
253            PMEVCNTR20_EL0.set(cntr_val);
254            PMEVTYPER20_EL0.set(typer_val);
255        }
256        21 => {
257            PMEVCNTR21_EL0.set(cntr_val);
258            PMEVTYPER21_EL0.set(typer_val);
259        }
260        22 => {
261            PMEVCNTR22_EL0.set(cntr_val);
262            PMEVTYPER22_EL0.set(typer_val);
263        }
264        23 => {
265            PMEVCNTR23_EL0.set(cntr_val);
266            PMEVTYPER23_EL0.set(typer_val);
267        }
268        24 => {
269            PMEVCNTR24_EL0.set(cntr_val);
270            PMEVTYPER24_EL0.set(typer_val);
271        }
272        25 => {
273            PMEVCNTR25_EL0.set(cntr_val);
274            PMEVTYPER25_EL0.set(typer_val);
275        }
276        26 => {
277            PMEVCNTR26_EL0.set(cntr_val);
278            PMEVTYPER26_EL0.set(typer_val);
279        }
280        27 => {
281            PMEVCNTR27_EL0.set(cntr_val);
282            PMEVTYPER27_EL0.set(typer_val);
283        }
284        28 => {
285            PMEVCNTR28_EL0.set(cntr_val);
286            PMEVTYPER28_EL0.set(typer_val);
287        }
288        29 => {
289            PMEVCNTR29_EL0.set(cntr_val);
290            PMEVTYPER29_EL0.set(typer_val);
291        }
292        30 => {
293            PMEVCNTR30_EL0.set(cntr_val);
294            PMEVTYPER30_EL0.set(typer_val);
295        }
296        _ => warn!("Invalid PMEV index"),
297    }
298}
299
300pub fn set_pmev_regs(
301    cnt: usize,
302    pmevcntr_el0: &[u64; MAX_EVCNT],
303    pmevtyper_el0: &[u64; MAX_EVCNT],
304) {
305    if cnt > MAX_EVCNT {
306        error!("Index out of bounds");
307        return;
308    }
309    for i in 0..cnt {
310        load_pmev(i, pmevcntr_el0[i], pmevtyper_el0[i]);
311    }
312}
313
314pub fn get_pmev_regs(
315    cnt: usize,
316    pmevcntr_el0: &mut [u64; MAX_EVCNT],
317    pmevtyper_el0: &mut [u64; MAX_EVCNT],
318) {
319    if cnt > MAX_EVCNT {
320        error!("Index out of bounds");
321        return;
322    }
323    for i in 0..cnt {
324        store_pmev(i, pmevcntr_el0, pmevtyper_el0);
325    }
326}