devices, vmm: Handle ivshmem bar reprogramming properly

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Songqian Li <sionli@tencent.com>
This commit is contained in:
Songqian Li
2025-07-08 11:53:16 +08:00
committed by Bo Chen
parent 51e095c54d
commit 5128ee9ba6
3 changed files with 165 additions and 23 deletions

View File

@@ -53,6 +53,8 @@ use devices::gic;
use devices::interrupt_controller::InterruptController;
#[cfg(target_arch = "x86_64")]
use devices::ioapic;
#[cfg(feature = "ivshmem")]
use devices::ivshmem::{IvshmemError, IvshmemOps};
#[cfg(all(feature = "fw_cfg", target_arch = "x86_64"))]
use devices::legacy::fw_cfg::FW_CFG_ACPI_ID;
#[cfg(target_arch = "aarch64")]
@@ -639,7 +641,7 @@ pub enum DeviceManagerError {
#[cfg(feature = "ivshmem")]
/// Cannot create a ivshmem device
#[error("Cannot create a ivshmem device: {0}")]
IvshmemCreate(devices::ivshmem::IvshmemError),
IvshmemCreate(IvshmemError),
/// Cannot create a RateLimiterGroup
#[error("Cannot create a RateLimiterGroup")]
@@ -4232,11 +4234,16 @@ impl DeviceManager {
self.pci_resources(&id, pci_segment_id)?;
let snapshot = snapshot_from_id(self.snapshot.as_ref(), id.as_str());
let ivshmem_ops = Arc::new(Mutex::new(IvshmemHandler {
memory_manager: self.memory_manager.clone(),
}));
let ivshmem_device = Arc::new(Mutex::new(
devices::IvshmemDevice::new(
id.clone(),
ivshmem_cfg.size as u64,
snapshot,
Some(ivshmem_cfg.path.clone()),
ivshmem_ops.clone(),
snapshot,
)
.map_err(DeviceManagerError::IvshmemCreate)?,
));
@@ -4247,6 +4254,15 @@ impl DeviceManager {
pci_device_bdf,
resources,
)?;
let start_addr = ivshmem_device.lock().unwrap().data_bar_addr();
let (region, mapping) = ivshmem_ops
.lock()
.unwrap()
.map_ram_region(start_addr, ivshmem_cfg.size, Some(ivshmem_cfg.path.clone()))
.map_err(DeviceManagerError::IvshmemCreate)?;
ivshmem_device.lock().unwrap().set_region(region, mapping);
let mut node = device_node!(id, ivshmem_device);
node.resources = new_resources;
node.pci_bdf = Some(pci_device_bdf);
@@ -4929,6 +4945,74 @@ impl DeviceManager {
}
}
#[cfg(feature = "ivshmem")]
struct IvshmemHandler {
memory_manager: Arc<Mutex<MemoryManager>>,
}
#[cfg(feature = "ivshmem")]
impl IvshmemOps for IvshmemHandler {
fn map_ram_region(
&mut self,
start_addr: u64,
size: usize,
backing_file: Option<PathBuf>,
) -> Result<(Arc<GuestRegionMmap>, UserspaceMapping), IvshmemError> {
info!("Creating ivshmem mem region at 0x{:x}", start_addr);
let region = MemoryManager::create_ram_region(
&backing_file,
0,
GuestAddress(start_addr),
size,
false,
true,
false,
None,
None,
None,
false,
)
.map_err(|_| IvshmemError::CreateUserMemoryRegion)?;
let mem_slot = self
.memory_manager
.lock()
.unwrap()
.create_userspace_mapping(
region.start_addr().0,
region.len(),
region.as_ptr() as u64,
false,
false,
false,
)
.map_err(|_| IvshmemError::CreateUserspaceMapping)?;
let mapping = UserspaceMapping {
host_addr: region.as_ptr() as u64,
mem_slot,
addr: GuestAddress(region.start_addr().0),
len: region.len(),
mergeable: false,
};
Ok((region, mapping))
}
fn unmap_ram_region(&mut self, mapping: UserspaceMapping) -> Result<(), IvshmemError> {
self.memory_manager
.lock()
.unwrap()
.remove_userspace_mapping(
mapping.addr.raw_value(),
mapping.len,
mapping.host_addr,
mapping.mergeable,
mapping.mem_slot,
)
.map_err(|_| IvshmemError::RemoveUserspaceMapping)?;
Ok(())
}
}
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()) {

View File

@@ -835,7 +835,6 @@ fn vcpu_thread_rules(
(libc::SYS_unlinkat, vec![]),
(libc::SYS_write, vec![]),
(libc::SYS_writev, vec![]),
#[cfg(debug_assertions)]
(libc::SYS_fcntl, vec![]),
(libc::SYS_getcwd, vec![]),
])