From 29607f38adea4f399a6359ca9ca379ba7ccf7f23 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Thu, 4 Feb 2021 16:21:53 +0000 Subject: [PATCH] vmm: config: Add a hugepage_size option This allows the user to use an alternative huge page size otherwise the default size will be used. Signed-off-by: Rob Bradford --- src/main.rs | 8 +++-- vmm/src/config.rs | 70 +++++++++++++++++++++++++++++++++++++-- vmm/src/memory_manager.rs | 1 + 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6a23bc3ae..7ac9e393e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -147,7 +147,8 @@ fn create_app<'a, 'b>( .long("memory") .help( "Memory parameters \ - \"size=,mergeable=on|off,shared=on|off,hugepages=on|off,\ + \"size=,mergeable=on|off,shared=on|off,\ + hugepages=on|off,hugepage_size=\ hotplug_method=acpi|virtio-mem,\ hotplug_size=,\ hotplugged_size=\"", @@ -161,7 +162,9 @@ fn create_app<'a, 'b>( .help( "User defined memory zone parameters \ \"size=,file=,\ - shared=on|off,hugepages=on|off,host_numa_node=,\ + shared=on|off,\ + hugepages=on|off,hugepage_size=\ + host_numa_node=,\ id=,hotplug_size=,\ hotplugged_size=\"", ) @@ -585,6 +588,7 @@ mod unit_tests { shared: false, hugepages: false, zones: None, + hugepage_size: None, }, kernel: Some(KernelConfig { path: PathBuf::from("/path/to/kernel"), diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 36313c830..ecec20012 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -109,6 +109,10 @@ pub enum ValidationError { VnetQueueLowerThan2, /// The input queue number for virtio_net must match the number of input fds VnetQueueFdMismatch, + // Hugepages not turned on + HugePageSizeWithoutHugePages, + // Huge page size is not power of 2 + InvalidHugePageSize(u64), } type ValidationResult = std::result::Result; @@ -138,6 +142,12 @@ impl fmt::Display for ValidationError { f, "Number of queues to virtio_net does not match the number of input FDs" ), + HugePageSizeWithoutHugePages => { + write!(f, "Huge page size specified but huge pages not enabled") + } + InvalidHugePageSize(s) => { + write!(f, "Huge page size is not power of 2: {}", s) + } } } } @@ -404,6 +414,8 @@ pub struct MemoryZoneConfig { #[serde(default)] pub hugepages: bool, #[serde(default)] + pub hugepage_size: Option, + #[serde(default)] pub host_numa_node: Option, #[serde(default)] pub hotplug_size: Option, @@ -427,6 +439,8 @@ pub struct MemoryConfig { #[serde(default)] pub hugepages: bool, #[serde(default)] + pub hugepage_size: Option, + #[serde(default)] pub zones: Option>, } @@ -441,7 +455,8 @@ impl MemoryConfig { .add("hotplug_size") .add("hotplugged_size") .add("shared") - .add("hugepages"); + .add("hugepages") + .add("hugepage_size"); parser.parse(memory).map_err(Error::ParseMemory)?; let size = parser @@ -476,6 +491,10 @@ impl MemoryConfig { .map_err(Error::ParseMemory)? .unwrap_or(Toggle(false)) .0; + let hugepage_size = parser + .convert::("hugepage_size") + .map_err(Error::ParseMemory)? + .map(|v| v.0); let zones: Option> = if let Some(memory_zones) = &memory_zones { let mut zones = Vec::new(); @@ -487,6 +506,7 @@ impl MemoryConfig { .add("file") .add("shared") .add("hugepages") + .add("hugepage_size") .add("host_numa_node") .add("hotplug_size") .add("hotplugged_size"); @@ -509,6 +529,11 @@ impl MemoryConfig { .map_err(Error::ParseMemoryZone)? .unwrap_or(Toggle(false)) .0; + let hugepage_size = parser + .convert::("hugepage_size") + .map_err(Error::ParseMemoryZone)? + .map(|v| v.0); + let host_numa_node = parser .convert::("host_numa_node") .map_err(Error::ParseMemoryZone)?; @@ -527,6 +552,7 @@ impl MemoryConfig { file, shared, hugepages, + hugepage_size, host_numa_node, hotplug_size, hotplugged_size, @@ -545,6 +571,7 @@ impl MemoryConfig { hotplugged_size, shared, hugepages, + hugepage_size, zones, }) } @@ -578,6 +605,7 @@ impl Default for MemoryConfig { hotplugged_size: None, shared: false, hugepages: false, + hugepage_size: None, zones: None, } } @@ -1523,6 +1551,15 @@ impl VmConfig { } } + if let Some(hugepage_size) = &self.memory.hugepage_size { + if !self.memory.hugepages { + return Err(ValidationError::HugePageSizeWithoutHugePages); + } + if !hugepage_size.is_power_of_two() { + return Err(ValidationError::InvalidHugePageSize(*hugepage_size)); + } + } + Ok(()) } @@ -1805,6 +1842,15 @@ mod tests { ..Default::default() } ); + assert_eq!( + MemoryConfig::parse("hugepages=on,size=1G,hugepage_size=2M", None)?, + MemoryConfig { + hugepage_size: Some(2 << 20), + size: 1 << 30, + hugepages: true, + ..Default::default() + } + ); Ok(()) } @@ -2228,6 +2274,7 @@ mod tests { hotplugged_size: None, shared: false, hugepages: false, + hugepage_size: None, zones: None, }, kernel: Some(KernelConfig { @@ -2351,10 +2398,29 @@ mod tests { }]); assert!(invalid_config.validate().is_err()); - let mut still_valid_config = valid_config; + let mut still_valid_config = valid_config.clone(); still_valid_config.memory.shared = true; assert!(still_valid_config.validate().is_ok()); + let mut still_valid_config = valid_config.clone(); + still_valid_config.memory.hugepages = true; + assert!(still_valid_config.validate().is_ok()); + + let mut still_valid_config = valid_config.clone(); + still_valid_config.memory.hugepages = true; + still_valid_config.memory.hugepage_size = Some(2 << 20); + assert!(still_valid_config.validate().is_ok()); + + let mut invalid_config = valid_config.clone(); + invalid_config.memory.hugepages = false; + invalid_config.memory.hugepage_size = Some(2 << 20); + assert!(invalid_config.validate().is_err()); + + let mut invalid_config = valid_config; + invalid_config.memory.hugepages = true; + invalid_config.memory.hugepage_size = Some(3 << 20); + assert!(invalid_config.validate().is_err()); + Ok(()) } } diff --git a/vmm/src/memory_manager.rs b/vmm/src/memory_manager.rs index a56b979eb..37db174e4 100644 --- a/vmm/src/memory_manager.rs +++ b/vmm/src/memory_manager.rs @@ -552,6 +552,7 @@ impl MemoryManager { file: None, shared: config.shared, hugepages: config.hugepages, + hugepage_size: config.hugepage_size, host_numa_node: None, hotplug_size: config.hotplug_size, hotplugged_size: config.hotplugged_size,