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