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; const 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}