1 // Copyright 2023 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 //! Virtqueue descriptor chain abstraction 6 7 #![deny(missing_docs)] 8 9 use anyhow::bail; 10 use anyhow::Context; 11 use anyhow::Result; 12 use base::trace; 13 use cros_async::MemRegion; 14 use smallvec::SmallVec; 15 use vm_memory::GuestAddress; 16 use vm_memory::GuestMemory; 17 18 use crate::virtio::descriptor_utils::Reader; 19 use crate::virtio::descriptor_utils::Writer; 20 21 /// Virtio flag indicating there is a next descriptor in descriptor chain 22 pub const VIRTQ_DESC_F_NEXT: u16 = 0x1; 23 /// Virtio flag indicating descriptor is write-only 24 pub const VIRTQ_DESC_F_WRITE: u16 = 0x2; 25 26 /// Packed virtqueue flags 27 pub const VIRTQ_DESC_F_AVAIL: u16 = 0x80; 28 pub const VIRTQ_DESC_F_USED: u16 = 0x8000; 29 30 /// Type of access allowed for a single virtio descriptor within a descriptor chain. 31 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 32 pub enum DescriptorAccess { 33 /// Descriptor is readable by the device (written by the driver before putting the descriptor 34 /// chain on the available queue). 35 DeviceRead, 36 /// Descriptor is writable by the device (read by the driver after the device puts the 37 /// descriptor chain on the used queue). 38 DeviceWrite, 39 } 40 41 /// A virtio descriptor chain. 42 /// 43 /// This is a low-level representation of the memory regions in a descriptor chain. Most code should 44 /// use [`virtio::Reader`](crate::virtio::Reader) and [`virtio::Writer`](crate::virtio::Writer) 45 /// rather than working with `DescriptorChain` memory regions directly. 46 pub struct DescriptorChain { 47 mem: GuestMemory, 48 49 /// Index into the descriptor table. 50 index: u16, 51 52 /// The readable memory regions that make up the descriptor chain. 53 pub reader: Reader, 54 55 /// The writable memory regions that make up the descriptor chain. 56 pub writer: Writer, 57 58 /// The descriptor chain id(only if it is a packed virtqueue descriptor chain) 59 pub id: Option<u16>, 60 61 /// Number of descriptor in descriptor chain 62 pub count: u16, 63 } 64 65 impl DescriptorChain { 66 /// Read all descriptors from `chain` into a new `DescriptorChain` instance. 67 /// 68 /// This function validates the following properties of the descriptor chain: 69 /// * The chain contains at least one descriptor. 70 /// * Each descriptor has a non-zero length. 71 /// * Each descriptor's memory falls entirely within a contiguous region of `mem`. 72 /// * The total length of the descriptor chain data is representable in `u32`. 73 /// 74 /// If these properties do not hold, `Err` will be returned. 75 /// 76 /// # Arguments 77 /// 78 /// * `chain` - Iterator that will be walked to retrieve all of the descriptors in the chain. 79 /// * `mem` - The [`GuestMemory`] backing the descriptor table and descriptor memory regions. 80 /// * `index` - The index of the first descriptor in the chain. new( mut chain: impl DescriptorChainIter, mem: &GuestMemory, index: u16, ) -> Result<DescriptorChain>81 pub fn new( 82 mut chain: impl DescriptorChainIter, 83 mem: &GuestMemory, 84 index: u16, 85 ) -> Result<DescriptorChain> { 86 let mut readable_regions = SmallVec::new(); 87 let mut writable_regions = SmallVec::new(); 88 89 // If `writable` is true, a writable descriptor has already been encountered. 90 // Valid descriptor chains must consist of readable descriptors followed by writable 91 // descriptors. 92 let mut writable = false; 93 94 while let Some(desc) = chain.next()? { 95 if desc.len == 0 { 96 trace!("zero-length descriptor at index {index}"); 97 continue; 98 } 99 100 let region = MemRegion { 101 offset: desc.address, 102 len: desc.len as usize, 103 }; 104 105 match desc.access { 106 DescriptorAccess::DeviceRead => { 107 if writable { 108 bail!("invalid device-readable descriptor following writable descriptors"); 109 } 110 readable_regions.push(region); 111 } 112 DescriptorAccess::DeviceWrite => { 113 writable = true; 114 writable_regions.push(region); 115 } 116 } 117 } 118 119 let count = chain.count(); 120 let id = chain.id(); 121 122 Self::validate_mem_regions(mem, &readable_regions, &writable_regions) 123 .context("invalid descriptor chain memory regions")?; 124 125 trace!( 126 "Descriptor chain created, index:{index}, count:{count}, buffer id:{:?}, readable:{}, writable:{}", 127 id, 128 readable_regions.len(), 129 writable_regions.len() 130 ); 131 132 let reader = Reader::new_from_regions(mem, readable_regions); 133 let writer = Writer::new_from_regions(mem, writable_regions); 134 135 let desc_chain = DescriptorChain { 136 mem: mem.clone(), 137 index, 138 reader, 139 writer, 140 id, 141 count, 142 }; 143 144 Ok(desc_chain) 145 } 146 validate_mem_regions( mem: &GuestMemory, readable_regions: &[MemRegion], writable_regions: &[MemRegion], ) -> Result<()>147 fn validate_mem_regions( 148 mem: &GuestMemory, 149 readable_regions: &[MemRegion], 150 writable_regions: &[MemRegion], 151 ) -> Result<()> { 152 let mut total_len: u32 = 0; 153 for r in readable_regions.iter().chain(writable_regions.iter()) { 154 // This cast is safe because the virtio descriptor length field is u32. 155 let len = r.len as u32; 156 157 // Check that all the regions are totally contained in GuestMemory. 158 if !mem.is_valid_range(GuestAddress(r.offset), len.into()) { 159 bail!( 160 "descriptor address range out of bounds: addr={:#x} len={:#x}", 161 r.offset, 162 r.len 163 ); 164 } 165 166 // Verify that summing the descriptor sizes does not overflow. 167 // This can happen if a driver tricks a device into reading/writing more data than 168 // fits in a `u32`. 169 total_len = total_len 170 .checked_add(len) 171 .context("descriptor chain length overflow")?; 172 } 173 174 if total_len == 0 { 175 bail!("invalid zero-length descriptor chain"); 176 } 177 178 Ok(()) 179 } 180 181 /// Returns a reference to the [`GuestMemory`] instance. mem(&self) -> &GuestMemory182 pub fn mem(&self) -> &GuestMemory { 183 &self.mem 184 } 185 186 /// Returns the index of the first descriptor in the chain. index(&self) -> u16187 pub fn index(&self) -> u16 { 188 self.index 189 } 190 } 191 192 /// A single descriptor within a [`DescriptorChain`]. 193 pub struct Descriptor { 194 /// Guest memory address of this descriptor. 195 /// If IOMMU is enabled, this is an IOVA, which must be translated via the IOMMU to get a 196 /// guest physical address. 197 pub address: u64, 198 199 /// Length of the descriptor in bytes. 200 pub len: u32, 201 202 /// Whether this descriptor should be treated as writable or readable by the device. 203 pub access: DescriptorAccess, 204 } 205 206 /// Iterator over the descriptors of a descriptor chain. 207 pub trait DescriptorChainIter { 208 /// Return the next descriptor in the chain, or `None` if there are no more descriptors. next(&mut self) -> Result<Option<Descriptor>>209 fn next(&mut self) -> Result<Option<Descriptor>>; 210 211 /// Return the number of descriptor has been iterated in the chain count(&self) -> u16212 fn count(&self) -> u16; 213 214 /// Return Packed descriptor chain buffer id if iterator reaches end, otherwise return None 215 /// SplitDescriptorChainIter should return None. id(&self) -> Option<u16>216 fn id(&self) -> Option<u16>; 217 } 218