virtio: fix dev_id initialization for virtio-pci and vfio device on aarch64 platform vfio: fix the problem of dma mapping failed syscall: add syscall "newfstatat" in x86_64-unknown-linux-gnu target kernel_config: update kernel config 5.10 on aarch64 platform machine/standard_vm: fix inappropriate file open permissions migration: fix an errors during the PL011 device state restore migration: fix an error during migration interface on aarch64 fix spelling errors in project (cherry picked from commit a12a13829fa5d788667e11b886c254760e6a4579)
229 lines
9.1 KiB
Diff
229 lines
9.1 KiB
Diff
From 023dde42b55a58c7a41293566e95a0fc94efa2c6 Mon Sep 17 00:00:00 2001
|
|
From: "Xinle.Guo" <guoxinle1@huawei.com>
|
|
Date: Thu, 19 Aug 2021 20:48:25 +0800
|
|
Subject: [PATCH 7/8] vfio: fix the problem of dma mapping failed
|
|
|
|
Failed to use libvirt to manager more than two vfio devices.
|
|
The reason is that creating a container for every vfio device,
|
|
the process stratovirt uses more than the memory locked limit.
|
|
|
|
Signed-off-by: Xinle.Guo <guoxinle1@huawei.com>
|
|
---
|
|
machine/src/lib.rs | 24 +++++++++++-------------
|
|
vfio/src/vfio_dev.rs | 25 +++++++++++++++----------
|
|
vfio/src/vfio_pci.rs | 31 ++++++++++++++++++-------------
|
|
3 files changed, 44 insertions(+), 36 deletions(-)
|
|
|
|
diff --git a/machine/src/lib.rs b/machine/src/lib.rs
|
|
index 9eb3039..8ba0ba3 100644
|
|
--- a/machine/src/lib.rs
|
|
+++ b/machine/src/lib.rs
|
|
@@ -121,7 +121,7 @@ use devices::legacy::FwCfgOps;
|
|
#[cfg(target_arch = "aarch64")]
|
|
use devices::InterruptController;
|
|
use hypervisor::KVM_FDS;
|
|
-use kvm_ioctls::{DeviceFd, VcpuFd};
|
|
+use kvm_ioctls::VcpuFd;
|
|
use machine_manager::config::{
|
|
get_pci_bdf, parse_balloon, parse_blk, parse_net, parse_rng_dev, parse_root_port, parse_vfio,
|
|
parse_virtconsole, parse_virtio_serial, parse_vsock, MachineMemConfig, PFlashConfig, PciBdf,
|
|
@@ -132,7 +132,7 @@ use machine_manager::machine::{KvmVmState, MachineInterface};
|
|
use migration::MigrationManager;
|
|
use util::loop_context::{EventNotifier, NotifierCallback, NotifierOperation};
|
|
use util::seccomp::{BpfRule, SeccompOpt, SyscallFilter};
|
|
-use vfio::vfio_pci::create_vfio_device;
|
|
+use vfio::vfio_pci::create_vfio_container;
|
|
use vfio::{VfioContainer, VfioPciDevice};
|
|
use virtio::{balloon_allow_list, Balloon, Block, Console, Rng, VirtioMmioDevice, VirtioPciDevice};
|
|
use vmm_sys_util::epoll::EventSet;
|
|
@@ -478,13 +478,8 @@ pub trait MachineOps {
|
|
&mut self,
|
|
vm_config: &VmConfig,
|
|
cfg_args: &str,
|
|
- dev_fd: Arc<DeviceFd>,
|
|
+ container: Arc<VfioContainer>,
|
|
) -> Result<()> {
|
|
- let sys_mem = self.get_sys_mem().clone();
|
|
- let container = Arc::new(
|
|
- VfioContainer::new(dev_fd, &sys_mem).chain_err(|| "Failed to create vfio container")?,
|
|
- );
|
|
-
|
|
let device_cfg: VfioConfig = parse_vfio(vm_config, cfg_args)?;
|
|
let path = "/sys/bus/pci/devices/".to_string() + &device_cfg.host;
|
|
let name = device_cfg.id;
|
|
@@ -543,10 +538,7 @@ pub trait MachineOps {
|
|
.chain_err(|| ErrorKind::AddDevErr("pflash".to_string()))?;
|
|
}
|
|
|
|
- // Create an emulated kvm device that is used for VFIO. It should be created only once.
|
|
- // See the kernel docs for `KVM_CREATE_DEVICE` to get more info.
|
|
- let vfio_dev = create_vfio_device().chain_err(|| "Failed to create kvm device for VFIO")?;
|
|
-
|
|
+ let mut container: Option<Arc<VfioContainer>> = None;
|
|
for dev in &cloned_vm_config.devices {
|
|
let cfg_args = dev.1.as_str();
|
|
match dev.0.as_str() {
|
|
@@ -581,7 +573,13 @@ pub trait MachineOps {
|
|
self.add_virtio_rng(vm_config, cfg_args)?;
|
|
}
|
|
"vfio-pci" => {
|
|
- self.add_vfio_device(&vm_config, cfg_args, vfio_dev.clone())?;
|
|
+ if container.is_none() {
|
|
+ container = Some(
|
|
+ create_vfio_container(self.get_sys_mem().clone())
|
|
+ .chain_err(|| "Failed to create vfio container")?,
|
|
+ );
|
|
+ }
|
|
+ self.add_vfio_device(&vm_config, cfg_args, container.clone().unwrap())?;
|
|
}
|
|
_ => {
|
|
bail!("Unsupported device: {:?}", dev.0.as_str());
|
|
diff --git a/vfio/src/vfio_dev.rs b/vfio/src/vfio_dev.rs
|
|
index 30f7d5a..93922ba 100644
|
|
--- a/vfio/src/vfio_dev.rs
|
|
+++ b/vfio/src/vfio_dev.rs
|
|
@@ -96,8 +96,8 @@ pub struct VfioMemoryRegion {
|
|
pub memory_size: u64,
|
|
// Host virtual address.
|
|
pub userspace_addr: u64,
|
|
- // No flags specified for now.
|
|
- flags_padding: u64,
|
|
+ // IOMMU mapped flag.
|
|
+ pub iommu_mapped: bool,
|
|
}
|
|
|
|
/// `VfioMemInfo` structure contains pinning pages information. If any pages need to be zapped from
|
|
@@ -131,7 +131,7 @@ impl VfioMemInfo {
|
|
guest_phys_addr,
|
|
memory_size,
|
|
userspace_addr,
|
|
- flags_padding: 0_u64,
|
|
+ iommu_mapped: false,
|
|
});
|
|
|
|
Ok(())
|
|
@@ -150,7 +150,7 @@ impl VfioMemInfo {
|
|
guest_phys_addr: fr.addr_range.base.raw_value(),
|
|
memory_size: fr.addr_range.size,
|
|
userspace_addr: hva + fr.offset_in_region,
|
|
- flags_padding: 0_u64,
|
|
+ iommu_mapped: false,
|
|
};
|
|
let mut mem_regions = self.regions.lock().unwrap();
|
|
for (index, mr) in mem_regions.iter().enumerate() {
|
|
@@ -378,9 +378,11 @@ impl VfioGroup {
|
|
return Err(ErrorKind::VfioIoctl("VFIO_GROUP_SET_CONTAINER".to_string(), ret).into());
|
|
}
|
|
|
|
- if let Err(e) = container.set_iommu(vfio::VFIO_TYPE1v2_IOMMU) {
|
|
- unsafe { ioctl_with_ref(&self.group, VFIO_GROUP_UNSET_CONTAINER(), &raw_fd) };
|
|
- return Err(e).chain_err(|| "Failed to set IOMMU");
|
|
+ if container.groups.lock().unwrap().is_empty() {
|
|
+ if let Err(e) = container.set_iommu(vfio::VFIO_TYPE1v2_IOMMU) {
|
|
+ unsafe { ioctl_with_ref(&self.group, VFIO_GROUP_UNSET_CONTAINER(), &raw_fd) };
|
|
+ return Err(e).chain_err(|| "Failed to set IOMMU");
|
|
+ }
|
|
}
|
|
|
|
if let Err(e) = container.kvm_device_add_group(&self.group.as_raw_fd()) {
|
|
@@ -473,15 +475,18 @@ impl VfioDevice {
|
|
group_id = n.parse::<u32>().chain_err(|| "Invalid iommu group id")?;
|
|
}
|
|
|
|
- let mut groups = container.groups.lock().unwrap();
|
|
- if let Some(g) = groups.get(&group_id) {
|
|
+ if let Some(g) = container.groups.lock().unwrap().get(&group_id) {
|
|
return Ok(g.clone());
|
|
}
|
|
let group = Arc::new(VfioGroup::new(group_id)?);
|
|
group
|
|
.connect_container(&container)
|
|
.chain_err(|| "Fail to connect container")?;
|
|
- groups.insert(group_id, group.clone());
|
|
+ container
|
|
+ .groups
|
|
+ .lock()
|
|
+ .unwrap()
|
|
+ .insert(group_id, group.clone());
|
|
|
|
Ok(group)
|
|
}
|
|
diff --git a/vfio/src/vfio_pci.rs b/vfio/src/vfio_pci.rs
|
|
index 5cc674a..7bec445 100644
|
|
--- a/vfio/src/vfio_pci.rs
|
|
+++ b/vfio/src/vfio_pci.rs
|
|
@@ -19,13 +19,12 @@ use std::sync::{Arc, Mutex, Weak};
|
|
use byteorder::{ByteOrder, LittleEndian};
|
|
use error_chain::ChainedError;
|
|
use kvm_bindings::{kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO};
|
|
-use kvm_ioctls::DeviceFd;
|
|
use vfio_bindings::bindings::vfio;
|
|
use vmm_sys_util::eventfd::EventFd;
|
|
use vmm_sys_util::ioctl::ioctl_with_mut_ref;
|
|
|
|
use super::errors::{ErrorKind, Result, ResultExt};
|
|
-use address_space::{FileBackend, GuestAddress, HostMemMapping, Region, RegionOps};
|
|
+use address_space::{AddressSpace, FileBackend, GuestAddress, HostMemMapping, Region, RegionOps};
|
|
use hypervisor::{MsiVector, KVM_FDS};
|
|
#[cfg(target_arch = "aarch64")]
|
|
use pci::config::SECONDARY_BUS_NUM;
|
|
@@ -380,7 +379,7 @@ impl VfioPciDevice {
|
|
.register_bar(i as usize, bar_region, vfio_bar.region_type, false, size);
|
|
}
|
|
|
|
- self.map_guest_memory()?;
|
|
+ self.do_dma_map()?;
|
|
|
|
Ok(())
|
|
}
|
|
@@ -569,14 +568,17 @@ impl VfioPciDevice {
|
|
}
|
|
|
|
/// Add all guest memory regions into IOMMU table.
|
|
- fn map_guest_memory(&mut self) -> Result<()> {
|
|
+ fn do_dma_map(&mut self) -> Result<()> {
|
|
let container = &self.vfio_device.container;
|
|
- let regions = container.vfio_mem_info.regions.lock().unwrap();
|
|
-
|
|
- for r in regions.iter() {
|
|
- container
|
|
- .vfio_dma_map(r.guest_phys_addr, r.memory_size, r.userspace_addr)
|
|
- .chain_err(|| "Failed to add guest memory region map into IOMMU table")?;
|
|
+ let mut regions = container.vfio_mem_info.regions.lock().unwrap();
|
|
+
|
|
+ for r in regions.iter_mut() {
|
|
+ if !r.iommu_mapped {
|
|
+ container
|
|
+ .vfio_dma_map(r.guest_phys_addr, r.memory_size, r.userspace_addr)
|
|
+ .chain_err(|| "Failed to add guest memory region map into IOMMU table")?;
|
|
+ r.iommu_mapped = true;
|
|
+ }
|
|
}
|
|
Ok(())
|
|
}
|
|
@@ -872,7 +874,7 @@ fn get_irq_rawfds(gsi_msi_routes: &[GsiMsiRoute]) -> Vec<RawFd> {
|
|
rawfds
|
|
}
|
|
|
|
-pub fn create_vfio_device() -> Result<Arc<DeviceFd>> {
|
|
+pub fn create_vfio_container(sys_mem: Arc<AddressSpace>) -> Result<Arc<VfioContainer>> {
|
|
let mut vfio_device = kvm_create_device {
|
|
type_: kvm_device_type_KVM_DEV_TYPE_VFIO,
|
|
fd: 0,
|
|
@@ -884,7 +886,10 @@ pub fn create_vfio_device() -> Result<Arc<DeviceFd>> {
|
|
.as_ref()
|
|
.unwrap()
|
|
.create_device(&mut vfio_device)
|
|
- .chain_err(|| "Failed to create VFIO type KVM device")?;
|
|
+ .chain_err(|| "Failed to create kvm device for VFIO")?;
|
|
|
|
- Ok(Arc::new(dev_fd))
|
|
+ Ok(Arc::new(
|
|
+ VfioContainer::new(Arc::new(dev_fd), &sys_mem)
|
|
+ .chain_err(|| "Failed to create vfio container")?,
|
|
+ ))
|
|
}
|
|
--
|
|
2.25.1
|
|
|