use std::fs::File;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use crate::ioctls::Result;
use crate::mshv_ioctls::{MSHV_GET_DEVICE_ATTR, MSHV_HAS_DEVICE_ATTR, MSHV_SET_DEVICE_ATTR};
use mshv_bindings::mshv_device_attr;
use vmm_sys_util::errno;
use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref};
#[derive(Debug)]
pub struct DeviceFd {
fd: File,
}
impl DeviceFd {
pub fn has_device_attr(&self, device_attr: &mshv_device_attr) -> Result<()> {
let ret = unsafe { ioctl_with_ref(self, MSHV_HAS_DEVICE_ATTR(), device_attr) };
if ret != 0 {
return Err(errno::Error::last().into());
}
Ok(())
}
pub fn set_device_attr(&self, device_attr: &mshv_device_attr) -> Result<()> {
let ret = unsafe { ioctl_with_ref(self, MSHV_SET_DEVICE_ATTR(), device_attr) };
if ret != 0 {
return Err(errno::Error::last().into());
}
Ok(())
}
pub fn get_device_attr(&self, device_attr: &mut mshv_device_attr) -> Result<()> {
let ret = unsafe { ioctl_with_mut_ref(self, MSHV_GET_DEVICE_ATTR(), device_attr) };
if ret != 0 {
return Err(errno::Error::last().into());
}
Ok(())
}
}
pub fn new_device(dev_fd: File) -> DeviceFd {
DeviceFd { fd: dev_fd }
}
impl AsRawFd for DeviceFd {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
impl FromRawFd for DeviceFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
DeviceFd {
fd: File::from_raw_fd(fd),
}
}
}
#[cfg(test)]
mod tests {
#[cfg(target_arch = "x86_64")]
use super::*;
#[cfg(target_arch = "x86_64")]
use crate::ioctls::system::Mshv;
#[cfg(target_arch = "x86_64")]
use mshv_bindings::{MSHV_DEV_TYPE_VFIO, MSHV_DEV_VFIO_FILE, MSHV_DEV_VFIO_FILE_ADD};
#[test]
#[cfg(target_arch = "x86_64")]
fn test_create_device() {
let mshv = Mshv::new().unwrap();
let vm = mshv.create_vm().unwrap();
vm.initialize().unwrap();
let mut device = mshv_bindings::mshv_create_device {
type_: MSHV_DEV_TYPE_VFIO,
fd: 0,
flags: 0,
};
let device = vm
.create_device(&mut device)
.expect("Cannot create MSHV device");
let raw_fd = unsafe { libc::dup(device.as_raw_fd()) };
assert!(raw_fd >= 0);
let device = unsafe { DeviceFd::from_raw_fd(raw_fd) };
let dist_attr = mshv_bindings::mshv_device_attr {
group: MSHV_DEV_VFIO_FILE,
attr: u64::from(MSHV_DEV_VFIO_FILE_ADD),
addr: 0,
flags: 0,
};
let mut dist_attr_mut = dist_attr;
assert!(device.has_device_attr(&dist_attr).is_ok());
assert!(device.get_device_attr(&mut dist_attr_mut).is_err());
assert!(device.set_device_attr(&dist_attr).is_err());
assert_eq!(errno::Error::last().errno(), 14);
}
}