vm_topology/processor/
aarch64.rs1use super::ArchTopology;
7use super::InvalidTopology;
8use super::ProcessorTopology;
9use super::TopologyBuilder;
10use super::VpIndex;
11use super::VpInfo;
12use super::VpTopologyInfo;
13use aarch64defs::MpidrEl1;
14
15#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
17#[derive(Debug, Copy, Clone)]
18#[non_exhaustive]
19pub struct Aarch64Topology {
20 gic: GicInfo,
21 #[cfg_attr(feature = "inspect", inspect(hex))]
23 pmu_gsiv: u32,
24}
25
26impl ArchTopology for Aarch64Topology {
27 type ArchVpInfo = Aarch64VpInfo;
28 type BuilderState = Aarch64TopologyBuilderState;
29
30 fn vp_topology(_topology: &ProcessorTopology<Self>, info: &Self::ArchVpInfo) -> VpTopologyInfo {
31 VpTopologyInfo {
32 socket: info.mpidr.aff2().into(),
33 core: info.mpidr.aff1().into(),
34 thread: info.mpidr.aff0().into(),
35 }
36 }
37}
38
39pub struct Aarch64TopologyBuilderState {
41 gic: GicInfo,
42 pmu_gsiv: u32,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
48pub struct GicInfo {
49 #[cfg_attr(feature = "inspect", inspect(hex))]
51 pub gic_distributor_base: u64,
52 #[cfg_attr(feature = "inspect", inspect(hex))]
54 pub gic_redistributors_base: u64,
55}
56
57#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
59#[derive(Debug, Copy, Clone)]
60pub struct Aarch64VpInfo {
61 #[cfg_attr(feature = "inspect", inspect(flatten))]
63 pub base: VpInfo,
64 #[cfg_attr(feature = "inspect", inspect(hex, with = "|&x| u64::from(x)"))]
66 pub mpidr: MpidrEl1,
67 #[cfg_attr(feature = "inspect", inspect(hex))]
69 pub gicr: u64,
70 #[cfg_attr(feature = "inspect", inspect(hex))]
72 pub pmu_gsiv: u32,
73}
74
75impl AsRef<VpInfo> for Aarch64VpInfo {
76 fn as_ref(&self) -> &VpInfo {
77 &self.base
78 }
79}
80
81impl TopologyBuilder<Aarch64Topology> {
82 pub fn new_aarch64(gic: GicInfo, pmu_gsiv: u32) -> Self {
84 Self {
85 vps_per_socket: 1,
86 smt_enabled: false,
87 arch: Aarch64TopologyBuilderState { gic, pmu_gsiv },
88 }
89 }
90
91 pub fn build(
93 &self,
94 proc_count: u32,
95 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
96 if proc_count >= 256 {
97 return Err(InvalidTopology::TooManyVps {
98 requested: proc_count,
99 max: u8::MAX.into(),
100 });
101 }
102 let mpidrs = (0..proc_count).map(|vp_index| {
103 let uni_proc = proc_count == 1;
106 let mut aff = (0..4).map(|i| (vp_index >> (8 * i)) as u8);
107 MpidrEl1::new()
108 .with_res1_31(true)
109 .with_u(uni_proc)
110 .with_aff0(aff.next().unwrap())
111 .with_aff1(aff.next().unwrap())
112 .with_aff2(aff.next().unwrap())
113 .with_aff3(aff.next().unwrap())
114 });
115 self.build_with_vp_info(mpidrs.enumerate().map(|(id, mpidr)| Aarch64VpInfo {
116 base: VpInfo {
117 vp_index: VpIndex::new(id as u32),
118 vnode: 0,
119 },
120 mpidr,
121 gicr: self.arch.gic.gic_redistributors_base
122 + id as u64 * aarch64defs::GIC_REDISTRIBUTOR_SIZE,
123 pmu_gsiv: self.arch.pmu_gsiv,
124 }))
125 }
126
127 pub fn build_with_vp_info(
129 &self,
130 vps: impl IntoIterator<Item = Aarch64VpInfo>,
131 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
132 let vps = Vec::from_iter(vps);
133 let mut smt_enabled = false;
134 for (i, vp) in vps.iter().enumerate() {
135 if i != vp.base.vp_index.index() as usize {
136 return Err(InvalidTopology::InvalidVpIndices);
137 }
138
139 if vp.mpidr.mt() {
140 smt_enabled = true;
141 }
142 }
143
144 Ok(ProcessorTopology {
145 vps,
146 smt_enabled,
147 vps_per_socket: self.vps_per_socket,
148 arch: Aarch64Topology {
149 gic: self.arch.gic,
150 pmu_gsiv: self.arch.pmu_gsiv,
151 },
152 })
153 }
154}
155
156impl ProcessorTopology<Aarch64Topology> {
157 pub fn gic_distributor_base(&self) -> u64 {
159 self.arch.gic.gic_distributor_base
160 }
161
162 pub fn gic_redistributors_base(&self) -> u64 {
164 self.arch.gic.gic_redistributors_base
165 }
166
167 pub fn pmu_gsiv(&self) -> u32 {
169 self.arch.pmu_gsiv
170 }
171}