cdev.rs0.00%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
use std::fmt::Debug;16
use std::fs::{File, OpenOptions};17
use std::mem::size_of;18
use std::os::fd::AsRawFd;19
use std::path::Path;20
use std::sync::Arc;21
22
use snafu::ResultExt;23
24
use crate::sys::vfio::{25
VfioDeviceAttachIommufdPt, VfioDeviceBindIommufd, VfioDeviceDetachIommufdPt,26
vfio_device_attach_iommufd_pt, vfio_device_bind_iommufd, vfio_device_detach_iommufd_pt,27
};28
use crate::vfio::device::Device;29
use crate::vfio::iommu::Ioas;30
use crate::vfio::{Result, error};31
32
#[derive(Debug)]33
pub struct Cdev {34
fd: File,35
ioas: Option<Arc<Ioas>>,36
}37
38
impl Cdev {39
pub fn new(path: impl AsRef<Path>) -> Result<Self> {40
let fd = OpenOptions::new()41
.read(true)42
.write(true)43
.open(&path)44
.context(error::AccessDevice {45
path: path.as_ref(),46
})?;47
Ok(Cdev { fd, ioas: None })48
}49
}50
51
impl Cdev {52
pub fn attach_iommu_ioas(&mut self, ioas: Arc<Ioas>) -> Result<()> {53
let bind = VfioDeviceBindIommufd {54
argsz: size_of::<VfioDeviceBindIommufd>() as u32,55
iommufd: ioas.iommu.fd.as_raw_fd(),56
..Default::default()57
};58
unsafe { vfio_device_bind_iommufd(&self.fd, &bind) }?;59
let attach = VfioDeviceAttachIommufdPt {60
argsz: size_of::<VfioDeviceAttachIommufdPt>() as u32,61
pt_id: ioas.id,62
..Default::default()63
};64
unsafe { vfio_device_attach_iommufd_pt(&self.fd, &attach) }?;65
self.ioas.replace(ioas);66
Ok(())67
}68
69
pub fn detach_iommu_ioas(&mut self) -> Result<()> {70
if self.ioas.is_none() {71
return Ok(());72
};73
let detach = VfioDeviceDetachIommufdPt {74
argsz: size_of::<VfioDeviceDetachIommufdPt>() as u32,75
flags: 0,76
};77
unsafe { vfio_device_detach_iommufd_pt(&self.fd, &detach) }?;78
self.ioas = None;79
Ok(())80
}81
}82
83
impl Device for Cdev {84
fn fd(&self) -> &File {85
&self.fd86
}87
}88
89
impl Drop for Cdev {90
fn drop(&mut self) {91
if let Err(e) = self.detach_iommu_ioas() {92
log::error!("Cdev-{}: detaching ioas: {e:?}", self.fd.as_raw_fd())93
}94
}95
}96