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 platform: Aarch64PlatformConfig,
21}
22
23impl ArchTopology for Aarch64Topology {
24 type ArchVpInfo = Aarch64VpInfo;
25 type BuilderState = Aarch64TopologyBuilderState;
26
27 fn vp_topology(_topology: &ProcessorTopology<Self>, info: &Self::ArchVpInfo) -> VpTopologyInfo {
28 VpTopologyInfo {
29 socket: info.mpidr.aff2().into(),
30 core: info.mpidr.aff1().into(),
31 thread: info.mpidr.aff0().into(),
32 }
33 }
34}
35
36pub struct Aarch64TopologyBuilderState {
38 platform: Aarch64PlatformConfig,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
48pub struct Aarch64PlatformConfig {
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 pub gic_v2m: Option<GicV2mInfo>,
57 pub pmu_gsiv: Option<u32>,
59 pub virt_timer_ppi: u32,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
66pub struct GicV2mInfo {
67 #[cfg_attr(feature = "inspect", inspect(hex))]
69 pub frame_base: u64,
70 pub spi_base: u32,
72 pub spi_count: u32,
74}
75
76#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
78#[derive(Debug, Copy, Clone)]
79pub struct Aarch64VpInfo {
80 #[cfg_attr(feature = "inspect", inspect(flatten))]
82 pub base: VpInfo,
83 #[cfg_attr(feature = "inspect", inspect(hex, with = "|&x| u64::from(x)"))]
85 pub mpidr: MpidrEl1,
86 #[cfg_attr(feature = "inspect", inspect(hex))]
88 pub gicr: u64,
89 #[cfg_attr(feature = "inspect", inspect(hex))]
91 pub pmu_gsiv: Option<u32>,
92}
93
94impl AsRef<VpInfo> for Aarch64VpInfo {
95 fn as_ref(&self) -> &VpInfo {
96 &self.base
97 }
98}
99
100impl TopologyBuilder<Aarch64Topology> {
101 pub fn new_aarch64(platform: Aarch64PlatformConfig) -> Self {
103 Self {
104 vps_per_socket: 1,
105 smt_enabled: false,
106 arch: Aarch64TopologyBuilderState { platform },
107 }
108 }
109
110 pub fn build(
112 &self,
113 proc_count: u32,
114 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
115 if proc_count >= 256 {
116 return Err(InvalidTopology::TooManyVps {
117 requested: proc_count,
118 max: u8::MAX.into(),
119 });
120 }
121 if !(16..32).contains(&self.arch.platform.virt_timer_ppi) {
122 return Err(InvalidTopology::InvalidPpiIntid(
123 self.arch.platform.virt_timer_ppi,
124 ));
125 }
126 if let Some(gsiv) = self.arch.platform.pmu_gsiv {
127 if !(16..32).contains(&gsiv) {
128 return Err(InvalidTopology::InvalidPpiIntid(gsiv));
129 }
130 }
131 let mpidrs = (0..proc_count).map(|vp_index| {
132 let uni_proc = proc_count == 1;
135 let mut aff = (0..4).map(|i| (vp_index >> (8 * i)) as u8);
136 MpidrEl1::new()
137 .with_res1_31(true)
138 .with_u(uni_proc)
139 .with_aff0(aff.next().unwrap())
140 .with_aff1(aff.next().unwrap())
141 .with_aff2(aff.next().unwrap())
142 .with_aff3(aff.next().unwrap())
143 });
144 self.build_with_vp_info(mpidrs.enumerate().map(|(id, mpidr)| Aarch64VpInfo {
145 base: VpInfo {
146 vp_index: VpIndex::new(id as u32),
147 vnode: 0,
148 },
149 mpidr,
150 gicr: self.arch.platform.gic_redistributors_base
151 + id as u64 * aarch64defs::GIC_REDISTRIBUTOR_SIZE,
152 pmu_gsiv: self.arch.platform.pmu_gsiv,
153 }))
154 }
155
156 pub fn build_with_vp_info(
158 &self,
159 vps: impl IntoIterator<Item = Aarch64VpInfo>,
160 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
161 let vps = Vec::from_iter(vps);
162 let mut smt_enabled = false;
163 for (i, vp) in vps.iter().enumerate() {
164 if i != vp.base.vp_index.index() as usize {
165 return Err(InvalidTopology::InvalidVpIndices);
166 }
167
168 if vp.mpidr.mt() {
169 smt_enabled = true;
170 }
171 }
172
173 Ok(ProcessorTopology {
174 vps,
175 smt_enabled,
176 vps_per_socket: self.vps_per_socket,
177 arch: Aarch64Topology {
178 platform: self.arch.platform,
179 },
180 })
181 }
182}
183
184impl ProcessorTopology<Aarch64Topology> {
185 pub fn gic_distributor_base(&self) -> u64 {
187 self.arch.platform.gic_distributor_base
188 }
189
190 pub fn gic_redistributors_base(&self) -> u64 {
192 self.arch.platform.gic_redistributors_base
193 }
194
195 pub fn pmu_gsiv(&self) -> Option<u32> {
197 self.arch.platform.pmu_gsiv
198 }
199
200 pub fn gic_v2m(&self) -> Option<GicV2mInfo> {
202 self.arch.platform.gic_v2m
203 }
204
205 pub fn virt_timer_ppi(&self) -> u32 {
207 self.arch.platform.virt_timer_ppi
208 }
209}