pci: vfio: Mmap region based on capabilities

Now that vfio-ioctls correctly exposes the list of capabilities related
to each region, Cloud Hypervisor can decide to mmap a region based on
the presence or absence of MSIX_MAPPABLE. Instead of blindly mmap'ing
the region, we check if the MSI-X table or PBA is present on the BAR,
and if that's the case, we look for MSIX_MAPPABLE.
If MSIX_MAPPABLE is present, we can go ahead and mmap the entire region.
If MSIX_MAPPABLE is not present, we simply ignore the mmap'ing of this
region as it wouldn't be supported.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-10-29 14:09:26 +02:00
parent 436f3605e9
commit b11a8a5ab5
3 changed files with 23 additions and 9 deletions

2
Cargo.lock generated
View File

@ -1150,7 +1150,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio-ioctls" name = "vfio-ioctls"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#adbc9444387a9276e568fd2e31ed19bd0cd96611" source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#8f7f2210ebe71660938b05b2ed7eec9253478bc5"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"kvm-bindings", "kvm-bindings",

2
fuzz/Cargo.lock generated
View File

@ -705,7 +705,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio-ioctls" name = "vfio-ioctls"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#d51c1fad37be30c20385c55a217e2d90972ea31d" source = "git+https://github.com/rust-vmm/vfio-ioctls?branch=main#8f7f2210ebe71660938b05b2ed7eec9253478bc5"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"kvm-bindings", "kvm-bindings",

View File

@ -18,7 +18,7 @@ use std::ptr::null_mut;
use std::sync::{Arc, Barrier}; use std::sync::{Arc, Barrier};
use thiserror::Error; use thiserror::Error;
use vfio_bindings::bindings::vfio::*; use vfio_bindings::bindings::vfio::*;
use vfio_ioctls::{VfioContainer, VfioDevice, VfioIrq}; use vfio_ioctls::{VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap};
use vm_allocator::{AddressAllocator, SystemAllocator}; use vm_allocator::{AddressAllocator, SystemAllocator};
use vm_device::interrupt::{ use vm_device::interrupt::{
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
@ -1120,11 +1120,25 @@ impl VfioPciDevice {
prot |= libc::PROT_WRITE; prot |= libc::PROT_WRITE;
} }
// We ignore the mmap offset because we only support running on // Retrieve the list of capabilities found on the region
// host with VFIO newer than 4.16. That's because sparse mmap let caps = if region_flags & VFIO_REGION_INFO_FLAG_CAPS != 0 {
// has been deprecated and instead MSI-X regions can now be self.device.get_region_caps(region.index)
// entirely mapped. } else {
let (_, mmap_size) = self.device.get_region_mmap(region.index); Vec::new()
};
// Don't try to mmap the region if it contains MSI-X table or
// MSI-X PBA subregion, and if we couldn't find MSIX_MAPPABLE
// in the list of supported capabilities.
if let Some(msix) = self.common.interrupt.msix.as_ref() {
if (region.index == msix.cap.table_bir() || region.index == msix.cap.pba_bir())
&& !caps.contains(&VfioRegionInfoCap::MsixMappable)
{
continue;
}
}
let mmap_size = self.device.get_region_size(region.index);
let offset = self.device.get_region_offset(region.index); let offset = self.device.get_region_offset(region.index);
let host_addr = unsafe { let host_addr = unsafe {
@ -1139,7 +1153,7 @@ impl VfioPciDevice {
}; };
if host_addr == libc::MAP_FAILED { if host_addr == libc::MAP_FAILED {
warn!( error!(
"Could not mmap region index {}: {}", "Could not mmap region index {}: {}",
region.index, region.index,
io::Error::last_os_error() io::Error::last_os_error()