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