Alioth Code Coverage

cdev.rs0.00%

1// Copyright 2024 Google LLC
2//
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 at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// 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 and
13// limitations under the License.
14
15use std::fmt::Debug;
16use std::fs::{File, OpenOptions};
17use std::mem::size_of;
18use std::os::fd::AsRawFd;
19use std::path::Path;
20use std::sync::Arc;
21
22use snafu::ResultExt;
23
24use crate::sys::vfio::{
25 VfioDeviceAttachIommufdPt, VfioDeviceBindIommufd, VfioDeviceDetachIommufdPt,
26 vfio_device_attach_iommufd_pt, vfio_device_bind_iommufd, vfio_device_detach_iommufd_pt,
27};
28use crate::vfio::device::Device;
29use crate::vfio::iommu::Ioas;
30use crate::vfio::{Result, error};
31
32#[derive(Debug)]
33pub struct Cdev {
34 fd: File,
35 ioas: Option<Arc<Ioas>>,
36}
37
38impl 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
51impl 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
83impl Device for Cdev {
84 fn fd(&self) -> &File {
85 &self.fd
86 }
87}
88
89impl 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