diff options
author | Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> | 2019-04-23 17:14:50 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-01 03:59:47 +0000 |
commit | 17b0daf88c97be0ace69d4b19b3352053668e96b (patch) | |
tree | 93c7de722eaa589bf45de3246b847bf3cfa6889a | |
parent | 71a6f0a790eb3f9a6fccbaf08aa915396a9d6749 (diff) | |
download | crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar.gz crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar.bz2 crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar.lz crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar.xz crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.tar.zst crosvm-17b0daf88c97be0ace69d4b19b3352053668e96b.zip |
vfio: Integrate VFIO device into pci device model
Create VFIO device and VFIO PCI device in create_devices() function, and intergrate it into PciRootBridge, so guest could see this vfio device. Add a vfio config parameter, this config point to passthrough or mdev device sysfs path. For passthrough case, first user unbind host device from its driver, then bind host device to vfio-pci. Like: echo 0000:00:02.0 > /sys/bus/pci/devices/0000:00:02.0/driver/unbind ech0 8086 1912 > /sys/bus/pci/drivers/vfio-pci/new_id Finally pass the sysfs to crosvm through --vfio=/sys/bus/pci/devices/0000:00:02.0 For mdev case, user create a mdev device through echo $UUID > mdev_type/create, then pass this mdev device to crosvm like --vfio=/sys/bus/pci/devices/0000:00:02.0/$UUID BUG=chromium:992270 TEST=none Change-Id: I0f59d6e93f62f9ab0727ad3a867d204f4ff6ad2d Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1581140 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
-rw-r--r-- | devices/src/pci/vfio_pci.rs | 3 | ||||
-rw-r--r-- | devices/src/vfio.rs | 17 | ||||
-rw-r--r-- | seccomp/x86_64/vfio_device.policy | 10 | ||||
-rw-r--r-- | src/crosvm.rs | 2 | ||||
-rw-r--r-- | src/linux.rs | 14 | ||||
-rw-r--r-- | src/main.rs | 19 |
6 files changed, 61 insertions, 4 deletions
diff --git a/devices/src/pci/vfio_pci.rs b/devices/src/pci/vfio_pci.rs index b5c5152..cdb253c 100644 --- a/devices/src/pci/vfio_pci.rs +++ b/devices/src/pci/vfio_pci.rs @@ -139,8 +139,7 @@ impl PciDevice for VfioPciDevice { } fn keep_fds(&self) -> Vec<RawFd> { - let fds = Vec::new(); - fds + self.device.keep_fds() } fn assign_irq( diff --git a/devices/src/vfio.rs b/devices/src/vfio.rs index b08414a..6a8c3ea 100644 --- a/devices/src/vfio.rs +++ b/devices/src/vfio.rs @@ -111,6 +111,7 @@ impl AsRawFd for VfioContainer { struct VfioGroup { group: File, + container: VfioContainer, } impl VfioGroup { @@ -163,7 +164,10 @@ impl VfioGroup { Self::kvm_device_add_group(vm, &group_file)?; - Ok(VfioGroup { group: group_file }) + Ok(VfioGroup { + group: group_file, + container, + }) } fn kvm_device_add_group(vm: &Vm, group: &File) -> Result<File, VfioError> { @@ -230,6 +234,7 @@ struct VfioRegion { /// Vfio device for exposing regions which could be read/write to kernel vfio device. pub struct VfioDevice { dev: File, + group: VfioGroup, regions: Vec<VfioRegion>, } @@ -254,6 +259,7 @@ impl VfioDevice { Ok(VfioDevice { dev: new_dev, + group, regions: dev_regions, }) } @@ -368,6 +374,15 @@ impl VfioDevice { ); } } + + /// get vfio device's fds which are passed into minijail process + pub fn keep_fds(&self) -> Vec<RawFd> { + let mut fds = Vec::new(); + fds.push(self.as_raw_fd()); + fds.push(self.group.as_raw_fd()); + fds.push(self.group.container.as_raw_fd()); + fds + } } impl AsRawFd for VfioDevice { diff --git a/seccomp/x86_64/vfio_device.policy b/seccomp/x86_64/vfio_device.policy new file mode 100644 index 0000000..8dd5961 --- /dev/null +++ b/seccomp/x86_64/vfio_device.policy @@ -0,0 +1,10 @@ +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +@include /usr/share/policy/crosvm/common_device.policy + +# VFIO_DEVICE_SET_IRQS, VFIO_IOMMU_MAP/UNMAP_DMA +ioctl: arg1 == 0x3B6E || arg1 == 0x3B71 || arg1 == 0x3B72 +readlink: 1 +pread64: 1 +pwrite64: 1 diff --git a/src/crosvm.rs b/src/crosvm.rs index bc39e7f..b7055df 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -109,6 +109,7 @@ pub struct Config { pub virtio_keyboard: Option<PathBuf>, pub virtio_input_evdevs: Vec<PathBuf>, pub split_irqchip: bool, + pub vfio: Option<PathBuf>, } impl Default for Config { @@ -153,6 +154,7 @@ impl Default for Config { virtio_keyboard: None, virtio_input_evdevs: Vec::new(), split_irqchip: false, + vfio: None, } } } diff --git a/src/linux.rs b/src/linux.rs index 58e0971..f2433f7 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -27,7 +27,10 @@ use libc::{self, c_int, gid_t, uid_t}; use audio_streams::DummyStreamSource; use devices::virtio::{self, VirtioDevice}; -use devices::{self, HostBackendDeviceProvider, PciDevice, VirtioPciDevice, XhciController}; +use devices::{ + self, HostBackendDeviceProvider, PciDevice, VfioDevice, VfioPciDevice, VirtioPciDevice, + XhciController, +}; use io_jail::{self, Minijail}; use kvm::*; use libcras::CrasClient; @@ -91,6 +94,7 @@ pub enum Error { CreateTimerFd(sys_util::Error), CreateTpmStorage(PathBuf, io::Error), CreateUsbProvider(devices::usb::host_backend::error::Error), + CreateVfioDevice(devices::vfio::VfioError), DeviceJail(io_jail::Error), DevicePivotRoot(io_jail::Error), Disk(io::Error), @@ -172,6 +176,7 @@ impl Display for Error { write!(f, "failed to create tpm storage dir {}: {}", p.display(), e) } CreateUsbProvider(e) => write!(f, "failed to create usb provider: {}", e), + CreateVfioDevice(e) => write!(f, "Failed to create vfio device {}", e), DeviceJail(e) => write!(f, "failed to jail device: {}", e), DevicePivotRoot(e) => write!(f, "failed to pivot root device: {}", e), Disk(e) => write!(f, "failed to load disk image: {}", e), @@ -979,6 +984,13 @@ fn create_devices( let usb_controller = Box::new(XhciController::new(mem.clone(), usb_provider)); pci_devices.push((usb_controller, simple_jail(&cfg, "xhci.policy")?)); + if cfg.vfio.is_some() { + let vfio_path = cfg.vfio.as_ref().unwrap().as_path(); + let vfiodevice = Box::new(VfioDevice::new(vfio_path, vm).map_err(Error::CreateVfioDevice)?); + let vfiopcidevice = Box::new(VfioPciDevice::new(vfiodevice)); + pci_devices.push((vfiopcidevice, simple_jail(&cfg, "vfio_device.policy")?)); + } + Ok(pci_devices) } diff --git a/src/main.rs b/src/main.rs index 75d08ae..a864833 100644 --- a/src/main.rs +++ b/src/main.rs @@ -685,6 +685,24 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: } cfg.executable_path = Some(Executable::Bios(PathBuf::from(value.unwrap().to_owned()))); } + "vfio" => { + let vfio_path = PathBuf::from(value.unwrap()); + if !vfio_path.exists() { + return Err(argument::Error::InvalidValue { + value: value.unwrap().to_owned(), + expected: "the vfio path does not exist", + }); + } + if !vfio_path.is_dir() { + return Err(argument::Error::InvalidValue { + value: value.unwrap().to_owned(), + expected: "the vfio path should be directory", + }); + } + + cfg.vfio = Some(vfio_path); + } + "help" => return Err(argument::Error::PrintHelp), _ => unreachable!(), } @@ -774,6 +792,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] Argument::flag("split-irqchip", "(EXPERIMENTAL) enable split-irqchip support"), Argument::value("bios", "PATH", "Path to BIOS/firmware ROM"), + Argument::value("vfio", "PATH", "Path to sysfs of pass through or mdev device"), Argument::short_flag('h', "help", "Print help message.")]; let mut cfg = Config::default(); |