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 #![allow(clippy::significant_drop_in_scrutinee)] 14 15 #[macro_use] 16 extern crate event_monitor; 17 #[macro_use] 18 extern crate log; 19 20 use serde::{Deserialize, Serialize}; 21 use std::convert::TryInto; 22 use std::io; 23 use thiserror::Error; 24 25 #[macro_use] 26 mod device; 27 pub mod balloon; 28 pub mod block; 29 mod console; 30 pub mod epoll_helper; 31 mod iommu; 32 pub mod mem; 33 pub mod net; 34 mod pmem; 35 mod rng; 36 pub mod seccomp_filters; 37 mod thread_helper; 38 pub mod transport; 39 pub mod vdpa; 40 pub mod vhost_user; 41 pub mod vsock; 42 pub mod watchdog; 43 44 pub use self::balloon::*; 45 pub use self::block::*; 46 pub use self::console::*; 47 pub use self::device::*; 48 pub use self::epoll_helper::*; 49 pub use self::iommu::*; 50 pub use self::mem::*; 51 pub use self::net::*; 52 pub use self::pmem::*; 53 pub use self::rng::*; 54 pub use self::vdpa::*; 55 pub use self::vsock::*; 56 pub use self::watchdog::*; 57 use vm_memory::{bitmap::AtomicBitmap, GuestAddress, GuestMemory}; 58 use vm_virtio::VirtioDeviceType; 59 60 type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>; 61 type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>; 62 type MmapRegion = vm_memory::MmapRegion<AtomicBitmap>; 63 64 const DEVICE_INIT: u32 = 0x00; 65 const DEVICE_ACKNOWLEDGE: u32 = 0x01; 66 const DEVICE_DRIVER: u32 = 0x02; 67 const DEVICE_DRIVER_OK: u32 = 0x04; 68 const DEVICE_FEATURES_OK: u32 = 0x08; 69 const DEVICE_FAILED: u32 = 0x80; 70 71 const VIRTIO_F_RING_INDIRECT_DESC: u32 = 28; 72 const VIRTIO_F_RING_EVENT_IDX: u32 = 29; 73 const VIRTIO_F_VERSION_1: u32 = 32; 74 const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; 75 const VIRTIO_F_IN_ORDER: u32 = 35; 76 const VIRTIO_F_ORDER_PLATFORM: u32 = 36; 77 #[allow(dead_code)] 78 const VIRTIO_F_SR_IOV: u32 = 37; 79 const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; 80 81 #[derive(Error, Debug)] 82 pub enum ActivateError { 83 #[error("Failed to activate virtio device.")] 84 BadActivate, 85 #[error("Failed to clone exit event fd: {0}")] 86 CloneExitEventFd(std::io::Error), 87 #[error("Failed to spawn thread: {0}")] 88 ThreadSpawn(std::io::Error), 89 #[error("Failed to setup vhost-user-fs daemon: {0}")] 90 VhostUserFsSetup(vhost_user::Error), 91 #[error("Failed to setup vhost-user-blk daemon: {0}")] 92 VhostUserBlkSetup(vhost_user::Error), 93 #[error("Failed to create seccomp filter: {0}")] 94 CreateSeccompFilter(seccompiler::Error), 95 #[error("Failed to create rate limiter: {0}")] 96 CreateRateLimiter(std::io::Error), 97 #[error("Failed to activate the vDPA device: {0}")] 98 ActivateVdpa(vdpa::Error), 99 } 100 101 pub type ActivateResult = std::result::Result<(), ActivateError>; 102 103 pub type DeviceEventT = u16; 104 105 #[derive(Error, Debug)] 106 pub enum Error { 107 #[error("Failed to single used queue: {0}")] 108 FailedSignalingUsedQueue(io::Error), 109 #[error("I/O Error: {0}")] 110 IoError(io::Error), 111 #[error("Failed to update memory vhost-user: {0}")] 112 VhostUserUpdateMemory(vhost_user::Error), 113 #[error("Failed to add memory region vhost-user: {0}")] 114 VhostUserAddMemoryRegion(vhost_user::Error), 115 #[error("Failed to set shared memory region.")] 116 SetShmRegionsNotSupported, 117 #[error("Failed to process net queue: {0}")] 118 NetQueuePair(::net_util::NetQueuePairError), 119 #[error("Failed to : {0}")] 120 QueueAddUsed(virtio_queue::Error), 121 #[error("Failed to : {0}")] 122 QueueIterator(virtio_queue::Error), 123 } 124 125 #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] 126 pub struct TokenBucketConfig { 127 pub size: u64, 128 pub one_time_burst: Option<u64>, 129 pub refill_time: u64, 130 } 131 132 #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] 133 #[serde(deny_unknown_fields)] 134 pub struct RateLimiterConfig { 135 pub bandwidth: Option<TokenBucketConfig>, 136 pub ops: Option<TokenBucketConfig>, 137 } 138 139 impl TryInto<rate_limiter::RateLimiter> for RateLimiterConfig { 140 type Error = io::Error; 141 142 fn try_into(self) -> std::result::Result<rate_limiter::RateLimiter, Self::Error> { 143 let bw = self.bandwidth.unwrap_or_default(); 144 let ops = self.ops.unwrap_or_default(); 145 rate_limiter::RateLimiter::new( 146 bw.size, 147 bw.one_time_burst.unwrap_or(0), 148 bw.refill_time, 149 ops.size, 150 ops.one_time_burst.unwrap_or(0), 151 ops.refill_time, 152 ) 153 } 154 } 155 156 /// Convert an absolute address into an address space (GuestMemory) 157 /// to a host pointer and verify that the provided size define a valid 158 /// range within a single memory region. 159 /// Return None if it is out of bounds or if addr+size overlaps a single region. 160 pub fn get_host_address_range<M: GuestMemory + ?Sized>( 161 mem: &M, 162 addr: GuestAddress, 163 size: usize, 164 ) -> Option<*mut u8> { 165 if mem.check_range(addr, size) { 166 Some(mem.get_host_address(addr).unwrap()) 167 } else { 168 None 169 } 170 } 171