Skip to content
Open
15 changes: 14 additions & 1 deletion alioth-cli/src/boot/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use alioth::hv::{CocoSpec, HvSpec, Hypervisor};
use alioth::loader::{Executable, PayloadSpec};
use alioth::mem::{MemBackend, MemSpec};
#[cfg(target_os = "linux")]
use alioth::vfio::{VfioCdevSpec, VfioContainerSpec, VfioGroupSpec, VfioIoasSpec};
use alioth::vfio::{VfioCdevSpec, VfioContainerSpec, VfioGroupSpec, VfioIoasSpec, VfioUserSpec};
#[cfg(target_os = "linux")]
use alioth::virtio::DeviceId;
use alioth::virtio::dev::balloon::BalloonSpec;
Expand Down Expand Up @@ -182,6 +182,10 @@ pub struct BootArgs {
#[arg(long, help(help_text::<VfioContainerSpec>("Add a new VFIO container.")))]
vfio_container: Vec<String>,

#[cfg(target_os = "linux")]
#[arg(long, help(help_text::<VfioUserSpec>("Assign a vfio-user device to the guest.")))]
vfio_user: Vec<String>,

#[arg(long)]
#[arg(long, help(help_text::<BalloonSpec>("Add a VirtIO balloon device.")))]
balloon: Option<String>,
Expand Down Expand Up @@ -358,6 +362,11 @@ fn parse_args(mut args: BootArgs, objects: HashMap<&str, &str>) -> Result<VmSpec
let param = serde_aco::from_args(&arg, &objects).context(error::ParseArg { arg })?;
spec.vfio_group.push(param);
}
#[cfg(target_os = "linux")]
for arg in args.vfio_user {
let param = serde_aco::from_args(&arg, &objects).context(error::ParseArg { arg })?;
spec.vfio_user.push(param);
}

Ok(spec)
}
Expand Down Expand Up @@ -460,6 +469,10 @@ fn create<H: Hypervisor>(hypervisor: &H, spec: VmSpec) -> Result<Machine<H>, ali
for (index, cdev_spec) in spec.vfio_cdev.into_iter().enumerate() {
vm.add_vfio_cdev(format!("vfio-{index}").into(), cdev_spec)?;
}
#[cfg(target_os = "linux")]
for (index, user_spec) in spec.vfio_user.into_iter().enumerate() {
vm.add_vfio_user_dev(format!("vfio-user-{index}").into(), user_spec)?;
}

#[cfg(target_os = "linux")]
for container_spec in spec.vfio_container.into_iter() {
Expand Down
2 changes: 2 additions & 0 deletions alioth-cli/src/boot/boot_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ fn test_parse_args() {
container: Some("gpu_container".into()),
devices: vec!["0000:06:0d.0".into(), "0000:06:0d.1".into()],
}],
#[cfg(target_os = "linux")]
vfio_user: vec![],
};
assert_eq!(spec, want);
}
Expand Down
4 changes: 3 additions & 1 deletion alioth-cli/src/boot/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use alioth::device::console::ConsoleSpec;
use alioth::device::fw_cfg::FwCfgItemSpec;
use alioth::loader::PayloadSpec;
#[cfg(target_os = "linux")]
use alioth::vfio::{VfioCdevSpec, VfioContainerSpec, VfioGroupSpec, VfioIoasSpec};
use alioth::vfio::{VfioCdevSpec, VfioContainerSpec, VfioGroupSpec, VfioIoasSpec, VfioUserSpec};
use alioth::virtio::dev::balloon::BalloonSpec;
use alioth::virtio::dev::blk::BlkFileSpec;
use alioth::virtio::dev::entropy::EntropySpec;
Expand Down Expand Up @@ -119,4 +119,6 @@ pub struct VmSpec {
pub vfio_group: Vec<VfioGroupSpec>,
#[cfg(target_os = "linux")]
pub vfio_container: Vec<VfioContainerSpec>,
#[cfg(target_os = "linux")]
pub vfio_user: Vec<VfioUserSpec>,
}
5 changes: 3 additions & 2 deletions alioth/src/sys/linux/vfio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use bitfield::bitfield;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};

use crate::sys::ioctl::ioctl_io;
use crate::{
Expand Down Expand Up @@ -80,7 +81,7 @@ consts! {
}

#[repr(C)]
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, KnownLayout, Immutable, FromBytes, IntoBytes)]
pub struct VfioRegionInfo {
pub argsz: u32,
pub flags: VfioRegionInfoFlag,
Expand Down Expand Up @@ -116,7 +117,7 @@ consts! {
}

#[repr(C)]
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, KnownLayout, Immutable, FromBytes, IntoBytes)]
pub struct VfioIrqInfo {
pub argsz: u32,
pub flags: VfioIrqInfoFlag,
Expand Down
74 changes: 60 additions & 14 deletions alioth/src/vfio/cdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,26 @@
// limitations under the License.

use std::fmt::Debug;
use std::fs::{File, OpenOptions};
use std::fs::OpenOptions;
use std::mem::size_of;
use std::os::fd::AsRawFd;
use std::os::fd::{AsRawFd, BorrowedFd, OwnedFd};
use std::path::Path;
use std::sync::Arc;

use snafu::ResultExt;

use crate::sys::vfio::{
VfioDeviceAttachIommufdPt, VfioDeviceBindIommufd, VfioDeviceDetachIommufdPt,
vfio_device_attach_iommufd_pt, vfio_device_bind_iommufd, vfio_device_detach_iommufd_pt,
VfioDeviceAttachIommufdPt, VfioDeviceBindIommufd, VfioDeviceDetachIommufdPt, VfioDeviceInfo,
VfioIrqInfo, VfioRegionInfo, vfio_device_attach_iommufd_pt, vfio_device_bind_iommufd,
vfio_device_detach_iommufd_pt,
};
use crate::vfio::device::Device;
use crate::vfio::device::{Device, VfioIoDevice};
use crate::vfio::iommu::Ioas;
use crate::vfio::{Result, error};

#[derive(Debug)]
pub struct Cdev {
fd: File,
io_dev: VfioIoDevice,
ioas: Option<Arc<Ioas>>,
}

Expand All @@ -44,7 +45,8 @@ impl Cdev {
.context(error::AccessDevice {
path: path.as_ref(),
})?;
Ok(Cdev { fd, ioas: None })
let io_dev = VfioIoDevice::new(fd)?;
Ok(Cdev { io_dev, ioas: None })
}
}

Expand All @@ -55,41 +57,85 @@ impl Cdev {
iommufd: ioas.iommu.fd.as_raw_fd(),
..Default::default()
};
unsafe { vfio_device_bind_iommufd(&self.fd, &bind) }?;
unsafe { vfio_device_bind_iommufd(self.io_dev.fd(), &bind) }?;
let attach = VfioDeviceAttachIommufdPt {
argsz: size_of::<VfioDeviceAttachIommufdPt>() as u32,
pt_id: ioas.id,
..Default::default()
};
unsafe { vfio_device_attach_iommufd_pt(&self.fd, &attach) }?;
unsafe { vfio_device_attach_iommufd_pt(self.io_dev.fd(), &attach) }?;
self.ioas.replace(ioas);
Ok(())
}

pub fn detach_iommu_ioas(&mut self) -> Result<()> {
if self.ioas.is_none() {
return Ok(());
};
}
let detach = VfioDeviceDetachIommufdPt {
argsz: size_of::<VfioDeviceDetachIommufdPt>() as u32,
flags: 0,
};
unsafe { vfio_device_detach_iommufd_pt(&self.fd, &detach) }?;
unsafe { vfio_device_detach_iommufd_pt(self.io_dev.fd(), &detach) }?;
self.ioas = None;
Ok(())
}
}

impl Device for Cdev {
fn fd(&self) -> &File {
&self.fd
fn get_info(&self) -> Result<VfioDeviceInfo> {
self.io_dev.get_info()
}

fn get_region_info(&self, index: u32) -> Result<VfioRegionInfo> {
self.io_dev.get_region_info(index)
}

fn get_irq_info(&self, index: u32) -> Result<VfioIrqInfo> {
self.io_dev.get_irq_info(index)
}

fn reset(&self) -> Result<()> {
self.io_dev.reset()
}

fn set_irq_eventfd(
&self,
index: u32,
start: u32,
eventfds: &[Option<BorrowedFd<'_>>],
) -> Result<()> {
self.io_dev.set_irq_eventfd(index, start, eventfds)
}

fn disable_irq(&self, index: u32) -> Result<()> {
self.io_dev.disable_irq(index)
}

fn read_region(&self, region: &VfioRegionInfo, offset: u64, buf: &mut [u8]) -> Result<()> {
self.io_dev.read_region(region, offset, buf)
}

fn write_region(&self, region: &VfioRegionInfo, offset: u64, buf: &[u8]) -> Result<()> {
self.io_dev.write_region(region, offset, buf)
}

fn get_region_mmap_fd(&self, index: u32) -> Result<Option<OwnedFd>> {
self.io_dev.get_region_mmap_fd(index)
}

fn get_dma_buf_fd(&self, index: u32, offset: u64, size: usize) -> Result<OwnedFd> {
self.io_dev.get_dma_buf_fd(index, offset, size)
}
}

impl Drop for Cdev {
fn drop(&mut self) {
if let Err(e) = self.detach_iommu_ioas() {
log::error!("Cdev-{}: detaching ioas: {e:?}", self.fd.as_raw_fd())
log::error!(
"Cdev-{}: detaching ioas: {e:?}",
self.io_dev.fd().as_raw_fd()
)
}
}
}
2 changes: 1 addition & 1 deletion alioth/src/vfio/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use crate::vfio::{Result, error};
#[derive(Debug)]
pub struct Container {
fd: File,
iommu: Mutex<Option<VfioIommu>>,
pub(super) iommu: Mutex<Option<VfioIommu>>,
}

impl Container {
Expand Down
Loading
Loading