ax_cpu/arch/aarch64/pmu/capability.rs
1//! Per-CPU PMUv3 capabilities, following Linux arm_pmuv3.c probe semantics.
2
3/// Architectural evidence for an event encoding.
4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5pub enum EventSupport {
6 /// The architecture reports the event as implemented.
7 Supported,
8 /// The architecture reports the event as absent.
9 Unsupported,
10 /// The encoding is outside the architectural identification bitmaps.
11 ImplementationDefined,
12}
13
14/// Immutable capabilities observed on one CPU.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct PmuInfo {
17 /// ID_AA64DFR0_EL1.PMUVer encoding.
18 pub version: u8,
19 /// Number of programmable counters, excluding fixed cycle/instruction counters.
20 pub num_counters: usize,
21 /// ID_AA64DFR1_EL1.PMICNTR reports a dedicated instruction counter.
22 /// This is independent of the PMUVer encoding.
23 pub has_instruction_counter: bool,
24 /// Currently configured programmable-counter overflow width.
25 pub counter_width: u8,
26 /// Currently configured cycle-counter overflow width.
27 pub cycle_counter_width: u8,
28 /// Full PMCEID0, including the extended common-event bits.
29 pub pmceid0: u64,
30 /// Full PMCEID1, including the extended common-event bits.
31 pub pmceid1: u64,
32}
33
34impl PmuInfo {
35 /// Reports PMUv3p5 long programmable-counter support.
36 pub const fn has_long_counters(self) -> bool {
37 self.version >= 6
38 }
39
40 /// Queries the common and extended common-event identification bitmaps.
41 pub const fn event_support(self, event: u16) -> EventSupport {
42 let (bitmap, bit) = match event {
43 0x0000..=0x001f => (self.pmceid0, event),
44 0x0020..=0x003f => (self.pmceid1, event - 0x20),
45 0x4000..=0x401f => (self.pmceid0, event - 0x4000 + 32),
46 0x4020..=0x403f => (self.pmceid1, event - 0x4020 + 32),
47 _ => return EventSupport::ImplementationDefined,
48 };
49 if bitmap & (1u64 << bit) != 0 {
50 EventSupport::Supported
51 } else {
52 EventSupport::Unsupported
53 }
54 }
55}