mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Create virtio-mem device with appropriate NUMA node
Now that virtio-mem device accept a guest NUMA node as parameter, we retrieve this information from the list of NUMA nodes. Based on the memory zone associated with the virtio-mem device, we obtain the NUMA node identifier, which we provide to the virtio-mem device. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
@@ -18,6 +18,8 @@ use crate::device_tree::{DeviceNode, DeviceTree};
|
|||||||
use crate::interrupt::kvm::KvmMsiInterruptManager as MsiInterruptManager;
|
use crate::interrupt::kvm::KvmMsiInterruptManager as MsiInterruptManager;
|
||||||
use crate::interrupt::LegacyUserspaceInterruptManager;
|
use crate::interrupt::LegacyUserspaceInterruptManager;
|
||||||
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
use crate::vm::NumaNodes;
|
||||||
#[cfg(feature = "pci_support")]
|
#[cfg(feature = "pci_support")]
|
||||||
use crate::PciDeviceInfo;
|
use crate::PciDeviceInfo;
|
||||||
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
||||||
@@ -805,9 +807,14 @@ pub struct DeviceManager {
|
|||||||
|
|
||||||
// seccomp action
|
// seccomp action
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
|
|
||||||
|
// List of guest NUMA nodes.
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
numa_nodes: NumaNodes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceManager {
|
impl DeviceManager {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
vm: Arc<dyn hypervisor::Vm>,
|
vm: Arc<dyn hypervisor::Vm>,
|
||||||
config: Arc<Mutex<VmConfig>>,
|
config: Arc<Mutex<VmConfig>>,
|
||||||
@@ -816,6 +823,7 @@ impl DeviceManager {
|
|||||||
#[cfg_attr(target_arch = "aarch64", allow(unused_variables))] reset_evt: &EventFd,
|
#[cfg_attr(target_arch = "aarch64", allow(unused_variables))] reset_evt: &EventFd,
|
||||||
vmm_path: PathBuf,
|
vmm_path: PathBuf,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
|
#[cfg(feature = "acpi")] numa_nodes: NumaNodes,
|
||||||
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
|
) -> DeviceManagerResult<Arc<Mutex<Self>>> {
|
||||||
let device_tree = Arc::new(Mutex::new(DeviceTree::new()));
|
let device_tree = Arc::new(Mutex::new(DeviceTree::new()));
|
||||||
|
|
||||||
@@ -878,6 +886,8 @@ impl DeviceManager {
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
id_to_dev_info: HashMap::new(),
|
id_to_dev_info: HashMap::new(),
|
||||||
seccomp_action,
|
seccomp_action,
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
numa_nodes,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
@@ -2419,13 +2429,19 @@ impl DeviceManager {
|
|||||||
|
|
||||||
let mm = self.memory_manager.clone();
|
let mm = self.memory_manager.clone();
|
||||||
let mm = mm.lock().unwrap();
|
let mm = mm.lock().unwrap();
|
||||||
for (_, memory_zone) in mm.memory_zones().iter() {
|
for (_memory_zone_id, memory_zone) in mm.memory_zones().iter() {
|
||||||
if let (Some(region), Some(resize)) = (
|
if let (Some(region), Some(resize)) = (
|
||||||
memory_zone.virtio_mem_region(),
|
memory_zone.virtio_mem_region(),
|
||||||
memory_zone.virtio_mem_resize(),
|
memory_zone.virtio_mem_resize(),
|
||||||
) {
|
) {
|
||||||
let id = self.next_device_name(MEM_DEVICE_NAME_PREFIX)?;
|
let id = self.next_device_name(MEM_DEVICE_NAME_PREFIX)?;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "acpi"))]
|
||||||
|
let node_id: Option<u16> = None;
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
let node_id = numa_node_id_from_memory_zone_id(&self.numa_nodes, _memory_zone_id)
|
||||||
|
.map(|i| i as u16);
|
||||||
|
|
||||||
let virtio_mem_device = Arc::new(Mutex::new(
|
let virtio_mem_device = Arc::new(Mutex::new(
|
||||||
virtio_devices::Mem::new(
|
virtio_devices::Mem::new(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
@@ -2434,7 +2450,7 @@ impl DeviceManager {
|
|||||||
.try_clone()
|
.try_clone()
|
||||||
.map_err(DeviceManagerError::TryCloneVirtioMemResize)?,
|
.map_err(DeviceManagerError::TryCloneVirtioMemResize)?,
|
||||||
self.seccomp_action.clone(),
|
self.seccomp_action.clone(),
|
||||||
None,
|
node_id,
|
||||||
)
|
)
|
||||||
.map_err(DeviceManagerError::CreateVirtioMem)?,
|
.map_err(DeviceManagerError::CreateVirtioMem)?,
|
||||||
));
|
));
|
||||||
@@ -3356,6 +3372,20 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
fn numa_node_id_from_memory_zone_id(numa_nodes: &NumaNodes, memory_zone_id: &str) -> Option<u32> {
|
||||||
|
for (numa_node_id, numa_node) in numa_nodes.iter() {
|
||||||
|
if numa_node
|
||||||
|
.memory_zones()
|
||||||
|
.contains(&memory_zone_id.to_owned())
|
||||||
|
{
|
||||||
|
return Some(*numa_node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
struct PciDevSlot {
|
struct PciDevSlot {
|
||||||
device_id: u8,
|
device_id: u8,
|
||||||
|
|||||||
@@ -212,11 +212,12 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default)]
|
||||||
pub struct NumaNode {
|
pub struct NumaNode {
|
||||||
memory_regions: Vec<Arc<GuestRegionMmap>>,
|
memory_regions: Vec<Arc<GuestRegionMmap>>,
|
||||||
cpus: Vec<u8>,
|
cpus: Vec<u8>,
|
||||||
distances: BTreeMap<u32, u8>,
|
distances: BTreeMap<u32, u8>,
|
||||||
|
memory_zones: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NumaNode {
|
impl NumaNode {
|
||||||
@@ -231,6 +232,10 @@ impl NumaNode {
|
|||||||
pub fn distances(&self) -> &BTreeMap<u32, u8> {
|
pub fn distances(&self) -> &BTreeMap<u32, u8> {
|
||||||
&self.distances
|
&self.distances
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn memory_zones(&self) -> &Vec<String> {
|
||||||
|
&self.memory_zones
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type NumaNodes = BTreeMap<u32, NumaNode>;
|
pub type NumaNodes = BTreeMap<u32, NumaNode>;
|
||||||
@@ -317,6 +322,11 @@ impl Vm {
|
|||||||
.validate()
|
.validate()
|
||||||
.map_err(Error::ConfigValidation)?;
|
.map_err(Error::ConfigValidation)?;
|
||||||
|
|
||||||
|
// Create NUMA nodes based on NumaConfig.
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
let numa_nodes =
|
||||||
|
Self::create_numa_nodes(config.lock().unwrap().numa.clone(), &memory_manager)?;
|
||||||
|
|
||||||
let device_manager = DeviceManager::new(
|
let device_manager = DeviceManager::new(
|
||||||
vm.clone(),
|
vm.clone(),
|
||||||
config.clone(),
|
config.clone(),
|
||||||
@@ -325,6 +335,8 @@ impl Vm {
|
|||||||
&reset_evt,
|
&reset_evt,
|
||||||
vmm_path,
|
vmm_path,
|
||||||
seccomp_action.clone(),
|
seccomp_action.clone(),
|
||||||
|
#[cfg(feature = "acpi")]
|
||||||
|
numa_nodes.clone(),
|
||||||
)
|
)
|
||||||
.map_err(Error::DeviceManager)?;
|
.map_err(Error::DeviceManager)?;
|
||||||
|
|
||||||
@@ -352,11 +364,6 @@ impl Vm {
|
|||||||
.transpose()
|
.transpose()
|
||||||
.map_err(Error::InitramfsFile)?;
|
.map_err(Error::InitramfsFile)?;
|
||||||
|
|
||||||
// Create NUMA nodes based on NumaConfig.
|
|
||||||
#[cfg(feature = "acpi")]
|
|
||||||
let numa_nodes =
|
|
||||||
Self::create_numa_nodes(config.lock().unwrap().numa.clone(), &memory_manager)?;
|
|
||||||
|
|
||||||
Ok(Vm {
|
Ok(Vm {
|
||||||
kernel,
|
kernel,
|
||||||
initramfs,
|
initramfs,
|
||||||
@@ -395,16 +402,13 @@ impl Vm {
|
|||||||
return Err(Error::InvalidNumaConfig);
|
return Err(Error::InvalidNumaConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut node = NumaNode {
|
let mut node = NumaNode::default();
|
||||||
memory_regions: Vec::new(),
|
|
||||||
cpus: Vec::new(),
|
|
||||||
distances: BTreeMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(memory_zones) = &config.memory_zones {
|
if let Some(memory_zones) = &config.memory_zones {
|
||||||
for memory_zone in memory_zones.iter() {
|
for memory_zone in memory_zones.iter() {
|
||||||
if let Some(mm_zone) = mm_zones.get(memory_zone) {
|
if let Some(mm_zone) = mm_zones.get(memory_zone) {
|
||||||
node.memory_regions.extend(mm_zone.regions().clone());
|
node.memory_regions.extend(mm_zone.regions().clone());
|
||||||
|
node.memory_zones.push(memory_zone.clone());
|
||||||
} else {
|
} else {
|
||||||
error!("Unknown memory zone '{}'", memory_zone);
|
error!("Unknown memory zone '{}'", memory_zone);
|
||||||
return Err(Error::InvalidNumaConfig);
|
return Err(Error::InvalidNumaConfig);
|
||||||
|
|||||||
Reference in New Issue
Block a user