• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Implements virtio devices, queues, and transport mechanisms.
6 
7 mod async_utils;
8 mod balloon;
9 mod descriptor_utils;
10 mod input;
11 mod interrupt;
12 mod iommu;
13 mod p9;
14 mod pmem;
15 mod queue;
16 mod rng;
17 #[cfg(feature = "tpm")]
18 mod tpm;
19 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
20 mod video;
21 mod virtio_device;
22 mod virtio_pci_common_config;
23 mod virtio_pci_device;
24 pub mod wl;
25 
26 pub mod block;
27 pub mod console;
28 pub mod fs;
29 #[cfg(feature = "gpu")]
30 pub mod gpu;
31 pub mod net;
32 pub mod resource_bridge;
33 #[cfg(feature = "audio")]
34 pub mod snd;
35 pub mod vhost;
36 
37 pub use self::balloon::*;
38 pub use self::block::*;
39 pub use self::console::*;
40 pub use self::descriptor_utils::Error as DescriptorError;
41 pub use self::descriptor_utils::*;
42 #[cfg(feature = "gpu")]
43 pub use self::gpu::*;
44 pub use self::input::*;
45 pub use self::interrupt::*;
46 pub use self::iommu::*;
47 pub use self::net::*;
48 pub use self::p9::*;
49 pub use self::pmem::*;
50 pub use self::queue::*;
51 pub use self::rng::*;
52 #[cfg(feature = "audio")]
53 pub use self::snd::*;
54 #[cfg(feature = "tpm")]
55 pub use self::tpm::*;
56 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
57 pub use self::video::*;
58 pub use self::virtio_device::*;
59 pub use self::virtio_pci_device::*;
60 pub use self::wl::*;
61 
62 use std::cmp;
63 use std::convert::TryFrom;
64 
65 use hypervisor::ProtectionType;
66 use virtio_sys::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
67 
68 const DEVICE_RESET: u32 = 0x0;
69 const DEVICE_ACKNOWLEDGE: u32 = 0x01;
70 const DEVICE_DRIVER: u32 = 0x02;
71 const DEVICE_DRIVER_OK: u32 = 0x04;
72 const DEVICE_FEATURES_OK: u32 = 0x08;
73 const DEVICE_FAILED: u32 = 0x80;
74 
75 // Types taken from linux/virtio_ids.h
76 const TYPE_NET: u32 = 1;
77 const TYPE_BLOCK: u32 = 2;
78 const TYPE_CONSOLE: u32 = 3;
79 const TYPE_RNG: u32 = 4;
80 const TYPE_BALLOON: u32 = 5;
81 const TYPE_RPMSG: u32 = 7;
82 const TYPE_SCSI: u32 = 8;
83 const TYPE_9P: u32 = 9;
84 const TYPE_RPROC_SERIAL: u32 = 11;
85 const TYPE_CAIF: u32 = 12;
86 const TYPE_GPU: u32 = 16;
87 const TYPE_INPUT: u32 = 18;
88 const TYPE_VSOCK: u32 = 19;
89 const TYPE_CRYPTO: u32 = 20;
90 const TYPE_IOMMU: u32 = 23;
91 const TYPE_SOUND: u32 = 25;
92 const TYPE_FS: u32 = 26;
93 const TYPE_PMEM: u32 = 27;
94 const TYPE_MAC80211_HWSIM: u32 = 29;
95 const TYPE_VIDEO_ENC: u32 = 30;
96 const TYPE_VIDEO_DEC: u32 = 31;
97 // Additional types invented by crosvm
98 const MAX_VIRTIO_DEVICE_ID: u32 = 63;
99 const TYPE_WL: u32 = MAX_VIRTIO_DEVICE_ID;
100 const TYPE_TPM: u32 = MAX_VIRTIO_DEVICE_ID - 1;
101 // TODO(abhishekbh): Fix this after this device is accepted upstream.
102 const TYPE_VHOST_USER: u32 = MAX_VIRTIO_DEVICE_ID - 2;
103 
104 pub const VIRTIO_F_VERSION_1: u32 = 32;
105 pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
106 
107 const INTERRUPT_STATUS_USED_RING: u32 = 0x1;
108 const INTERRUPT_STATUS_CONFIG_CHANGED: u32 = 0x2;
109 
110 const VIRTIO_MSI_NO_VECTOR: u16 = 0xffff;
111 
112 /// Offset from the base MMIO address of a virtio device used by the guest to notify the device of
113 /// queue events.
114 pub const NOTIFY_REG_OFFSET: u32 = 0x50;
115 
116 /// Returns a string representation of the given virtio device type number.
type_to_str(type_: u32) -> Option<&'static str>117 pub fn type_to_str(type_: u32) -> Option<&'static str> {
118     Some(match type_ {
119         TYPE_NET => "net",
120         TYPE_BLOCK => "block",
121         TYPE_CONSOLE => "console",
122         TYPE_RNG => "rng",
123         TYPE_BALLOON => "balloon",
124         TYPE_RPMSG => "rpmsg",
125         TYPE_SCSI => "scsi",
126         TYPE_9P => "9p",
127         TYPE_RPROC_SERIAL => "rproc-serial",
128         TYPE_CAIF => "caif",
129         TYPE_INPUT => "input",
130         TYPE_GPU => "gpu",
131         TYPE_VSOCK => "vsock",
132         TYPE_CRYPTO => "crypto",
133         TYPE_IOMMU => "iommu",
134         TYPE_VHOST_USER => "vhost-user",
135         TYPE_SOUND => "snd",
136         TYPE_FS => "fs",
137         TYPE_PMEM => "pmem",
138         TYPE_WL => "wl",
139         TYPE_TPM => "tpm",
140         TYPE_VIDEO_DEC => "video-decoder",
141         TYPE_VIDEO_ENC => "video-encoder",
142         _ => return None,
143     })
144 }
145 
146 /// Copy virtio device configuration data from a subslice of `src` to a subslice of `dst`.
147 /// Unlike std::slice::copy_from_slice(), this function copies as much as possible within
148 /// the common subset of the two slices, truncating the requested range instead of
149 /// panicking if the slices do not match in size.
150 ///
151 /// `dst_offset` and `src_offset` specify the starting indexes of the `dst` and `src`
152 /// slices, respectively; if either index is out of bounds, this function is a no-op
153 /// rather than panicking.  This makes it safe to call with arbitrary user-controlled
154 /// inputs.
copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64)155 pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) {
156     if let Ok(dst_offset) = usize::try_from(dst_offset) {
157         if let Ok(src_offset) = usize::try_from(src_offset) {
158             if let Some(dst_slice) = dst.get_mut(dst_offset..) {
159                 if let Some(src_slice) = src.get(src_offset..) {
160                     let len = cmp::min(dst_slice.len(), src_slice.len());
161                     let dst_subslice = &mut dst_slice[0..len];
162                     let src_subslice = &src_slice[0..len];
163                     dst_subslice.copy_from_slice(src_subslice);
164                 }
165             }
166         }
167     }
168 }
169 
170 /// Returns the set of reserved base features common to all virtio devices.
base_features(protected_vm: ProtectionType) -> u64171 pub fn base_features(protected_vm: ProtectionType) -> u64 {
172     let mut features: u64 = 1 << VIRTIO_F_VERSION_1 | 1 << VIRTIO_RING_F_EVENT_IDX;
173 
174     if protected_vm != ProtectionType::Unprotected {
175         features |= 1 << VIRTIO_F_ACCESS_PLATFORM;
176     }
177 
178     features
179 }
180