xref: /cloud-hypervisor/vmm/src/device_tree.rs (revision 2bc8d51a60821504abdbd52f9ca7873c31ccdac2)
164e01684SSebastien Boeuf // Copyright © 2020 Intel Corporation
264e01684SSebastien Boeuf //
364e01684SSebastien Boeuf // SPDX-License-Identifier: Apache-2.0
464e01684SSebastien Boeuf 
564e01684SSebastien Boeuf use std::collections::HashMap;
664e01684SSebastien Boeuf use std::sync::{Arc, Mutex};
788a9f799SRob Bradford 
888a9f799SRob Bradford use pci::PciBdf;
988a9f799SRob Bradford use serde::{Deserialize, Serialize};
1064e01684SSebastien Boeuf use vm_device::Resource;
1164e01684SSebastien Boeuf use vm_migration::Migratable;
1264e01684SSebastien Boeuf 
1388a9f799SRob Bradford use crate::device_manager::PciDeviceHandle;
1488a9f799SRob Bradford 
1564e01684SSebastien Boeuf #[derive(Clone, Serialize, Deserialize)]
1664e01684SSebastien Boeuf pub struct DeviceNode {
1764e01684SSebastien Boeuf     pub id: String,
1864e01684SSebastien Boeuf     pub resources: Vec<Resource>,
1964e01684SSebastien Boeuf     pub parent: Option<String>,
2064e01684SSebastien Boeuf     pub children: Vec<String>,
2164e01684SSebastien Boeuf     #[serde(skip)]
2264e01684SSebastien Boeuf     pub migratable: Option<Arc<Mutex<dyn Migratable>>>,
2342b5d4a2SSebastien Boeuf     pub pci_bdf: Option<PciBdf>,
24b06fd80fSSebastien Boeuf     #[serde(skip)]
25b06fd80fSSebastien Boeuf     pub pci_device_handle: Option<PciDeviceHandle>,
2664e01684SSebastien Boeuf }
2764e01684SSebastien Boeuf 
2864e01684SSebastien Boeuf impl DeviceNode {
new(id: String, migratable: Option<Arc<Mutex<dyn Migratable>>>) -> Self2964e01684SSebastien Boeuf     pub fn new(id: String, migratable: Option<Arc<Mutex<dyn Migratable>>>) -> Self {
3064e01684SSebastien Boeuf         DeviceNode {
3164e01684SSebastien Boeuf             id,
3264e01684SSebastien Boeuf             resources: Vec::new(),
3364e01684SSebastien Boeuf             parent: None,
3464e01684SSebastien Boeuf             children: Vec::new(),
3564e01684SSebastien Boeuf             migratable,
3698dac352SSebastien Boeuf             pci_bdf: None,
37b06fd80fSSebastien Boeuf             pci_device_handle: None,
3864e01684SSebastien Boeuf         }
3964e01684SSebastien Boeuf     }
4064e01684SSebastien Boeuf }
4164e01684SSebastien Boeuf 
4264e01684SSebastien Boeuf #[macro_export]
4364e01684SSebastien Boeuf macro_rules! device_node {
4464e01684SSebastien Boeuf     ($id:ident) => {
4564e01684SSebastien Boeuf         DeviceNode::new($id.clone(), None)
4664e01684SSebastien Boeuf     };
4764e01684SSebastien Boeuf     ($id:ident, $device:ident) => {
4864e01684SSebastien Boeuf         DeviceNode::new(
4964e01684SSebastien Boeuf             $id.clone(),
5064e01684SSebastien Boeuf             Some(Arc::clone(&$device) as Arc<Mutex<dyn Migratable>>),
5164e01684SSebastien Boeuf         )
5264e01684SSebastien Boeuf     };
5364e01684SSebastien Boeuf }
5464e01684SSebastien Boeuf 
5564e01684SSebastien Boeuf #[derive(Clone, Default, Serialize, Deserialize)]
5664e01684SSebastien Boeuf pub struct DeviceTree(HashMap<String, DeviceNode>);
5764e01684SSebastien Boeuf 
5864e01684SSebastien Boeuf impl DeviceTree {
new() -> Self5964e01684SSebastien Boeuf     pub fn new() -> Self {
6064e01684SSebastien Boeuf         DeviceTree(HashMap::new())
6164e01684SSebastien Boeuf     }
contains_key(&self, k: &str) -> bool6262aacceeSSebastien Boeuf     pub fn contains_key(&self, k: &str) -> bool {
6362aacceeSSebastien Boeuf         self.0.contains_key(k)
6462aacceeSSebastien Boeuf     }
get(&self, k: &str) -> Option<&DeviceNode>6564e01684SSebastien Boeuf     pub fn get(&self, k: &str) -> Option<&DeviceNode> {
6664e01684SSebastien Boeuf         self.0.get(k)
6764e01684SSebastien Boeuf     }
get_mut(&mut self, k: &str) -> Option<&mut DeviceNode>6864e01684SSebastien Boeuf     pub fn get_mut(&mut self, k: &str) -> Option<&mut DeviceNode> {
6964e01684SSebastien Boeuf         self.0.get_mut(k)
7064e01684SSebastien Boeuf     }
insert(&mut self, k: String, v: DeviceNode) -> Option<DeviceNode>7164e01684SSebastien Boeuf     pub fn insert(&mut self, k: String, v: DeviceNode) -> Option<DeviceNode> {
7264e01684SSebastien Boeuf         self.0.insert(k, v)
7364e01684SSebastien Boeuf     }
remove(&mut self, k: &str) -> Option<DeviceNode>7464e01684SSebastien Boeuf     pub fn remove(&mut self, k: &str) -> Option<DeviceNode> {
7564e01684SSebastien Boeuf         self.0.remove(k)
7664e01684SSebastien Boeuf     }
iter(&self) -> std::collections::hash_map::Iter<'_, String, DeviceNode>77*2bc8d51aSJinank Jain     pub fn iter(&self) -> std::collections::hash_map::Iter<'_, String, DeviceNode> {
7864e01684SSebastien Boeuf         self.0.iter()
7964e01684SSebastien Boeuf     }
breadth_first_traversal(&self) -> BftIter<'_>80*2bc8d51aSJinank Jain     pub fn breadth_first_traversal(&self) -> BftIter<'_> {
8164e01684SSebastien Boeuf         BftIter::new(&self.0)
8264e01684SSebastien Boeuf     }
pci_devices(&self) -> Vec<&DeviceNode>83b06fd80fSSebastien Boeuf     pub fn pci_devices(&self) -> Vec<&DeviceNode> {
84b06fd80fSSebastien Boeuf         self.0
85b06fd80fSSebastien Boeuf             .values()
861a5a8950SRob Bradford             .filter(|v| v.pci_bdf.is_some() && v.pci_device_handle.is_some())
87b06fd80fSSebastien Boeuf             .collect()
88b06fd80fSSebastien Boeuf     }
89d33d2549SRob Bradford 
remove_node_by_pci_bdf(&mut self, pci_bdf: PciBdf) -> Option<DeviceNode>9042b5d4a2SSebastien Boeuf     pub fn remove_node_by_pci_bdf(&mut self, pci_bdf: PciBdf) -> Option<DeviceNode> {
91b06fd80fSSebastien Boeuf         let mut id = None;
92b06fd80fSSebastien Boeuf         for (k, v) in self.0.iter() {
931a5a8950SRob Bradford             if v.pci_bdf == Some(pci_bdf) {
94b06fd80fSSebastien Boeuf                 id = Some(k.clone());
95b06fd80fSSebastien Boeuf                 break;
96b06fd80fSSebastien Boeuf             }
97b06fd80fSSebastien Boeuf         }
98b06fd80fSSebastien Boeuf 
99b06fd80fSSebastien Boeuf         if let Some(id) = &id {
100b06fd80fSSebastien Boeuf             self.0.remove(id)
101b06fd80fSSebastien Boeuf         } else {
102b06fd80fSSebastien Boeuf             None
103b06fd80fSSebastien Boeuf         }
104b06fd80fSSebastien Boeuf     }
10564e01684SSebastien Boeuf }
10664e01684SSebastien Boeuf 
10764e01684SSebastien Boeuf // Breadth first traversal iterator.
10864e01684SSebastien Boeuf pub struct BftIter<'a> {
10964e01684SSebastien Boeuf     nodes: Vec<&'a DeviceNode>,
11064e01684SSebastien Boeuf }
11164e01684SSebastien Boeuf 
11264e01684SSebastien Boeuf impl<'a> BftIter<'a> {
new(hash_map: &'a HashMap<String, DeviceNode>) -> Self11364e01684SSebastien Boeuf     fn new(hash_map: &'a HashMap<String, DeviceNode>) -> Self {
114c56a3ce5SHao Xu         let mut nodes = Vec::with_capacity(hash_map.len());
115c56a3ce5SHao Xu         let mut i = 0;
11664e01684SSebastien Boeuf 
11764e01684SSebastien Boeuf         for (_, node) in hash_map.iter() {
11864e01684SSebastien Boeuf             if node.parent.is_none() {
11964e01684SSebastien Boeuf                 nodes.push(node);
12064e01684SSebastien Boeuf             }
12164e01684SSebastien Boeuf         }
12264e01684SSebastien Boeuf 
123c56a3ce5SHao Xu         while i < nodes.len() {
124c56a3ce5SHao Xu             for child_node_id in nodes[i].children.iter() {
12564e01684SSebastien Boeuf                 if let Some(child_node) = hash_map.get(child_node_id) {
126c56a3ce5SHao Xu                     nodes.push(child_node);
12764e01684SSebastien Boeuf                 }
12864e01684SSebastien Boeuf             }
129c56a3ce5SHao Xu             i += 1;
13064e01684SSebastien Boeuf         }
13164e01684SSebastien Boeuf 
13264e01684SSebastien Boeuf         BftIter { nodes }
13364e01684SSebastien Boeuf     }
13464e01684SSebastien Boeuf }
13564e01684SSebastien Boeuf 
13664e01684SSebastien Boeuf impl<'a> Iterator for BftIter<'a> {
13764e01684SSebastien Boeuf     type Item = &'a DeviceNode;
13864e01684SSebastien Boeuf 
next(&mut self) -> Option<Self::Item>13964e01684SSebastien Boeuf     fn next(&mut self) -> Option<Self::Item> {
14064e01684SSebastien Boeuf         if self.nodes.is_empty() {
14164e01684SSebastien Boeuf             None
14264e01684SSebastien Boeuf         } else {
14364e01684SSebastien Boeuf             Some(self.nodes.remove(0))
14464e01684SSebastien Boeuf         }
14564e01684SSebastien Boeuf     }
14664e01684SSebastien Boeuf }
14764e01684SSebastien Boeuf 
1480aab960bSRuoqing He impl DoubleEndedIterator for BftIter<'_> {
next_back(&mut self) -> Option<Self::Item>14964e01684SSebastien Boeuf     fn next_back(&mut self) -> Option<Self::Item> {
15064e01684SSebastien Boeuf         self.nodes.pop()
15164e01684SSebastien Boeuf     }
15264e01684SSebastien Boeuf }
153f6a71becSSebastien Boeuf 
154f6a71becSSebastien Boeuf #[cfg(test)]
155f6a71becSSebastien Boeuf mod tests {
156f6a71becSSebastien Boeuf     use super::{DeviceNode, DeviceTree};
157f6a71becSSebastien Boeuf 
158f6a71becSSebastien Boeuf     #[test]
test_device_tree()159f6a71becSSebastien Boeuf     fn test_device_tree() {
160f6a71becSSebastien Boeuf         // Check new()
161f6a71becSSebastien Boeuf         let mut device_tree = DeviceTree::new();
162e4763b47SRob Bradford         assert_eq!(device_tree.0.len(), 0);
163f6a71becSSebastien Boeuf 
164f6a71becSSebastien Boeuf         // Check insert()
165f6a71becSSebastien Boeuf         let id = String::from("id1");
166f6a71becSSebastien Boeuf         device_tree.insert(id.clone(), DeviceNode::new(id.clone(), None));
167e4763b47SRob Bradford         assert_eq!(device_tree.0.len(), 1);
168f6a71becSSebastien Boeuf         let node = device_tree.0.get(&id);
169e4763b47SRob Bradford         assert!(node.is_some());
170f6a71becSSebastien Boeuf         let node = node.unwrap();
171e4763b47SRob Bradford         assert_eq!(node.id, id);
172f6a71becSSebastien Boeuf 
173f6a71becSSebastien Boeuf         // Check get()
174f6a71becSSebastien Boeuf         let id2 = String::from("id2");
175e4763b47SRob Bradford         assert!(device_tree.get(&id).is_some());
176e4763b47SRob Bradford         assert!(device_tree.get(&id2).is_none());
177f6a71becSSebastien Boeuf 
178f6a71becSSebastien Boeuf         // Check get_mut()
179f6a71becSSebastien Boeuf         let node = device_tree.get_mut(&id).unwrap();
180521a0d1aSRob Bradford         node.id.clone_from(&id2);
181f6a71becSSebastien Boeuf         let node = device_tree.0.get(&id).unwrap();
182e4763b47SRob Bradford         assert_eq!(node.id, id2);
183f6a71becSSebastien Boeuf 
184f6a71becSSebastien Boeuf         // Check remove()
185f6a71becSSebastien Boeuf         let node = device_tree.remove(&id).unwrap();
186e4763b47SRob Bradford         assert_eq!(node.id, id2);
187e4763b47SRob Bradford         assert_eq!(device_tree.0.len(), 0);
188f6a71becSSebastien Boeuf 
189f6a71becSSebastien Boeuf         // Check iter()
190f6a71becSSebastien Boeuf         let disk_id = String::from("disk0");
191f6a71becSSebastien Boeuf         let net_id = String::from("net0");
192f6a71becSSebastien Boeuf         let rng_id = String::from("rng0");
193f6a71becSSebastien Boeuf         let device_list = vec![
194f6a71becSSebastien Boeuf             (disk_id.clone(), device_node!(disk_id)),
195f6a71becSSebastien Boeuf             (net_id.clone(), device_node!(net_id)),
196f6a71becSSebastien Boeuf             (rng_id.clone(), device_node!(rng_id)),
197f6a71becSSebastien Boeuf         ];
198f6a71becSSebastien Boeuf         device_tree.0.extend(device_list);
199f6a71becSSebastien Boeuf         for (id, node) in device_tree.iter() {
200f6a71becSSebastien Boeuf             if id == &disk_id {
201e4763b47SRob Bradford                 assert_eq!(node.id, disk_id);
202f6a71becSSebastien Boeuf             } else if id == &net_id {
203e4763b47SRob Bradford                 assert_eq!(node.id, net_id);
204f6a71becSSebastien Boeuf             } else if id == &rng_id {
205e4763b47SRob Bradford                 assert_eq!(node.id, rng_id);
206f6a71becSSebastien Boeuf             } else {
207e4763b47SRob Bradford                 unreachable!()
208f6a71becSSebastien Boeuf             }
209f6a71becSSebastien Boeuf         }
210f6a71becSSebastien Boeuf 
211f6a71becSSebastien Boeuf         // Check breadth_first_traversal() based on the following hierarchy
212f6a71becSSebastien Boeuf         //
213f6a71becSSebastien Boeuf         // 0
214f6a71becSSebastien Boeuf         // | \
215f6a71becSSebastien Boeuf         // 1  2
216f6a71becSSebastien Boeuf         // |  | \
217f6a71becSSebastien Boeuf         // 3  4  5
218f6a71becSSebastien Boeuf         //
219f6a71becSSebastien Boeuf         let mut device_tree = DeviceTree::new();
220f6a71becSSebastien Boeuf         let child_1_id = String::from("child1");
221f6a71becSSebastien Boeuf         let child_2_id = String::from("child2");
222f6a71becSSebastien Boeuf         let child_3_id = String::from("child3");
223f6a71becSSebastien Boeuf         let parent_1_id = String::from("parent1");
224f6a71becSSebastien Boeuf         let parent_2_id = String::from("parent2");
225f6a71becSSebastien Boeuf         let root_id = String::from("root");
226f6a71becSSebastien Boeuf         let mut child_1_node = device_node!(child_1_id);
227f6a71becSSebastien Boeuf         let mut child_2_node = device_node!(child_2_id);
228f6a71becSSebastien Boeuf         let mut child_3_node = device_node!(child_3_id);
229f6a71becSSebastien Boeuf         let mut parent_1_node = device_node!(parent_1_id);
230f6a71becSSebastien Boeuf         let mut parent_2_node = device_node!(parent_2_id);
231f6a71becSSebastien Boeuf         let mut root_node = device_node!(root_id);
232f6a71becSSebastien Boeuf         child_1_node.parent = Some(parent_1_id.clone());
233f6a71becSSebastien Boeuf         child_2_node.parent = Some(parent_2_id.clone());
234f6a71becSSebastien Boeuf         child_3_node.parent = Some(parent_2_id.clone());
235f6a71becSSebastien Boeuf         parent_1_node.children = vec![child_1_id.clone()];
236f6a71becSSebastien Boeuf         parent_1_node.parent = Some(root_id.clone());
237f6a71becSSebastien Boeuf         parent_2_node.children = vec![child_2_id.clone(), child_3_id.clone()];
238f6a71becSSebastien Boeuf         parent_2_node.parent = Some(root_id.clone());
239f6a71becSSebastien Boeuf         root_node.children = vec![parent_1_id.clone(), parent_2_id.clone()];
240f6a71becSSebastien Boeuf         let device_list = vec![
241f6a71becSSebastien Boeuf             (child_1_id.clone(), child_1_node),
242f6a71becSSebastien Boeuf             (child_2_id.clone(), child_2_node),
243f6a71becSSebastien Boeuf             (child_3_id.clone(), child_3_node),
244f6a71becSSebastien Boeuf             (parent_1_id.clone(), parent_1_node),
245f6a71becSSebastien Boeuf             (parent_2_id.clone(), parent_2_node),
246f6a71becSSebastien Boeuf             (root_id.clone(), root_node),
247f6a71becSSebastien Boeuf         ];
248f6a71becSSebastien Boeuf         device_tree.0.extend(device_list);
249f6a71becSSebastien Boeuf 
250f6a71becSSebastien Boeuf         let iter_vec = device_tree
251f6a71becSSebastien Boeuf             .breadth_first_traversal()
252f6a71becSSebastien Boeuf             .collect::<Vec<&DeviceNode>>();
253e4763b47SRob Bradford         assert_eq!(iter_vec.len(), 6);
254e4763b47SRob Bradford         assert_eq!(iter_vec[0].id, root_id);
255e4763b47SRob Bradford         assert_eq!(iter_vec[1].id, parent_1_id);
256e4763b47SRob Bradford         assert_eq!(iter_vec[2].id, parent_2_id);
257e4763b47SRob Bradford         assert_eq!(iter_vec[3].id, child_1_id);
258e4763b47SRob Bradford         assert_eq!(iter_vec[4].id, child_2_id);
259e4763b47SRob Bradford         assert_eq!(iter_vec[5].id, child_3_id);
260f6a71becSSebastien Boeuf 
261f6a71becSSebastien Boeuf         let iter_vec = device_tree
262f6a71becSSebastien Boeuf             .breadth_first_traversal()
263f6a71becSSebastien Boeuf             .rev()
264f6a71becSSebastien Boeuf             .collect::<Vec<&DeviceNode>>();
265e4763b47SRob Bradford         assert_eq!(iter_vec.len(), 6);
266e4763b47SRob Bradford         assert_eq!(iter_vec[5].id, root_id);
267e4763b47SRob Bradford         assert_eq!(iter_vec[4].id, parent_1_id);
268e4763b47SRob Bradford         assert_eq!(iter_vec[3].id, parent_2_id);
269e4763b47SRob Bradford         assert_eq!(iter_vec[2].id, child_1_id);
270e4763b47SRob Bradford         assert_eq!(iter_vec[1].id, child_2_id);
271e4763b47SRob Bradford         assert_eq!(iter_vec[0].id, child_3_id);
272f6a71becSSebastien Boeuf     }
273f6a71becSSebastien Boeuf }
274