main, vmm: Add new --numa parameter

Through this new parameter, we give users the opportunity to specify a
set of CPUs attached to a NUMA node that has been previously created
from the --memory-zone parameter.

This parameter will be extended in the future to describe the distance
between multiple nodes.

For instance, if a user wants to attach CPUs 0, 1, 2 and 6 to a NUMA
node, here are two different ways of doing so:
Either
	./cloud-hypervisor ... --numa id=0,cpus=0-2:6
Or
	./cloud-hypervisor ... --numa id=0,cpus=0:1:2:6

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2020-08-28 18:20:12 +02:00
parent 36171caba9
commit 42f963d6f2
4 changed files with 120 additions and 1 deletions
+18
View File
@@ -413,6 +413,10 @@ components:
type: array
items:
$ref: '#/components/schemas/SgxEpcConfig'
numa:
type: array
items:
$ref: '#/components/schemas/NumaConfig'
iommu:
type: boolean
default: false
@@ -717,6 +721,20 @@ components:
type: boolean
default: false
NumaConfig:
required:
- id
type: object
properties:
id:
type: integer
format: uint32
cpus:
type: array
items:
type: integer
format: uint8
VmResize:
type: object
properties:
+49 -1
View File
@@ -5,7 +5,7 @@
use clap::ArgMatches;
use net_util::MacAddr;
use option_parser::{ByteSized, OptionParser, OptionParserError, Toggle};
use option_parser::{ByteSized, IntegerList, OptionParser, OptionParserError, Toggle};
use std::convert::From;
use std::fmt;
use std::net::Ipv4Addr;
@@ -69,6 +69,8 @@ pub enum Error {
/// Failed to parse SGX EPC parameters
#[cfg(target_arch = "x86_64")]
ParseSgxEpc(OptionParserError),
/// Failed to parse NUMA parameters
ParseNuma(OptionParserError),
/// Failed to validate configuration
Validation(ValidationError),
}
@@ -156,6 +158,7 @@ impl fmt::Display for Error {
ParseRestore(o) => write!(f, "Error parsing --restore: {}", o),
#[cfg(target_arch = "x86_64")]
ParseSgxEpc(o) => write!(f, "Error parsing --sgx-epc: {}", o),
ParseNuma(o) => write!(f, "Error parsing --numa: {}", o),
ParseRestoreSourceUrlMissing => {
write!(f, "Error parsing --restore: source_url missing")
}
@@ -184,6 +187,7 @@ pub struct VmParams<'a> {
pub vsock: Option<&'a str>,
#[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<&'a str>>,
pub numa: Option<Vec<&'a str>>,
}
impl<'a> VmParams<'a> {
@@ -208,6 +212,7 @@ impl<'a> VmParams<'a> {
let vsock: Option<&str> = args.value_of("vsock");
#[cfg(target_arch = "x86_64")]
let sgx_epc: Option<Vec<&str>> = args.values_of("sgx-epc").map(|x| x.collect());
let numa: Option<Vec<&str>> = args.values_of("numa").map(|x| x.collect());
VmParams {
cpus,
@@ -227,6 +232,7 @@ impl<'a> VmParams<'a> {
vsock,
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
}
}
}
@@ -1204,6 +1210,35 @@ impl SgxEpcConfig {
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
pub struct NumaConfig {
#[serde(default)]
pub id: u32,
#[serde(default)]
pub cpus: Option<Vec<u8>>,
}
impl NumaConfig {
pub const SYNTAX: &'static str = "Settings related to a given NUMA node \
\"id=<node_id>,cpus=<cpus_id>\"";
pub fn parse(numa: &str) -> Result<Self> {
let mut parser = OptionParser::new();
parser.add("id").add("cpus");
parser.parse(numa).map_err(Error::ParseNuma)?;
let id = parser
.convert::<u32>("id")
.map_err(Error::ParseNuma)?
.unwrap_or(0);
let cpus = parser
.convert::<IntegerList>("cpus")
.map_err(Error::ParseNuma)?
.map(|v| v.0.iter().map(|e| *e as u8).collect());
Ok(NumaConfig { id, cpus })
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
pub struct RestoreConfig {
pub source_url: PathBuf,
@@ -1265,6 +1300,7 @@ pub struct VmConfig {
pub iommu: bool,
#[cfg(target_arch = "x86_64")]
pub sgx_epc: Option<Vec<SgxEpcConfig>>,
pub numa: Option<Vec<NumaConfig>>,
}
impl VmConfig {
@@ -1438,6 +1474,16 @@ impl VmConfig {
}
}
let mut numa: Option<Vec<NumaConfig>> = None;
if let Some(numa_list) = &vm_params.numa {
let mut numa_config_list = Vec::new();
for item in numa_list.iter() {
let numa_config = NumaConfig::parse(item)?;
numa_config_list.push(numa_config);
}
numa = Some(numa_config_list);
}
let mut kernel: Option<KernelConfig> = None;
if let Some(k) = vm_params.kernel {
kernel = Some(KernelConfig {
@@ -1470,6 +1516,7 @@ impl VmConfig {
iommu,
#[cfg(target_arch = "x86_64")]
sgx_epc,
numa,
};
config.validate().map_err(Error::Validation)?;
Ok(config)
@@ -2038,6 +2085,7 @@ mod tests {
iommu: false,
#[cfg(target_arch = "x86_64")]
sgx_epc: None,
numa: None,
};
assert!(valid_config.validate().is_ok());