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 balloon;
8 mod block;
9 mod block_async;
10 mod console;
11 mod descriptor_utils;
12 mod input;
13 mod interrupt;
14 mod net;
15 mod p9;
16 mod pmem;
17 mod queue;
18 mod rng;
19 #[cfg(feature = "tpm")]
20 mod tpm;
21 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
22 mod video;
23 mod virtio_device;
24 mod virtio_pci_common_config;
25 mod virtio_pci_device;
26 mod wl;
27 
28 pub mod fs;
29 #[cfg(feature = "gpu")]
30 pub mod gpu;
31 pub mod resource_bridge;
32 #[cfg(feature = "audio")]
33 pub mod snd;
34 pub mod vhost;
35 
36 pub use self::balloon::*;
37 pub use self::block::*;
38 pub use self::block_async::*;
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::net::*;
47 pub use self::p9::*;
48 pub use self::pmem::*;
49 pub use self::queue::*;
50 pub use self::rng::*;
51 #[cfg(feature = "tpm")]
52 pub use self::tpm::*;
53 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
54 pub use self::video::*;
55 pub use self::virtio_device::*;
56 pub use self::virtio_pci_device::*;
57 pub use self::wl::*;
58 
59 use crate::ProtectionType;
60 use std::cmp;
61 use std::convert::TryFrom;
62 
63 const DEVICE_RESET: u32 = 0x0;
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 // Types taken from linux/virtio_ids.h
71 const TYPE_NET: u32 = 1;
72 const TYPE_BLOCK: u32 = 2;
73 const TYPE_CONSOLE: u32 = 3;
74 const TYPE_RNG: u32 = 4;
75 const TYPE_BALLOON: u32 = 5;
76 const TYPE_RPMSG: u32 = 7;
77 const TYPE_SCSI: u32 = 8;
78 const TYPE_9P: u32 = 9;
79 const TYPE_RPROC_SERIAL: u32 = 11;
80 const TYPE_CAIF: u32 = 12;
81 const TYPE_GPU: u32 = 16;
82 const TYPE_INPUT: u32 = 18;
83 const TYPE_VSOCK: u32 = 19;
84 const TYPE_CRYPTO: u32 = 20;
85 const TYPE_IOMMU: u32 = 23;
86 const TYPE_FS: u32 = 26;
87 const TYPE_PMEM: u32 = 27;
88 const TYPE_VIDEO_ENC: u32 = 30;
89 const TYPE_VIDEO_DEC: u32 = 31;
90 // Additional types invented by crosvm
91 const MAX_VIRTIO_DEVICE_ID: u32 = 63;
92 const TYPE_WL: u32 = MAX_VIRTIO_DEVICE_ID;
93 const TYPE_TPM: u32 = MAX_VIRTIO_DEVICE_ID - 1;
94 
95 pub const VIRTIO_F_VERSION_1: u32 = 32;
96 const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
97 
98 const INTERRUPT_STATUS_USED_RING: u32 = 0x1;
99 const INTERRUPT_STATUS_CONFIG_CHANGED: u32 = 0x2;
100 
101 const VIRTIO_MSI_NO_VECTOR: u16 = 0xffff;
102 
103 /// Offset from the base MMIO address of a virtio device used by the guest to notify the device of
104 /// queue events.
105 pub const NOTIFY_REG_OFFSET: u32 = 0x50;
106 
107 /// Returns a string representation of the given virtio device type number.
type_to_str(type_: u32) -> Option<&'static str>108 pub fn type_to_str(type_: u32) -> Option<&'static str> {
109     Some(match type_ {
110         TYPE_NET => "net",
111         TYPE_BLOCK => "block",
112         TYPE_CONSOLE => "console",
113         TYPE_RNG => "rng",
114         TYPE_BALLOON => "balloon",
115         TYPE_RPMSG => "rpmsg",
116         TYPE_SCSI => "scsi",
117         TYPE_9P => "9p",
118         TYPE_RPROC_SERIAL => "rproc-serial",
119         TYPE_CAIF => "caif",
120         TYPE_INPUT => "input",
121         TYPE_GPU => "gpu",
122         TYPE_VSOCK => "vsock",
123         TYPE_CRYPTO => "crypto",
124         TYPE_IOMMU => "iommu",
125         TYPE_FS => "fs",
126         TYPE_PMEM => "pmem",
127         TYPE_WL => "wl",
128         TYPE_TPM => "tpm",
129         TYPE_VIDEO_DEC => "video-decoder",
130         TYPE_VIDEO_ENC => "video-encoder",
131         _ => return None,
132     })
133 }
134 
135 /// Copy virtio device configuration data from a subslice of `src` to a subslice of `dst`.
136 /// Unlike std::slice::copy_from_slice(), this function copies as much as possible within
137 /// the common subset of the two slices, truncating the requested range instead of
138 /// panicking if the slices do not match in size.
139 ///
140 /// `dst_offset` and `src_offset` specify the starting indexes of the `dst` and `src`
141 /// slices, respectively; if either index is out of bounds, this function is a no-op
142 /// rather than panicking.  This makes it safe to call with arbitrary user-controlled
143 /// inputs.
copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64)144 pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) {
145     if let Ok(dst_offset) = usize::try_from(dst_offset) {
146         if let Ok(src_offset) = usize::try_from(src_offset) {
147             if let Some(dst_slice) = dst.get_mut(dst_offset..) {
148                 if let Some(src_slice) = src.get(src_offset..) {
149                     let len = cmp::min(dst_slice.len(), src_slice.len());
150                     let dst_subslice = &mut dst_slice[0..len];
151                     let src_subslice = &src_slice[0..len];
152                     dst_subslice.copy_from_slice(src_subslice);
153                 }
154             }
155         }
156     }
157 }
158 
159 /// Returns the set of reserved base features common to all virtio devices.
base_features(protected_vm: ProtectionType) -> u64160 pub fn base_features(protected_vm: ProtectionType) -> u64 {
161     let mut features: u64 = 1 << VIRTIO_F_VERSION_1;
162 
163     if protected_vm == ProtectionType::Protected {
164         features |= 1 << VIRTIO_F_ACCESS_PLATFORM;
165     }
166 
167     features
168 }
169