diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index 906960fde..e09425078 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -67,6 +67,7 @@ struct HotPlugState { pub struct NumaNode { memory_regions: Vec>, cpus: Vec, + distances: BTreeMap, } impl NumaNode { @@ -81,6 +82,14 @@ impl NumaNode { pub fn cpus_mut(&mut self) -> &mut Vec { &mut self.cpus } + + pub fn distances(&self) -> &BTreeMap { + &self.distances + } + + pub fn distances_mut(&mut self) -> &mut BTreeMap { + &mut self.distances + } } pub type NumaNodes = BTreeMap; @@ -366,6 +375,7 @@ impl MemoryManager { NumaNode { memory_regions: vec![region.clone()], cpus: Vec::new(), + distances: BTreeMap::new(), }, ); } diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index bf5d8dcc5..9cd7dc9e4 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -195,6 +195,9 @@ pub enum Error { /// Failed serializing into JSON SerializeJson(serde_json::Error), + + /// Invalid configuration for NUMA. + InvalidNumaConfig, } pub type Result = result::Result; @@ -339,12 +342,30 @@ impl Vm { ) -> Result<()> { let mut mm = memory_manager.lock().unwrap(); let numa_nodes = mm.numa_nodes_mut(); + let existing_nodes: Vec = numa_nodes.keys().cloned().collect(); for config in configs.iter() { - if let Some(cpus) = &config.cpus { - if let Some(node) = numa_nodes.get_mut(&config.id) { + if let Some(node) = numa_nodes.get_mut(&config.id) { + if let Some(cpus) = &config.cpus { node.cpus_mut().extend(cpus); } + + if let Some(distances) = &config.distances { + for distance in distances.iter() { + let dest = distance.destination; + let dist = distance.distance; + + if !existing_nodes.contains(&dest) { + error!("Unknown destination NUMA node {}", dest); + return Err(Error::InvalidNumaConfig); + } + + node.distances_mut().insert(dest, dist); + } + } + } else { + error!("Unknown NUMA node {}", config.id); + return Err(Error::InvalidNumaConfig); } }