vmm, doc: Forbid same memory zone in multiple NUMA nodes

It is forbidden that the same memory zone belongs to more than one
NUMA node. This commit adds related validation to the `--numa`
parameter to prevent the user from specifying such configuration.

Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
Henry Wang 2021-08-07 06:15:13 -04:00 committed by Sebastien Boeuf
parent f3197c3833
commit bcae6c41e3
2 changed files with 41 additions and 6 deletions

View File

@ -441,6 +441,10 @@ Multiple values can be provided to define the list. Each value is a string
referring to an existing memory zone identifier. Values are separated from
each other with the `:` separator.
Note that a memory zone must belong to a single NUMA node. The following
configuration is incorrect, therefore not allowed:
`--numa guest_numa_id=0,memory_zones=mem0 guest_numa_id=1,memory_zones=mem0`
_Example_
```

View File

@ -8,6 +8,7 @@ use net_util::MacAddr;
use option_parser::{
ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, TupleTwoIntegers,
};
use std::collections::HashMap;
use std::convert::From;
use std::fmt;
use std::net::Ipv4Addr;
@ -126,20 +127,22 @@ pub enum ValidationError {
VnetQueueFdMismatch,
/// Using reserved fd
VnetReservedFd,
// Hugepages not turned on
/// Hugepages not turned on
HugePageSizeWithoutHugePages,
// Huge page size is not power of 2
/// Huge page size is not power of 2
InvalidHugePageSize(u64),
// CPU Hotplug not permitted with TDX
/// CPU Hotplug not permitted with TDX
#[cfg(feature = "tdx")]
TdxNoCpuHotplug,
// Specifying kernel not permitted with TDX
/// Specifying kernel not permitted with TDX
#[cfg(feature = "tdx")]
TdxKernelSpecified,
// Insuffient vCPUs for queues
/// Insuffient vCPUs for queues
TooManyQueues,
// Need shared memory for vfio-user
/// Need shared memory for vfio-user
UserDevicesRequireSharedMemory,
/// Memory zone is reused across NUMA nodes
MemoryZoneReused(String, u32, u32),
}
type ValidationResult<T> = std::result::Result<T, ValidationError>;
@ -190,6 +193,13 @@ impl fmt::Display for ValidationError {
UserDevicesRequireSharedMemory => {
write!(f, "Using user devices requires using shared memory")
}
MemoryZoneReused(s, u1, u2) => {
write!(
f,
"Memory zone: {} belongs to multiple NUMA nodes {} and {}",
s, u1, u2
)
}
}
}
}
@ -1915,6 +1925,27 @@ impl VmConfig {
return Err(ValidationError::UserDevicesRequireSharedMemory);
}
}
if let Some(numa) = &self.numa {
let mut used_numa_node_memory_zones = HashMap::new();
for numa_node in numa.iter() {
for memory_zone in numa_node.memory_zones.clone().unwrap().iter() {
if !used_numa_node_memory_zones.contains_key(memory_zone) {
used_numa_node_memory_zones
.insert(memory_zone.to_string(), numa_node.guest_numa_id);
} else {
return Err(ValidationError::MemoryZoneReused(
memory_zone.to_string(),
*used_numa_node_memory_zones
.get(&memory_zone.to_string())
.unwrap(),
numa_node.guest_numa_id,
));
}
}
}
}
Ok(())
}