1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // 3 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE-BSD-3-Clause file. 6 // 7 // Copyright © 2019 Intel Corporation 8 // 9 // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 10 11 //! Implements virtio devices, queues, and transport mechanisms. 12 13 #[macro_use] 14 extern crate event_monitor; 15 #[macro_use] 16 extern crate log; 17 18 use std::io; 19 20 use serde::{Deserialize, Serialize}; 21 use thiserror::Error; 22 23 #[macro_use] 24 mod device; 25 pub mod balloon; 26 pub mod block; 27 mod console; 28 pub mod epoll_helper; 29 mod iommu; 30 pub mod mem; 31 pub mod net; 32 mod pmem; 33 mod rng; 34 pub mod seccomp_filters; 35 mod thread_helper; 36 pub mod transport; 37 pub mod vdpa; 38 pub mod vhost_user; 39 pub mod vsock; 40 pub mod watchdog; 41 42 use vm_memory::bitmap::AtomicBitmap; 43 use vm_memory::{GuestAddress, GuestMemory}; 44 use vm_virtio::VirtioDeviceType; 45 46 pub use self::balloon::Balloon; 47 pub use self::block::{Block, BlockState}; 48 pub use self::console::{Console, ConsoleResizer, Endpoint}; 49 pub use self::device::{ 50 DmaRemapping, UserspaceMapping, VirtioCommon, VirtioDevice, VirtioInterrupt, 51 VirtioInterruptType, VirtioSharedMemoryList, 52 }; 53 pub use self::epoll_helper::{ 54 EpollHelper, EpollHelperError, EpollHelperHandler, EPOLL_HELPER_EVENT_LAST, 55 }; 56 pub use self::iommu::{AccessPlatformMapping, Iommu, IommuMapping}; 57 pub use self::mem::{BlocksState, Mem, VirtioMemMappingSource, VIRTIO_MEM_ALIGN_SIZE}; 58 pub use self::net::{Net, NetCtrlEpollHandler}; 59 pub use self::pmem::Pmem; 60 pub use self::rng::Rng; 61 pub use self::vdpa::{Vdpa, VdpaDmaMapping}; 62 pub use self::vsock::Vsock; 63 pub use self::watchdog::Watchdog; 64 65 type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>; 66 type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>; 67 type MmapRegion = vm_memory::MmapRegion<AtomicBitmap>; 68 69 const DEVICE_INIT: u32 = 0x00; 70 const DEVICE_ACKNOWLEDGE: u32 = 0x01; 71 const DEVICE_DRIVER: u32 = 0x02; 72 const DEVICE_DRIVER_OK: u32 = 0x04; 73 const DEVICE_FEATURES_OK: u32 = 0x08; 74 const DEVICE_FAILED: u32 = 0x80; 75 76 const VIRTIO_F_RING_INDIRECT_DESC: u32 = 28; 77 const VIRTIO_F_RING_EVENT_IDX: u32 = 29; 78 const VIRTIO_F_VERSION_1: u32 = 32; 79 const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; 80 const VIRTIO_F_IN_ORDER: u32 = 35; 81 const VIRTIO_F_ORDER_PLATFORM: u32 = 36; 82 #[allow(dead_code)] 83 const VIRTIO_F_SR_IOV: u32 = 37; 84 const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; 85 86 #[derive(Error, Debug)] 87 pub enum ActivateError { 88 #[error("Failed to activate virtio device")] 89 BadActivate, 90 #[error("Failed to clone exit event fd: {0}")] 91 CloneExitEventFd(std::io::Error), 92 #[error("Failed to spawn thread: {0}")] 93 ThreadSpawn(std::io::Error), 94 #[error("Failed to setup vhost-user-fs daemon: {0}")] 95 VhostUserFsSetup(vhost_user::Error), 96 #[error("Failed to setup vhost-user daemon: {0}")] 97 VhostUserSetup(vhost_user::Error), 98 #[error("Failed to create seccomp filter: {0}")] 99 CreateSeccompFilter(seccompiler::Error), 100 #[error("Failed to create rate limiter: {0}")] 101 CreateRateLimiter(std::io::Error), 102 #[error("Failed to activate the vDPA device: {0}")] 103 ActivateVdpa(vdpa::Error), 104 } 105 106 pub type ActivateResult = std::result::Result<(), ActivateError>; 107 108 pub type DeviceEventT = u16; 109 110 #[derive(Error, Debug)] 111 pub enum Error { 112 #[error("Failed to single used queue: {0}")] 113 FailedSignalingUsedQueue(io::Error), 114 #[error("I/O Error: {0}")] 115 IoError(io::Error), 116 #[error("Failed to update memory vhost-user: {0}")] 117 VhostUserUpdateMemory(vhost_user::Error), 118 #[error("Failed to add memory region vhost-user: {0}")] 119 VhostUserAddMemoryRegion(vhost_user::Error), 120 #[error("Failed to set shared memory region")] 121 SetShmRegionsNotSupported, 122 #[error("Failed to process net queue: {0}")] 123 NetQueuePair(::net_util::NetQueuePairError), 124 #[error("Failed to : {0}")] 125 QueueAddUsed(virtio_queue::Error), 126 #[error("Failed to : {0}")] 127 QueueIterator(virtio_queue::Error), 128 } 129 130 #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] 131 pub struct TokenBucketConfig { 132 pub size: u64, 133 pub one_time_burst: Option<u64>, 134 pub refill_time: u64, 135 } 136 137 #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] 138 #[serde(deny_unknown_fields)] 139 pub struct RateLimiterConfig { 140 pub bandwidth: Option<TokenBucketConfig>, 141 pub ops: Option<TokenBucketConfig>, 142 } 143 144 impl TryInto<rate_limiter::RateLimiter> for RateLimiterConfig { 145 type Error = io::Error; 146 147 fn try_into(self) -> std::result::Result<rate_limiter::RateLimiter, Self::Error> { 148 let bw = self.bandwidth.unwrap_or_default(); 149 let ops = self.ops.unwrap_or_default(); 150 rate_limiter::RateLimiter::new( 151 bw.size, 152 bw.one_time_burst.unwrap_or(0), 153 bw.refill_time, 154 ops.size, 155 ops.one_time_burst.unwrap_or(0), 156 ops.refill_time, 157 ) 158 } 159 } 160 161 /// Return the host virtual address corresponding to the given guest address range 162 /// 163 /// Convert an absolute address into an address space (GuestMemory) 164 /// to a host pointer and verify that the provided size define a valid 165 /// range within a single memory region. 166 /// Return None if it is out of bounds or if addr+size overlaps a single region. 167 pub fn get_host_address_range<M: GuestMemory + ?Sized>( 168 mem: &M, 169 addr: GuestAddress, 170 size: usize, 171 ) -> Option<*mut u8> { 172 if mem.check_range(addr, size) { 173 Some(mem.get_host_address(addr).unwrap()) 174 } else { 175 None 176 } 177 } 178