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}
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 gic: GicInfo,
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
44pub struct GicInfo {
45 #[cfg_attr(feature = "inspect", inspect(hex))]
47 pub gic_distributor_base: u64,
48 #[cfg_attr(feature = "inspect", inspect(hex))]
50 pub gic_redistributors_base: u64,
51}
52
53#[cfg_attr(feature = "inspect", derive(inspect::Inspect))]
55#[derive(Debug, Copy, Clone)]
56pub struct Aarch64VpInfo {
57 #[cfg_attr(feature = "inspect", inspect(flatten))]
59 pub base: VpInfo,
60 #[cfg_attr(
62 feature = "inspect",
63 inspect(with = "|&x| inspect::AsHex(u64::from(x))")
64 )]
65 pub mpidr: MpidrEl1,
66 #[cfg_attr(feature = "inspect", inspect(hex))]
68 pub gicr: u64,
69}
70
71impl AsRef<VpInfo> for Aarch64VpInfo {
72 fn as_ref(&self) -> &VpInfo {
73 &self.base
74 }
75}
76
77impl TopologyBuilder<Aarch64Topology> {
78 pub fn new_aarch64(gic: GicInfo) -> Self {
80 Self {
81 vps_per_socket: 1,
82 smt_enabled: false,
83 arch: Aarch64TopologyBuilderState { gic },
84 }
85 }
86
87 pub fn build(
89 &self,
90 proc_count: u32,
91 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
92 if proc_count >= 256 {
93 return Err(InvalidTopology::TooManyVps {
94 requested: proc_count,
95 max: u8::MAX.into(),
96 });
97 }
98 let mpidrs = (0..proc_count).map(|vp_index| {
99 let uni_proc = proc_count == 1;
102 let mut aff = (0..4).map(|i| (vp_index >> (8 * i)) as u8);
103 MpidrEl1::new()
104 .with_res1_31(true)
105 .with_u(uni_proc)
106 .with_aff0(aff.next().unwrap())
107 .with_aff1(aff.next().unwrap())
108 .with_aff2(aff.next().unwrap())
109 .with_aff3(aff.next().unwrap())
110 });
111 self.build_with_vp_info(mpidrs.enumerate().map(|(id, mpidr)| Aarch64VpInfo {
112 base: VpInfo {
113 vp_index: VpIndex::new(id as u32),
114 vnode: 0,
115 },
116 mpidr,
117 gicr: self.arch.gic.gic_redistributors_base
118 + id as u64 * aarch64defs::GIC_REDISTRIBUTOR_SIZE,
119 }))
120 }
121
122 pub fn build_with_vp_info(
124 &self,
125 vps: impl IntoIterator<Item = Aarch64VpInfo>,
126 ) -> Result<ProcessorTopology<Aarch64Topology>, InvalidTopology> {
127 let vps = Vec::from_iter(vps);
128 let mut smt_enabled = false;
129 for (i, vp) in vps.iter().enumerate() {
130 if i != vp.base.vp_index.index() as usize {
131 return Err(InvalidTopology::InvalidVpIndices);
132 }
133
134 if vp.mpidr.mt() {
135 smt_enabled = true;
136 }
137 }
138
139 Ok(ProcessorTopology {
140 vps,
141 smt_enabled,
142 vps_per_socket: self.vps_per_socket,
143 arch: Aarch64Topology { gic: self.arch.gic },
144 })
145 }
146}
147
148impl ProcessorTopology<Aarch64Topology> {
149 pub fn gic_distributor_base(&self) -> u64 {
151 self.arch.gic.gic_distributor_base
152 }
153
154 pub fn gic_redistributors_base(&self) -> u64 {
156 self.arch.gic.gic_redistributors_base
157 }
158}