// Copyright 2017 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. //! Implements virtio devices, queues, and transport mechanisms. mod balloon; mod block; mod descriptor_utils; mod input; mod interrupt; mod net; mod p9; mod pmem; mod queue; mod rng; #[cfg(feature = "tpm")] mod tpm; mod virtio_device; mod virtio_pci_common_config; mod virtio_pci_device; mod wl; pub mod fs; #[cfg(feature = "gpu")] pub mod gpu; pub mod resource_bridge; pub mod vhost; pub use self::balloon::*; pub use self::block::*; pub use self::descriptor_utils::Error as DescriptorError; pub use self::descriptor_utils::*; #[cfg(feature = "gpu")] pub use self::gpu::*; pub use self::input::*; pub use self::interrupt::*; pub use self::net::*; pub use self::p9::*; pub use self::pmem::*; pub use self::queue::*; pub use self::rng::*; #[cfg(feature = "tpm")] pub use self::tpm::*; pub use self::virtio_device::*; pub use self::virtio_pci_device::*; pub use self::wl::*; use std::cmp; use std::convert::TryFrom; const DEVICE_RESET: u32 = 0x0; const DEVICE_ACKNOWLEDGE: u32 = 0x01; const DEVICE_DRIVER: u32 = 0x02; const DEVICE_DRIVER_OK: u32 = 0x04; const DEVICE_FEATURES_OK: u32 = 0x08; const DEVICE_FAILED: u32 = 0x80; // Types taken from linux/virtio_ids.h const TYPE_NET: u32 = 1; const TYPE_BLOCK: u32 = 2; const TYPE_CONSOLE: u32 = 3; const TYPE_RNG: u32 = 4; const TYPE_BALLOON: u32 = 5; const TYPE_RPMSG: u32 = 7; const TYPE_SCSI: u32 = 8; const TYPE_9P: u32 = 9; const TYPE_RPROC_SERIAL: u32 = 11; const TYPE_CAIF: u32 = 12; const TYPE_GPU: u32 = 16; const TYPE_INPUT: u32 = 18; const TYPE_VSOCK: u32 = 19; const TYPE_CRYPTO: u32 = 20; const TYPE_IOMMU: u32 = 23; const TYPE_FS: u32 = 26; const TYPE_PMEM: u32 = 27; // Additional types invented by crosvm const MAX_VIRTIO_DEVICE_ID: u32 = 63; const TYPE_WL: u32 = MAX_VIRTIO_DEVICE_ID; const TYPE_TPM: u32 = MAX_VIRTIO_DEVICE_ID - 1; const VIRTIO_F_VERSION_1: u32 = 32; const INTERRUPT_STATUS_USED_RING: u32 = 0x1; const INTERRUPT_STATUS_CONFIG_CHANGED: u32 = 0x2; const VIRTIO_MSI_NO_VECTOR: u16 = 0xffff; /// Offset from the base MMIO address of a virtio device used by the guest to notify the device of /// queue events. pub const NOTIFY_REG_OFFSET: u32 = 0x50; /// Returns a string representation of the given virtio device type number. pub fn type_to_str(type_: u32) -> Option<&'static str> { Some(match type_ { TYPE_NET => "net", TYPE_BLOCK => "block", TYPE_CONSOLE => "console", TYPE_RNG => "rng", TYPE_BALLOON => "balloon", TYPE_RPMSG => "rpmsg", TYPE_SCSI => "scsi", TYPE_9P => "9p", TYPE_RPROC_SERIAL => "rproc-serial", TYPE_CAIF => "caif", TYPE_INPUT => "input", TYPE_GPU => "gpu", TYPE_VSOCK => "vsock", TYPE_CRYPTO => "crypto", TYPE_IOMMU => "iommu", TYPE_FS => "fs", TYPE_PMEM => "pmem", TYPE_WL => "wl", TYPE_TPM => "tpm", _ => return None, }) } /// Copy virtio device configuration data from a subslice of `src` to a subslice of `dst`. /// Unlike std::slice::copy_from_slice(), this function copies as much as possible within /// the common subset of the two slices, truncating the requested range instead of /// panicking if the slices do not match in size. /// /// `dst_offset` and `src_offset` specify the starting indexes of the `dst` and `src` /// slices, respectively; if either index is out of bounds, this function is a no-op /// rather than panicking. This makes it safe to call with arbitrary user-controlled /// inputs. pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) { if let Ok(dst_offset) = usize::try_from(dst_offset) { if let Ok(src_offset) = usize::try_from(src_offset) { if let Some(dst_slice) = dst.get_mut(dst_offset..) { if let Some(src_slice) = src.get(src_offset..) { let len = cmp::min(dst_slice.len(), src_slice.len()); let dst_subslice = &mut dst_slice[0..len]; let src_subslice = &src_slice[0..len]; dst_subslice.copy_from_slice(src_subslice); } } } } }