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