1 // Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // Copyright (C) 2020-2021 Alibaba Cloud. All rights reserved. 3 // Copyright © 2019 Intel Corporation. 4 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style license that can be 6 // found in the LICENSE-BSD-3-Clause file. 7 // 8 // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 9 10 use std::mem::size_of; 11 use std::num::Wrapping; 12 use std::ops::Deref; 13 use std::sync::atomic::{fence, Ordering}; 14 15 use vm_memory::{Address, Bytes, GuestAddress, GuestMemory}; 16 17 use crate::defs::{ 18 DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR, 19 VIRTQ_AVAIL_ELEMENT_SIZE, VIRTQ_AVAIL_RING_HEADER_SIZE, VIRTQ_AVAIL_RING_META_SIZE, 20 VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_RING_HEADER_SIZE, VIRTQ_USED_RING_META_SIZE, 21 }; 22 use crate::{ 23 error, Descriptor, DescriptorChain, Error, QueueGuard, QueueOwnedT, QueueState, QueueT, 24 VirtqUsedElem, 25 }; 26 use virtio_bindings::bindings::virtio_ring::VRING_USED_F_NO_NOTIFY; 27 28 /// The maximum queue size as defined in the Virtio Spec. 29 pub const MAX_QUEUE_SIZE: u16 = 32768; 30 31 /// Struct to maintain information and manipulate a virtio queue. 32 /// 33 /// # Example 34 /// 35 /// ```rust 36 /// use virtio_queue::{Queue, QueueOwnedT, QueueT}; 37 /// use vm_memory::{Bytes, GuestAddress, GuestAddressSpace, GuestMemoryMmap}; 38 /// 39 /// let m = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 40 /// let mut queue = Queue::new(1024).unwrap(); 41 /// 42 /// // First, the driver sets up the queue; this set up is done via writes on the bus (PCI, MMIO). 43 /// queue.set_size(8); 44 /// queue.set_desc_table_address(Some(0x1000), None); 45 /// queue.set_avail_ring_address(Some(0x2000), None); 46 /// queue.set_used_ring_address(Some(0x3000), None); 47 /// queue.set_event_idx(true); 48 /// queue.set_ready(true); 49 /// // The user should check if the queue is valid before starting to use it. 50 /// assert!(queue.is_valid(&m)); 51 /// 52 /// // Here the driver would add entries in the available ring and then update the `idx` field of 53 /// // the available ring (address = 0x2000 + 2). 54 /// m.write_obj(3, GuestAddress(0x2002)); 55 /// 56 /// loop { 57 /// queue.disable_notification(&m).unwrap(); 58 /// 59 /// // Consume entries from the available ring. 60 /// while let Some(chain) = queue.iter(&m).unwrap().next() { 61 /// // Process the descriptor chain, and then add an entry in the used ring and optionally 62 /// // notify the driver. 63 /// queue.add_used(&m, chain.head_index(), 0x100).unwrap(); 64 /// 65 /// if queue.needs_notification(&m).unwrap() { 66 /// // Here we would notify the driver it has new entries in the used ring to consume. 67 /// } 68 /// } 69 /// if !queue.enable_notification(&m).unwrap() { 70 /// break; 71 /// } 72 /// } 73 /// 74 /// // We can reset the queue at some point. 75 /// queue.reset(); 76 /// // The queue should not be ready after reset. 77 /// assert!(!queue.ready()); 78 /// ``` 79 #[derive(Debug, Default, PartialEq, Eq)] 80 pub struct Queue { 81 /// The maximum size in elements offered by the device. 82 max_size: u16, 83 84 /// Tail position of the available ring. 85 next_avail: Wrapping<u16>, 86 87 /// Head position of the used ring. 88 next_used: Wrapping<u16>, 89 90 /// VIRTIO_F_RING_EVENT_IDX negotiated. 91 event_idx_enabled: bool, 92 93 /// The number of descriptor chains placed in the used ring via `add_used` 94 /// since the last time `needs_notification` was called on the associated queue. 95 num_added: Wrapping<u16>, 96 97 /// The queue size in elements the driver selected. 98 size: u16, 99 100 /// Indicates if the queue is finished with configuration. 101 ready: bool, 102 103 /// Guest physical address of the descriptor table. 104 desc_table: GuestAddress, 105 106 /// Guest physical address of the available ring. 107 avail_ring: GuestAddress, 108 109 /// Guest physical address of the used ring. 110 used_ring: GuestAddress, 111 } 112 113 impl Queue { 114 /// Equivalent of [`QueueT::set_size`] returning an error in case of invalid size. 115 /// 116 /// This should not be directly used, as the preferred method is part of the [`QueueT`] 117 /// interface. This is a convenience function for implementing save/restore capabilities. try_set_size(&mut self, size: u16) -> Result<(), Error>118 pub fn try_set_size(&mut self, size: u16) -> Result<(), Error> { 119 if size > self.max_size() || size == 0 || (size & (size - 1)) != 0 { 120 return Err(Error::InvalidSize); 121 } 122 self.size = size; 123 Ok(()) 124 } 125 126 /// Tries to set the descriptor table address. In case of an invalid value, the address is 127 /// not updated. 128 /// 129 /// This should not be directly used, as the preferred method is 130 /// [`QueueT::set_desc_table_address`]. This is a convenience function for implementing 131 /// save/restore capabilities. try_set_desc_table_address(&mut self, desc_table: GuestAddress) -> Result<(), Error>132 pub fn try_set_desc_table_address(&mut self, desc_table: GuestAddress) -> Result<(), Error> { 133 if desc_table.mask(0xf) != 0 { 134 return Err(Error::InvalidDescTableAlign); 135 } 136 self.desc_table = desc_table; 137 138 Ok(()) 139 } 140 141 /// Tries to update the available ring address. In case of an invalid value, the address is 142 /// not updated. 143 /// 144 /// This should not be directly used, as the preferred method is 145 /// [`QueueT::set_avail_ring_address`]. This is a convenience function for implementing 146 /// save/restore capabilities. try_set_avail_ring_address(&mut self, avail_ring: GuestAddress) -> Result<(), Error>147 pub fn try_set_avail_ring_address(&mut self, avail_ring: GuestAddress) -> Result<(), Error> { 148 if avail_ring.mask(0x1) != 0 { 149 return Err(Error::InvalidAvailRingAlign); 150 } 151 self.avail_ring = avail_ring; 152 Ok(()) 153 } 154 155 /// Tries to update the used ring address. In cae of an invalid value, the address is not 156 /// updated. 157 /// 158 /// This should not be directly used, as the preferred method is 159 /// [`QueueT::set_used_ring_address`]. This is a convenience function for implementing 160 /// save/restore capabilities. try_set_used_ring_address(&mut self, used_ring: GuestAddress) -> Result<(), Error>161 pub fn try_set_used_ring_address(&mut self, used_ring: GuestAddress) -> Result<(), Error> { 162 if used_ring.mask(0x3) != 0 { 163 return Err(Error::InvalidUsedRingAlign); 164 } 165 self.used_ring = used_ring; 166 Ok(()) 167 } 168 169 /// Returns the state of the `Queue`. 170 /// 171 /// This is useful for implementing save/restore capabilities. 172 /// The state does not have support for serialization, but this can be 173 /// added by VMMs locally through the use of a 174 /// [remote type](https://serde.rs/remote-derive.html). 175 /// 176 /// Alternatively, a version aware and serializable/deserializable QueueState 177 /// is available in the `virtio-queue-ser` crate. state(&self) -> QueueState178 pub fn state(&self) -> QueueState { 179 QueueState { 180 max_size: self.max_size, 181 next_avail: self.next_avail(), 182 next_used: self.next_used(), 183 event_idx_enabled: self.event_idx_enabled, 184 size: self.size, 185 ready: self.ready, 186 desc_table: self.desc_table(), 187 avail_ring: self.avail_ring(), 188 used_ring: self.used_ring(), 189 } 190 } 191 192 // Helper method that writes `val` to the `avail_event` field of the used ring, using 193 // the provided ordering. set_avail_event<M: GuestMemory>( &self, mem: &M, val: u16, order: Ordering, ) -> Result<(), Error>194 fn set_avail_event<M: GuestMemory>( 195 &self, 196 mem: &M, 197 val: u16, 198 order: Ordering, 199 ) -> Result<(), Error> { 200 // This can not overflow an u64 since it is working with relatively small numbers compared 201 // to u64::MAX. 202 let avail_event_offset = 203 VIRTQ_USED_RING_HEADER_SIZE + VIRTQ_USED_ELEMENT_SIZE * u64::from(self.size); 204 let addr = self 205 .used_ring 206 .checked_add(avail_event_offset) 207 .ok_or(Error::AddressOverflow)?; 208 209 mem.store(u16::to_le(val), addr, order) 210 .map_err(Error::GuestMemory) 211 } 212 213 // Set the value of the `flags` field of the used ring, applying the specified ordering. set_used_flags<M: GuestMemory>( &mut self, mem: &M, val: u16, order: Ordering, ) -> Result<(), Error>214 fn set_used_flags<M: GuestMemory>( 215 &mut self, 216 mem: &M, 217 val: u16, 218 order: Ordering, 219 ) -> Result<(), Error> { 220 mem.store(u16::to_le(val), self.used_ring, order) 221 .map_err(Error::GuestMemory) 222 } 223 224 // Write the appropriate values to enable or disable notifications from the driver. 225 // 226 // Every access in this method uses `Relaxed` ordering because a fence is added by the caller 227 // when appropriate. set_notification<M: GuestMemory>(&mut self, mem: &M, enable: bool) -> Result<(), Error>228 fn set_notification<M: GuestMemory>(&mut self, mem: &M, enable: bool) -> Result<(), Error> { 229 if enable { 230 if self.event_idx_enabled { 231 // We call `set_avail_event` using the `next_avail` value, instead of reading 232 // and using the current `avail_idx` to avoid missing notifications. More 233 // details in `enable_notification`. 234 self.set_avail_event(mem, self.next_avail.0, Ordering::Relaxed) 235 } else { 236 self.set_used_flags(mem, 0, Ordering::Relaxed) 237 } 238 } else if !self.event_idx_enabled { 239 self.set_used_flags(mem, VRING_USED_F_NO_NOTIFY as u16, Ordering::Relaxed) 240 } else { 241 // Notifications are effectively disabled by default after triggering once when 242 // `VIRTIO_F_EVENT_IDX` is negotiated, so we don't do anything in that case. 243 Ok(()) 244 } 245 } 246 247 // Return the value present in the used_event field of the avail ring. 248 // 249 // If the VIRTIO_F_EVENT_IDX feature bit is not negotiated, the flags field in the available 250 // ring offers a crude mechanism for the driver to inform the device that it doesn’t want 251 // interrupts when buffers are used. Otherwise virtq_avail.used_event is a more performant 252 // alternative where the driver specifies how far the device can progress before interrupting. 253 // 254 // Neither of these interrupt suppression methods are reliable, as they are not synchronized 255 // with the device, but they serve as useful optimizations. So we only ensure access to the 256 // virtq_avail.used_event is atomic, but do not need to synchronize with other memory accesses. used_event<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>257 fn used_event<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> { 258 // This can not overflow an u64 since it is working with relatively small numbers compared 259 // to u64::MAX. 260 let used_event_offset = 261 VIRTQ_AVAIL_RING_HEADER_SIZE + u64::from(self.size) * VIRTQ_AVAIL_ELEMENT_SIZE; 262 let used_event_addr = self 263 .avail_ring 264 .checked_add(used_event_offset) 265 .ok_or(Error::AddressOverflow)?; 266 267 mem.load(used_event_addr, order) 268 .map(u16::from_le) 269 .map(Wrapping) 270 .map_err(Error::GuestMemory) 271 } 272 } 273 274 impl<'a> QueueGuard<'a> for Queue { 275 type G = &'a mut Self; 276 } 277 278 impl QueueT for Queue { new(max_size: u16) -> Result<Self, Error>279 fn new(max_size: u16) -> Result<Self, Error> { 280 // We need to check that the max size is a power of 2 because we're setting this as the 281 // queue size, and the valid queue sizes are a power of 2 as per the specification. 282 if max_size == 0 || max_size > MAX_QUEUE_SIZE || (max_size & (max_size - 1)) != 0 { 283 return Err(Error::InvalidMaxSize); 284 } 285 Ok(Queue { 286 max_size, 287 size: max_size, 288 ready: false, 289 desc_table: GuestAddress(DEFAULT_DESC_TABLE_ADDR), 290 avail_ring: GuestAddress(DEFAULT_AVAIL_RING_ADDR), 291 used_ring: GuestAddress(DEFAULT_USED_RING_ADDR), 292 next_avail: Wrapping(0), 293 next_used: Wrapping(0), 294 event_idx_enabled: false, 295 num_added: Wrapping(0), 296 }) 297 } 298 is_valid<M: GuestMemory>(&self, mem: &M) -> bool299 fn is_valid<M: GuestMemory>(&self, mem: &M) -> bool { 300 let queue_size = self.size as u64; 301 let desc_table = self.desc_table; 302 // The multiplication can not overflow an u64 since we are multiplying an u16 with a 303 // small number. 304 let desc_table_size = size_of::<Descriptor>() as u64 * queue_size; 305 let avail_ring = self.avail_ring; 306 // The operations below can not overflow an u64 since they're working with relatively small 307 // numbers compared to u64::MAX. 308 let avail_ring_size = VIRTQ_AVAIL_RING_META_SIZE + VIRTQ_AVAIL_ELEMENT_SIZE * queue_size; 309 let used_ring = self.used_ring; 310 let used_ring_size = VIRTQ_USED_RING_META_SIZE + VIRTQ_USED_ELEMENT_SIZE * queue_size; 311 312 if !self.ready { 313 error!("attempt to use virtio queue that is not marked ready"); 314 false 315 } else if desc_table 316 .checked_add(desc_table_size) 317 .map_or(true, |v| !mem.address_in_range(v)) 318 { 319 error!( 320 "virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}", 321 desc_table.raw_value(), 322 desc_table_size 323 ); 324 false 325 } else if avail_ring 326 .checked_add(avail_ring_size) 327 .map_or(true, |v| !mem.address_in_range(v)) 328 { 329 error!( 330 "virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}", 331 avail_ring.raw_value(), 332 avail_ring_size 333 ); 334 false 335 } else if used_ring 336 .checked_add(used_ring_size) 337 .map_or(true, |v| !mem.address_in_range(v)) 338 { 339 error!( 340 "virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}", 341 used_ring.raw_value(), 342 used_ring_size 343 ); 344 false 345 } else { 346 true 347 } 348 } 349 reset(&mut self)350 fn reset(&mut self) { 351 self.ready = false; 352 self.size = self.max_size; 353 self.desc_table = GuestAddress(DEFAULT_DESC_TABLE_ADDR); 354 self.avail_ring = GuestAddress(DEFAULT_AVAIL_RING_ADDR); 355 self.used_ring = GuestAddress(DEFAULT_USED_RING_ADDR); 356 self.next_avail = Wrapping(0); 357 self.next_used = Wrapping(0); 358 self.num_added = Wrapping(0); 359 self.event_idx_enabled = false; 360 } 361 lock(&mut self) -> <Self as QueueGuard>::G362 fn lock(&mut self) -> <Self as QueueGuard>::G { 363 self 364 } 365 max_size(&self) -> u16366 fn max_size(&self) -> u16 { 367 self.max_size 368 } 369 size(&self) -> u16370 fn size(&self) -> u16 { 371 self.size 372 } 373 set_size(&mut self, size: u16)374 fn set_size(&mut self, size: u16) { 375 if self.try_set_size(size).is_err() { 376 error!("virtio queue with invalid size: {}", size); 377 } 378 } 379 ready(&self) -> bool380 fn ready(&self) -> bool { 381 self.ready 382 } 383 set_ready(&mut self, ready: bool)384 fn set_ready(&mut self, ready: bool) { 385 self.ready = ready; 386 } 387 set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>)388 fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) { 389 let low = low.unwrap_or(self.desc_table.0 as u32) as u64; 390 let high = high.unwrap_or((self.desc_table.0 >> 32) as u32) as u64; 391 392 let desc_table = GuestAddress((high << 32) | low); 393 if self.try_set_desc_table_address(desc_table).is_err() { 394 error!("virtio queue descriptor table breaks alignment constraints"); 395 } 396 } 397 set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>)398 fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) { 399 let low = low.unwrap_or(self.avail_ring.0 as u32) as u64; 400 let high = high.unwrap_or((self.avail_ring.0 >> 32) as u32) as u64; 401 402 let avail_ring = GuestAddress((high << 32) | low); 403 if self.try_set_avail_ring_address(avail_ring).is_err() { 404 error!("virtio queue available ring breaks alignment constraints"); 405 } 406 } 407 set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>)408 fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) { 409 let low = low.unwrap_or(self.used_ring.0 as u32) as u64; 410 let high = high.unwrap_or((self.used_ring.0 >> 32) as u32) as u64; 411 412 let used_ring = GuestAddress((high << 32) | low); 413 if self.try_set_used_ring_address(used_ring).is_err() { 414 error!("virtio queue used ring breaks alignment constraints"); 415 } 416 } 417 set_event_idx(&mut self, enabled: bool)418 fn set_event_idx(&mut self, enabled: bool) { 419 self.event_idx_enabled = enabled; 420 } 421 avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> where M: GuestMemory + ?Sized,422 fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> 423 where 424 M: GuestMemory + ?Sized, 425 { 426 let addr = self 427 .avail_ring 428 .checked_add(2) 429 .ok_or(Error::AddressOverflow)?; 430 431 mem.load(addr, order) 432 .map(u16::from_le) 433 .map(Wrapping) 434 .map_err(Error::GuestMemory) 435 } 436 used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>437 fn used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> { 438 let addr = self 439 .used_ring 440 .checked_add(2) 441 .ok_or(Error::AddressOverflow)?; 442 443 mem.load(addr, order) 444 .map(u16::from_le) 445 .map(Wrapping) 446 .map_err(Error::GuestMemory) 447 } 448 add_used<M: GuestMemory>( &mut self, mem: &M, head_index: u16, len: u32, ) -> Result<(), Error>449 fn add_used<M: GuestMemory>( 450 &mut self, 451 mem: &M, 452 head_index: u16, 453 len: u32, 454 ) -> Result<(), Error> { 455 if head_index >= self.size { 456 error!( 457 "attempted to add out of bounds descriptor to used ring: {}", 458 head_index 459 ); 460 return Err(Error::InvalidDescriptorIndex); 461 } 462 463 let next_used_index = u64::from(self.next_used.0 % self.size); 464 // This can not overflow an u64 since it is working with relatively small numbers compared 465 // to u64::MAX. 466 let offset = VIRTQ_USED_RING_HEADER_SIZE + next_used_index * VIRTQ_USED_ELEMENT_SIZE; 467 let addr = self 468 .used_ring 469 .checked_add(offset) 470 .ok_or(Error::AddressOverflow)?; 471 mem.write_obj(VirtqUsedElem::new(head_index.into(), len), addr) 472 .map_err(Error::GuestMemory)?; 473 474 self.next_used += Wrapping(1); 475 self.num_added += Wrapping(1); 476 477 mem.store( 478 u16::to_le(self.next_used.0), 479 self.used_ring 480 .checked_add(2) 481 .ok_or(Error::AddressOverflow)?, 482 Ordering::Release, 483 ) 484 .map_err(Error::GuestMemory) 485 } 486 enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error>487 fn enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> { 488 self.set_notification(mem, true)?; 489 // Ensures the following read is not reordered before any previous write operation. 490 fence(Ordering::SeqCst); 491 492 // We double check here to avoid the situation where the available ring has been updated 493 // just before we re-enabled notifications, and it's possible to miss one. We compare the 494 // current `avail_idx` value to `self.next_avail` because it's where we stopped processing 495 // entries. There are situations where we intentionally avoid processing everything in the 496 // available ring (which will cause this method to return `true`), but in that case we'll 497 // probably not re-enable notifications as we already know there are pending entries. 498 self.avail_idx(mem, Ordering::Relaxed) 499 .map(|idx| idx != self.next_avail) 500 } 501 disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error>502 fn disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error> { 503 self.set_notification(mem, false) 504 } 505 needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error>506 fn needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> { 507 let used_idx = self.next_used; 508 509 // Complete all the writes in add_used() before reading the event. 510 fence(Ordering::SeqCst); 511 512 // The VRING_AVAIL_F_NO_INTERRUPT flag isn't supported yet. 513 514 // When the `EVENT_IDX` feature is negotiated, the driver writes into `used_event` 515 // a value that's used by the device to determine whether a notification must 516 // be submitted after adding a descriptor chain to the used ring. According to the 517 // standard, the notification must be sent when `next_used == used_event + 1`, but 518 // various device model implementations rely on an inequality instead, most likely 519 // to also support use cases where a bunch of descriptor chains are added to the used 520 // ring first, and only afterwards the `needs_notification` logic is called. For example, 521 // the approach based on `num_added` below is taken from the Linux Kernel implementation 522 // (i.e. https://elixir.bootlin.com/linux/v5.15.35/source/drivers/virtio/virtio_ring.c#L661) 523 524 // The `old` variable below is used to determine the value of `next_used` from when 525 // `needs_notification` was called last (each `needs_notification` call resets `num_added` 526 // to zero, while each `add_used` called increments it by one). Then, the logic below 527 // uses wrapped arithmetic to see whether `used_event` can be found between `old` and 528 // `next_used` in the circular sequence space of the used ring. 529 if self.event_idx_enabled { 530 let used_event = self.used_event(mem, Ordering::Relaxed)?; 531 let old = used_idx - self.num_added; 532 self.num_added = Wrapping(0); 533 534 return Ok(used_idx - used_event - Wrapping(1) < used_idx - old); 535 } 536 537 Ok(true) 538 } 539 next_avail(&self) -> u16540 fn next_avail(&self) -> u16 { 541 self.next_avail.0 542 } 543 set_next_avail(&mut self, next_avail: u16)544 fn set_next_avail(&mut self, next_avail: u16) { 545 self.next_avail = Wrapping(next_avail); 546 } 547 next_used(&self) -> u16548 fn next_used(&self) -> u16 { 549 self.next_used.0 550 } 551 set_next_used(&mut self, next_used: u16)552 fn set_next_used(&mut self, next_used: u16) { 553 self.next_used = Wrapping(next_used); 554 } 555 desc_table(&self) -> u64556 fn desc_table(&self) -> u64 { 557 self.desc_table.0 558 } 559 avail_ring(&self) -> u64560 fn avail_ring(&self) -> u64 { 561 self.avail_ring.0 562 } 563 used_ring(&self) -> u64564 fn used_ring(&self) -> u64 { 565 self.used_ring.0 566 } 567 event_idx_enabled(&self) -> bool568 fn event_idx_enabled(&self) -> bool { 569 self.event_idx_enabled 570 } 571 pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>> where M: Clone + Deref, M::Target: GuestMemory,572 fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>> 573 where 574 M: Clone + Deref, 575 M::Target: GuestMemory, 576 { 577 // Default, iter-based impl. Will be subsequently improved. 578 match self.iter(mem) { 579 Ok(mut iter) => iter.next(), 580 Err(e) => { 581 error!("Iterator error {}", e); 582 None 583 } 584 } 585 } 586 } 587 588 impl QueueOwnedT for Queue { iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error> where M: Deref, M::Target: GuestMemory,589 fn iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error> 590 where 591 M: Deref, 592 M::Target: GuestMemory, 593 { 594 // We're checking here that a reset did not happen without re-initializing the queue. 595 // TODO: In the future we might want to also check that the other parameters in the 596 // queue are valid. 597 if !self.ready || self.avail_ring == GuestAddress(0) { 598 return Err(Error::QueueNotReady); 599 } 600 601 self.avail_idx(mem.deref(), Ordering::Acquire) 602 .map(move |idx| AvailIter::new(mem, idx, self))? 603 } 604 go_to_previous_position(&mut self)605 fn go_to_previous_position(&mut self) { 606 self.next_avail -= Wrapping(1); 607 } 608 } 609 610 /// Consuming iterator over all available descriptor chain heads in the queue. 611 /// 612 /// # Example 613 /// 614 /// ```rust 615 /// # use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE}; 616 /// # use virtio_queue::mock::MockSplitQueue; 617 /// use virtio_queue::{Descriptor, Queue, QueueOwnedT}; 618 /// use vm_memory::{GuestAddress, GuestMemoryMmap}; 619 /// 620 /// # fn populate_queue(m: &GuestMemoryMmap) -> Queue { 621 /// # let vq = MockSplitQueue::new(m, 16); 622 /// # let mut q: Queue = vq.create_queue().unwrap(); 623 /// # 624 /// # // The chains are (0, 1), (2, 3, 4) and (5, 6). 625 /// # let mut descs = Vec::new(); 626 /// # for i in 0..7 { 627 /// # let flags = match i { 628 /// # 1 | 6 => 0, 629 /// # 2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, 630 /// # 4 => VRING_DESC_F_WRITE, 631 /// # _ => VRING_DESC_F_NEXT, 632 /// # }; 633 /// # 634 /// # descs.push(Descriptor::new((0x1000 * (i + 1)) as u64, 0x1000, flags as u16, i + 1)); 635 /// # } 636 /// # 637 /// # vq.add_desc_chains(&descs, 0).unwrap(); 638 /// # q 639 /// # } 640 /// let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 641 /// // Populate the queue with descriptor chains and update the available ring accordingly. 642 /// let mut queue = populate_queue(m); 643 /// let mut i = queue.iter(m).unwrap(); 644 /// 645 /// { 646 /// let mut c = i.next().unwrap(); 647 /// let _first_head_index = c.head_index(); 648 /// // We should have two descriptors in the first chain. 649 /// let _desc1 = c.next().unwrap(); 650 /// let _desc2 = c.next().unwrap(); 651 /// } 652 /// 653 /// { 654 /// let c = i.next().unwrap(); 655 /// let _second_head_index = c.head_index(); 656 /// 657 /// let mut iter = c.writable(); 658 /// // We should have two writable descriptors in the second chain. 659 /// let _desc1 = iter.next().unwrap(); 660 /// let _desc2 = iter.next().unwrap(); 661 /// } 662 /// 663 /// { 664 /// let c = i.next().unwrap(); 665 /// let _third_head_index = c.head_index(); 666 /// 667 /// let mut iter = c.readable(); 668 /// // We should have one readable descriptor in the third chain. 669 /// let _desc1 = iter.next().unwrap(); 670 /// } 671 /// // Let's go back one position in the available ring. 672 /// i.go_to_previous_position(); 673 /// // We should be able to access again the third descriptor chain. 674 /// let c = i.next().unwrap(); 675 /// let _third_head_index = c.head_index(); 676 /// ``` 677 #[derive(Debug)] 678 pub struct AvailIter<'b, M> { 679 mem: M, 680 desc_table: GuestAddress, 681 avail_ring: GuestAddress, 682 queue_size: u16, 683 last_index: Wrapping<u16>, 684 next_avail: &'b mut Wrapping<u16>, 685 } 686 687 impl<'b, M> AvailIter<'b, M> 688 where 689 M: Deref, 690 M::Target: GuestMemory, 691 { 692 /// Create a new instance of `AvailInter`. 693 /// 694 /// # Arguments 695 /// * `mem` - the `GuestMemory` object that can be used to access the queue buffers. 696 /// * `idx` - the index of the available ring entry where the driver would put the next 697 /// available descriptor chain. 698 /// * `queue` - the `Queue` object from which the needed data to create the `AvailIter` can 699 /// be retrieved. new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error>700 pub(crate) fn new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error> { 701 // The number of descriptor chain heads to process should always 702 // be smaller or equal to the queue size, as the driver should 703 // never ask the VMM to process a available ring entry more than 704 // once. Checking and reporting such incorrect driver behavior 705 // can prevent potential hanging and Denial-of-Service from 706 // happening on the VMM side. 707 if (idx - queue.next_avail).0 > queue.size { 708 return Err(Error::InvalidAvailRingIndex); 709 } 710 711 Ok(AvailIter { 712 mem, 713 desc_table: queue.desc_table, 714 avail_ring: queue.avail_ring, 715 queue_size: queue.size, 716 last_index: idx, 717 next_avail: &mut queue.next_avail, 718 }) 719 } 720 721 /// Goes back one position in the available descriptor chain offered by the driver. 722 /// 723 /// Rust does not support bidirectional iterators. This is the only way to revert the effect 724 /// of an iterator increment on the queue. 725 /// 726 /// Note: this method assumes there's only one thread manipulating the queue, so it should only 727 /// be invoked in single-threaded context. go_to_previous_position(&mut self)728 pub fn go_to_previous_position(&mut self) { 729 *self.next_avail -= Wrapping(1); 730 } 731 } 732 733 impl<'b, M> Iterator for AvailIter<'b, M> 734 where 735 M: Clone + Deref, 736 M::Target: GuestMemory, 737 { 738 type Item = DescriptorChain<M>; 739 next(&mut self) -> Option<Self::Item>740 fn next(&mut self) -> Option<Self::Item> { 741 if *self.next_avail == self.last_index { 742 return None; 743 } 744 745 // These two operations can not overflow an u64 since they're working with relatively small 746 // numbers compared to u64::MAX. 747 let elem_off = 748 u64::from(self.next_avail.0.checked_rem(self.queue_size)?) * VIRTQ_AVAIL_ELEMENT_SIZE; 749 let offset = VIRTQ_AVAIL_RING_HEADER_SIZE + elem_off; 750 751 let addr = self.avail_ring.checked_add(offset)?; 752 let head_index: u16 = self 753 .mem 754 .load(addr, Ordering::Acquire) 755 .map(u16::from_le) 756 .map_err(|_| error!("Failed to read from memory {:x}", addr.raw_value())) 757 .ok()?; 758 759 *self.next_avail += Wrapping(1); 760 761 Some(DescriptorChain::new( 762 self.mem.clone(), 763 self.desc_table, 764 self.queue_size, 765 head_index, 766 )) 767 } 768 } 769 770 #[cfg(any(test, feature = "test-utils"))] 771 // It is convenient for tests to implement `PartialEq`, but it is not a 772 // proper implementation as `GuestMemory` errors cannot implement `PartialEq`. 773 impl PartialEq for Error { eq(&self, other: &Self) -> bool774 fn eq(&self, other: &Self) -> bool { 775 format!("{}", &self) == format!("{}", other) 776 } 777 } 778 779 #[cfg(test)] 780 mod tests { 781 use super::*; 782 use crate::defs::{DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR}; 783 use crate::mock::MockSplitQueue; 784 use crate::Descriptor; 785 use virtio_bindings::bindings::virtio_ring::{ 786 VRING_DESC_F_NEXT, VRING_DESC_F_WRITE, VRING_USED_F_NO_NOTIFY, 787 }; 788 789 use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap}; 790 791 #[test] test_queue_is_valid()792 fn test_queue_is_valid() { 793 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 794 let vq = MockSplitQueue::new(m, 16); 795 let mut q: Queue = vq.create_queue().unwrap(); 796 797 // q is currently valid 798 assert!(q.is_valid(m)); 799 800 // shouldn't be valid when not marked as ready 801 q.set_ready(false); 802 assert!(!q.ready()); 803 assert!(!q.is_valid(m)); 804 q.set_ready(true); 805 806 // shouldn't be allowed to set a size > max_size 807 q.set_size(q.max_size() << 1); 808 assert_eq!(q.size, q.max_size()); 809 810 // or set the size to 0 811 q.set_size(0); 812 assert_eq!(q.size, q.max_size()); 813 814 // or set a size which is not a power of 2 815 q.set_size(11); 816 assert_eq!(q.size, q.max_size()); 817 818 // but should be allowed to set a size if 0 < size <= max_size and size is a power of two 819 q.set_size(4); 820 assert_eq!(q.size, 4); 821 q.size = q.max_size(); 822 823 // shouldn't be allowed to set an address that breaks the alignment constraint 824 q.set_desc_table_address(Some(0xf), None); 825 assert_eq!(q.desc_table.0, vq.desc_table_addr().0); 826 // should be allowed to set an aligned out of bounds address 827 q.set_desc_table_address(Some(0xffff_fff0), None); 828 assert_eq!(q.desc_table.0, 0xffff_fff0); 829 // but shouldn't be valid 830 assert!(!q.is_valid(m)); 831 // but should be allowed to set a valid description table address 832 q.set_desc_table_address(Some(0x10), None); 833 assert_eq!(q.desc_table.0, 0x10); 834 assert!(q.is_valid(m)); 835 let addr = vq.desc_table_addr().0; 836 q.set_desc_table_address(Some(addr as u32), Some((addr >> 32) as u32)); 837 838 // shouldn't be allowed to set an address that breaks the alignment constraint 839 q.set_avail_ring_address(Some(0x1), None); 840 assert_eq!(q.avail_ring.0, vq.avail_addr().0); 841 // should be allowed to set an aligned out of bounds address 842 q.set_avail_ring_address(Some(0xffff_fffe), None); 843 assert_eq!(q.avail_ring.0, 0xffff_fffe); 844 // but shouldn't be valid 845 assert!(!q.is_valid(m)); 846 // but should be allowed to set a valid available ring address 847 q.set_avail_ring_address(Some(0x2), None); 848 assert_eq!(q.avail_ring.0, 0x2); 849 assert!(q.is_valid(m)); 850 let addr = vq.avail_addr().0; 851 q.set_avail_ring_address(Some(addr as u32), Some((addr >> 32) as u32)); 852 853 // shouldn't be allowed to set an address that breaks the alignment constraint 854 q.set_used_ring_address(Some(0x3), None); 855 assert_eq!(q.used_ring.0, vq.used_addr().0); 856 // should be allowed to set an aligned out of bounds address 857 q.set_used_ring_address(Some(0xffff_fffc), None); 858 assert_eq!(q.used_ring.0, 0xffff_fffc); 859 // but shouldn't be valid 860 assert!(!q.is_valid(m)); 861 // but should be allowed to set a valid used ring address 862 q.set_used_ring_address(Some(0x4), None); 863 assert_eq!(q.used_ring.0, 0x4); 864 let addr = vq.used_addr().0; 865 q.set_used_ring_address(Some(addr as u32), Some((addr >> 32) as u32)); 866 assert!(q.is_valid(m)); 867 } 868 869 #[test] test_add_used()870 fn test_add_used() { 871 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 872 let vq = MockSplitQueue::new(mem, 16); 873 let mut q: Queue = vq.create_queue().unwrap(); 874 875 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(0)); 876 assert_eq!(u16::from_le(vq.used().idx().load()), 0); 877 878 // index too large 879 assert!(q.add_used(mem, 16, 0x1000).is_err()); 880 assert_eq!(u16::from_le(vq.used().idx().load()), 0); 881 882 // should be ok 883 q.add_used(mem, 1, 0x1000).unwrap(); 884 assert_eq!(q.next_used, Wrapping(1)); 885 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(1)); 886 assert_eq!(u16::from_le(vq.used().idx().load()), 1); 887 888 let x = vq.used().ring().ref_at(0).unwrap().load(); 889 assert_eq!(x.id(), 1); 890 assert_eq!(x.len(), 0x1000); 891 } 892 893 #[test] test_reset_queue()894 fn test_reset_queue() { 895 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 896 let vq = MockSplitQueue::new(m, 16); 897 let mut q: Queue = vq.create_queue().unwrap(); 898 899 q.set_size(8); 900 // The address set by `MockSplitQueue` for the descriptor table is DEFAULT_DESC_TABLE_ADDR, 901 // so let's change it for testing the reset. 902 q.set_desc_table_address(Some(0x5000), None); 903 // Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`. 904 q.set_event_idx(true); 905 q.set_next_avail(2); 906 q.set_next_used(4); 907 q.num_added = Wrapping(15); 908 assert_eq!(q.size, 8); 909 // `create_queue` also marks the queue as ready. 910 assert!(q.ready); 911 assert_ne!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR)); 912 assert_ne!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR)); 913 assert_ne!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR)); 914 assert_ne!(q.next_avail, Wrapping(0)); 915 assert_ne!(q.next_used, Wrapping(0)); 916 assert_ne!(q.num_added, Wrapping(0)); 917 assert!(q.event_idx_enabled); 918 919 q.reset(); 920 assert_eq!(q.size, 16); 921 assert!(!q.ready); 922 assert_eq!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR)); 923 assert_eq!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR)); 924 assert_eq!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR)); 925 assert_eq!(q.next_avail, Wrapping(0)); 926 assert_eq!(q.next_used, Wrapping(0)); 927 assert_eq!(q.num_added, Wrapping(0)); 928 assert!(!q.event_idx_enabled); 929 } 930 931 #[test] test_needs_notification()932 fn test_needs_notification() { 933 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 934 let qsize = 16; 935 let vq = MockSplitQueue::new(mem, qsize); 936 let mut q: Queue = vq.create_queue().unwrap(); 937 let avail_addr = vq.avail_addr(); 938 939 // It should always return true when EVENT_IDX isn't enabled. 940 for i in 0..qsize { 941 q.next_used = Wrapping(i); 942 assert!(q.needs_notification(mem).unwrap()); 943 } 944 945 mem.write_obj::<u16>( 946 u16::to_le(4), 947 avail_addr.unchecked_add(4 + qsize as u64 * 2), 948 ) 949 .unwrap(); 950 q.set_event_idx(true); 951 952 // Incrementing up to this value causes an `u16` to wrap back to 0. 953 let wrap = u32::from(u16::MAX) + 1; 954 955 for i in 0..wrap + 12 { 956 q.next_used = Wrapping(i as u16); 957 // Let's test wrapping around the maximum index value as well. 958 // `num_added` needs to be at least `1` to represent the fact that new descriptor 959 // chains have be added to the used ring since the last time `needs_notification` 960 // returned. 961 q.num_added = Wrapping(1); 962 let expected = i == 5 || i == (5 + wrap); 963 assert_eq!((q.needs_notification(mem).unwrap(), i), (expected, i)); 964 } 965 966 mem.write_obj::<u16>( 967 u16::to_le(8), 968 avail_addr.unchecked_add(4 + qsize as u64 * 2), 969 ) 970 .unwrap(); 971 972 // Returns `false` because the current `used_event` value is behind both `next_used` and 973 // the value of `next_used` at the time when `needs_notification` last returned (which is 974 // computed based on `num_added` as described in the comments for `needs_notification`. 975 assert!(!q.needs_notification(mem).unwrap()); 976 977 mem.write_obj::<u16>( 978 u16::to_le(15), 979 avail_addr.unchecked_add(4 + qsize as u64 * 2), 980 ) 981 .unwrap(); 982 983 q.num_added = Wrapping(1); 984 assert!(!q.needs_notification(mem).unwrap()); 985 986 q.next_used = Wrapping(15); 987 q.num_added = Wrapping(1); 988 assert!(!q.needs_notification(mem).unwrap()); 989 990 q.next_used = Wrapping(16); 991 q.num_added = Wrapping(1); 992 assert!(q.needs_notification(mem).unwrap()); 993 994 // Calling `needs_notification` again immediately returns `false`. 995 assert!(!q.needs_notification(mem).unwrap()); 996 997 mem.write_obj::<u16>( 998 u16::to_le(u16::MAX - 3), 999 avail_addr.unchecked_add(4 + qsize as u64 * 2), 1000 ) 1001 .unwrap(); 1002 q.next_used = Wrapping(u16::MAX - 2); 1003 q.num_added = Wrapping(1); 1004 // Returns `true` because, when looking at circular sequence of indices of the used ring, 1005 // the value we wrote in the `used_event` appears between the "old" value of `next_used` 1006 // (i.e. `next_used` - `num_added`) and the current `next_used`, thus suggesting that we 1007 // need to notify the driver. 1008 assert!(q.needs_notification(mem).unwrap()); 1009 } 1010 1011 #[test] test_enable_disable_notification()1012 fn test_enable_disable_notification() { 1013 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1014 let vq = MockSplitQueue::new(mem, 16); 1015 1016 let mut q: Queue = vq.create_queue().unwrap(); 1017 let used_addr = vq.used_addr(); 1018 1019 assert!(!q.event_idx_enabled); 1020 1021 q.enable_notification(mem).unwrap(); 1022 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1023 assert_eq!(v, 0); 1024 1025 q.disable_notification(mem).unwrap(); 1026 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1027 assert_eq!(v, VRING_USED_F_NO_NOTIFY as u16); 1028 1029 q.enable_notification(mem).unwrap(); 1030 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1031 assert_eq!(v, 0); 1032 1033 q.set_event_idx(true); 1034 let avail_addr = vq.avail_addr(); 1035 mem.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2)) 1036 .unwrap(); 1037 1038 assert!(q.enable_notification(mem).unwrap()); 1039 q.next_avail = Wrapping(2); 1040 assert!(!q.enable_notification(mem).unwrap()); 1041 1042 mem.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2)) 1043 .unwrap(); 1044 1045 assert!(q.enable_notification(mem).unwrap()); 1046 q.next_avail = Wrapping(8); 1047 assert!(!q.enable_notification(mem).unwrap()); 1048 } 1049 1050 #[test] test_consume_chains_with_notif()1051 fn test_consume_chains_with_notif() { 1052 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1053 let vq = MockSplitQueue::new(mem, 16); 1054 1055 let mut q: Queue = vq.create_queue().unwrap(); 1056 1057 // q is currently valid. 1058 assert!(q.is_valid(mem)); 1059 1060 // The chains are (0, 1), (2, 3, 4), (5, 6), (7, 8), (9, 10, 11, 12). 1061 let mut descs = Vec::new(); 1062 for i in 0..13 { 1063 let flags = match i { 1064 1 | 4 | 6 | 8 | 12 => 0, 1065 _ => VRING_DESC_F_NEXT, 1066 }; 1067 1068 descs.push(Descriptor::new( 1069 (0x1000 * (i + 1)) as u64, 1070 0x1000, 1071 flags as u16, 1072 i + 1, 1073 )); 1074 } 1075 1076 vq.add_desc_chains(&descs, 0).unwrap(); 1077 // Update the index of the chain that can be consumed to not be the last one. 1078 // This enables us to consume chains in multiple iterations as opposed to consuming 1079 // all the driver written chains at once. 1080 vq.avail().idx().store(u16::to_le(2)); 1081 // No descriptor chains are consumed at this point. 1082 assert_eq!(q.next_avail(), 0); 1083 1084 let mut i = 0; 1085 1086 loop { 1087 i += 1; 1088 q.disable_notification(mem).unwrap(); 1089 1090 while let Some(chain) = q.iter(mem).unwrap().next() { 1091 // Process the descriptor chain, and then add entries to the 1092 // used ring. 1093 let head_index = chain.head_index(); 1094 let mut desc_len = 0; 1095 chain.for_each(|d| { 1096 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1097 desc_len += d.len(); 1098 } 1099 }); 1100 q.add_used(mem, head_index, desc_len).unwrap(); 1101 } 1102 if !q.enable_notification(mem).unwrap() { 1103 break; 1104 } 1105 } 1106 // The chains should be consumed in a single loop iteration because there's nothing updating 1107 // the `idx` field of the available ring in the meantime. 1108 assert_eq!(i, 1); 1109 // The next chain that can be consumed should have index 2. 1110 assert_eq!(q.next_avail(), 2); 1111 assert_eq!(q.next_used(), 2); 1112 // Let the device know it can consume one more chain. 1113 vq.avail().idx().store(u16::to_le(3)); 1114 i = 0; 1115 1116 loop { 1117 i += 1; 1118 q.disable_notification(mem).unwrap(); 1119 1120 while let Some(chain) = q.iter(mem).unwrap().next() { 1121 // Process the descriptor chain, and then add entries to the 1122 // used ring. 1123 let head_index = chain.head_index(); 1124 let mut desc_len = 0; 1125 chain.for_each(|d| { 1126 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1127 desc_len += d.len(); 1128 } 1129 }); 1130 q.add_used(mem, head_index, desc_len).unwrap(); 1131 } 1132 1133 // For the simplicity of the test we are updating here the `idx` value of the available 1134 // ring. Ideally this should be done on a separate thread. 1135 // Because of this update, the loop should be iterated again to consume the new 1136 // available descriptor chains. 1137 vq.avail().idx().store(u16::to_le(4)); 1138 if !q.enable_notification(mem).unwrap() { 1139 break; 1140 } 1141 } 1142 assert_eq!(i, 2); 1143 // The next chain that can be consumed should have index 4. 1144 assert_eq!(q.next_avail(), 4); 1145 assert_eq!(q.next_used(), 4); 1146 1147 // Set an `idx` that is bigger than the number of entries added in the ring. 1148 // This is an allowed scenario, but the indexes of the chain will have unexpected values. 1149 vq.avail().idx().store(u16::to_le(7)); 1150 loop { 1151 q.disable_notification(mem).unwrap(); 1152 1153 while let Some(chain) = q.iter(mem).unwrap().next() { 1154 // Process the descriptor chain, and then add entries to the 1155 // used ring. 1156 let head_index = chain.head_index(); 1157 let mut desc_len = 0; 1158 chain.for_each(|d| { 1159 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1160 desc_len += d.len(); 1161 } 1162 }); 1163 q.add_used(mem, head_index, desc_len).unwrap(); 1164 } 1165 if !q.enable_notification(mem).unwrap() { 1166 break; 1167 } 1168 } 1169 assert_eq!(q.next_avail(), 7); 1170 assert_eq!(q.next_used(), 7); 1171 } 1172 1173 #[test] test_invalid_avail_idx()1174 fn test_invalid_avail_idx() { 1175 // This is a negative test for the following MUST from the spec: `A driver MUST NOT 1176 // decrement the available idx on a virtqueue (ie. there is no way to “unexpose” buffers).`. 1177 // We validate that for this misconfiguration, the device does not panic. 1178 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1179 let vq = MockSplitQueue::new(mem, 16); 1180 1181 let mut q: Queue = vq.create_queue().unwrap(); 1182 1183 // q is currently valid. 1184 assert!(q.is_valid(mem)); 1185 1186 // The chains are (0, 1), (2, 3, 4), (5, 6). 1187 let mut descs = Vec::new(); 1188 for i in 0..7 { 1189 let flags = match i { 1190 1 | 4 | 6 => 0, 1191 _ => VRING_DESC_F_NEXT, 1192 }; 1193 1194 descs.push(Descriptor::new( 1195 (0x1000 * (i + 1)) as u64, 1196 0x1000, 1197 flags as u16, 1198 i + 1, 1199 )); 1200 } 1201 1202 vq.add_desc_chains(&descs, 0).unwrap(); 1203 // Let the device know it can consume chains with the index < 2. 1204 vq.avail().idx().store(u16::to_le(3)); 1205 // No descriptor chains are consumed at this point. 1206 assert_eq!(q.next_avail(), 0); 1207 assert_eq!(q.next_used(), 0); 1208 1209 loop { 1210 q.disable_notification(mem).unwrap(); 1211 1212 while let Some(chain) = q.iter(mem).unwrap().next() { 1213 // Process the descriptor chain, and then add entries to the 1214 // used ring. 1215 let head_index = chain.head_index(); 1216 let mut desc_len = 0; 1217 chain.for_each(|d| { 1218 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1219 desc_len += d.len(); 1220 } 1221 }); 1222 q.add_used(mem, head_index, desc_len).unwrap(); 1223 } 1224 if !q.enable_notification(mem).unwrap() { 1225 break; 1226 } 1227 } 1228 // The next chain that can be consumed should have index 3. 1229 assert_eq!(q.next_avail(), 3); 1230 assert_eq!(q.avail_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3)); 1231 assert_eq!(q.next_used(), 3); 1232 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3)); 1233 assert!(q.lock().ready()); 1234 1235 // Decrement `idx` which should be forbidden. We don't enforce this thing, but we should 1236 // test that we don't panic in case the driver decrements it. 1237 vq.avail().idx().store(u16::to_le(1)); 1238 // Invalid available ring index 1239 assert!(q.iter(mem).is_err()); 1240 } 1241 1242 #[test] test_iterator_and_avail_idx()1243 fn test_iterator_and_avail_idx() { 1244 // This test ensures constructing a descriptor chain iterator succeeds 1245 // with valid available ring indexes while produces an error with invalid 1246 // indexes. 1247 let queue_size = 2; 1248 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1249 let vq = MockSplitQueue::new(mem, queue_size); 1250 1251 let mut q: Queue = vq.create_queue().unwrap(); 1252 1253 // q is currently valid. 1254 assert!(q.is_valid(mem)); 1255 1256 // Create descriptors to fill up the queue 1257 let mut descs = Vec::new(); 1258 for i in 0..queue_size { 1259 descs.push(Descriptor::new( 1260 (0x1000 * (i + 1)) as u64, 1261 0x1000, 1262 0_u16, 1263 i + 1, 1264 )); 1265 } 1266 vq.add_desc_chains(&descs, 0).unwrap(); 1267 1268 // Set the 'next_available' index to 'u16:MAX' to test the wrapping scenarios 1269 q.set_next_avail(u16::MAX); 1270 1271 // When the number of chains exposed by the driver is equal to or less than the queue 1272 // size, the available ring index is valid and constructs an iterator successfully. 1273 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size); 1274 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1275 assert!(q.iter(mem).is_ok()); 1276 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size - 1); 1277 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1278 assert!(q.iter(mem).is_ok()); 1279 1280 // When the number of chains exposed by the driver is larger than the queue size, the 1281 // available ring index is invalid and produces an error from constructing an iterator. 1282 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size + 1); 1283 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1284 assert!(q.iter(mem).is_err()); 1285 } 1286 1287 #[test] test_descriptor_and_iterator()1288 fn test_descriptor_and_iterator() { 1289 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1290 let vq = MockSplitQueue::new(m, 16); 1291 1292 let mut q: Queue = vq.create_queue().unwrap(); 1293 1294 // q is currently valid 1295 assert!(q.is_valid(m)); 1296 1297 // the chains are (0, 1), (2, 3, 4) and (5, 6) 1298 let mut descs = Vec::new(); 1299 for j in 0..7 { 1300 let flags = match j { 1301 1 | 6 => 0, 1302 2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, 1303 4 => VRING_DESC_F_WRITE, 1304 _ => VRING_DESC_F_NEXT, 1305 }; 1306 1307 descs.push(Descriptor::new( 1308 (0x1000 * (j + 1)) as u64, 1309 0x1000, 1310 flags as u16, 1311 j + 1, 1312 )); 1313 } 1314 1315 vq.add_desc_chains(&descs, 0).unwrap(); 1316 1317 let mut i = q.iter(m).unwrap(); 1318 1319 { 1320 let c = i.next().unwrap(); 1321 assert_eq!(c.head_index(), 0); 1322 1323 let mut iter = c; 1324 assert!(iter.next().is_some()); 1325 assert!(iter.next().is_some()); 1326 assert!(iter.next().is_none()); 1327 assert!(iter.next().is_none()); 1328 } 1329 1330 { 1331 let c = i.next().unwrap(); 1332 assert_eq!(c.head_index(), 2); 1333 1334 let mut iter = c.writable(); 1335 assert!(iter.next().is_some()); 1336 assert!(iter.next().is_some()); 1337 assert!(iter.next().is_none()); 1338 assert!(iter.next().is_none()); 1339 } 1340 1341 { 1342 let c = i.next().unwrap(); 1343 assert_eq!(c.head_index(), 5); 1344 1345 let mut iter = c.readable(); 1346 assert!(iter.next().is_some()); 1347 assert!(iter.next().is_none()); 1348 assert!(iter.next().is_none()); 1349 } 1350 } 1351 1352 #[test] test_iterator()1353 fn test_iterator() { 1354 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1355 let vq = MockSplitQueue::new(m, 16); 1356 1357 let mut q: Queue = vq.create_queue().unwrap(); 1358 1359 q.size = q.max_size; 1360 q.desc_table = vq.desc_table_addr(); 1361 q.avail_ring = vq.avail_addr(); 1362 q.used_ring = vq.used_addr(); 1363 assert!(q.is_valid(m)); 1364 1365 { 1366 // an invalid queue should return an iterator with no next 1367 q.ready = false; 1368 assert!(q.iter(m).is_err()); 1369 } 1370 1371 q.ready = true; 1372 1373 // now let's create two simple descriptor chains 1374 // the chains are (0, 1) and (2, 3, 4) 1375 { 1376 let mut descs = Vec::new(); 1377 for j in 0..5u16 { 1378 let flags = match j { 1379 1 | 4 => 0, 1380 _ => VRING_DESC_F_NEXT, 1381 }; 1382 1383 descs.push(Descriptor::new( 1384 (0x1000 * (j + 1)) as u64, 1385 0x1000, 1386 flags as u16, 1387 j + 1, 1388 )); 1389 } 1390 vq.add_desc_chains(&descs, 0).unwrap(); 1391 1392 let mut i = q.iter(m).unwrap(); 1393 1394 { 1395 let mut c = i.next().unwrap(); 1396 assert_eq!(c.head_index(), 0); 1397 1398 c.next().unwrap(); 1399 assert!(c.next().is_some()); 1400 assert!(c.next().is_none()); 1401 assert_eq!(c.head_index(), 0); 1402 } 1403 1404 { 1405 let mut c = i.next().unwrap(); 1406 assert_eq!(c.head_index(), 2); 1407 1408 c.next().unwrap(); 1409 c.next().unwrap(); 1410 c.next().unwrap(); 1411 assert!(c.next().is_none()); 1412 assert_eq!(c.head_index(), 2); 1413 } 1414 1415 // also test go_to_previous_position() works as expected 1416 { 1417 assert!(i.next().is_none()); 1418 i.go_to_previous_position(); 1419 let mut c = q.iter(m).unwrap().next().unwrap(); 1420 c.next().unwrap(); 1421 c.next().unwrap(); 1422 c.next().unwrap(); 1423 assert!(c.next().is_none()); 1424 } 1425 } 1426 1427 // Test that iterating some broken descriptor chain does not exceed 1428 // 2^32 bytes in total (VIRTIO spec version 1.2, 2.7.5.2: 1429 // Drivers MUST NOT add a descriptor chain longer than 2^32 bytes in 1430 // total) 1431 { 1432 let descs = vec![ 1433 Descriptor::new(0x1000, 0xffff_ffff, VRING_DESC_F_NEXT as u16, 1), 1434 Descriptor::new(0x1000, 0x1234_5678, 0, 2), 1435 ]; 1436 vq.add_desc_chains(&descs, 0).unwrap(); 1437 let mut yielded_bytes_by_iteration = 0_u32; 1438 for d in q.iter(m).unwrap().next().unwrap() { 1439 yielded_bytes_by_iteration = yielded_bytes_by_iteration 1440 .checked_add(d.len()) 1441 .expect("iterator should not yield more than 2^32 bytes"); 1442 } 1443 } 1444 1445 // Same as above, but test with a descriptor which is self-referential 1446 { 1447 let descs = vec![Descriptor::new( 1448 0x1000, 1449 0xffff_ffff, 1450 VRING_DESC_F_NEXT as u16, 1451 0, 1452 )]; 1453 vq.add_desc_chains(&descs, 0).unwrap(); 1454 let mut yielded_bytes_by_iteration = 0_u32; 1455 for d in q.iter(m).unwrap().next().unwrap() { 1456 yielded_bytes_by_iteration = yielded_bytes_by_iteration 1457 .checked_add(d.len()) 1458 .expect("iterator should not yield more than 2^32 bytes"); 1459 } 1460 } 1461 } 1462 1463 #[test] test_regression_iterator_division()1464 fn test_regression_iterator_division() { 1465 // This is a regression test that tests that the iterator does not try to divide 1466 // by 0 when the queue size is 0 1467 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1468 let vq = MockSplitQueue::new(m, 1); 1469 // This input was generated by the fuzzer, both for the QueueS and the Descriptor 1470 let descriptors: Vec<Descriptor> = vec![Descriptor::new( 1471 14178673876262995140, 1472 3301229764, 1473 50372, 1474 50372, 1475 )]; 1476 vq.build_desc_chain(&descriptors).unwrap(); 1477 1478 let mut q = Queue { 1479 max_size: 38, 1480 next_avail: Wrapping(0), 1481 next_used: Wrapping(0), 1482 event_idx_enabled: false, 1483 num_added: Wrapping(0), 1484 size: 0, 1485 ready: false, 1486 desc_table: GuestAddress(12837708984796196), 1487 avail_ring: GuestAddress(0), 1488 used_ring: GuestAddress(9943947977301164032), 1489 }; 1490 1491 assert!(q.pop_descriptor_chain(m).is_none()); 1492 } 1493 1494 #[test] test_setters_error_cases()1495 fn test_setters_error_cases() { 1496 assert_eq!(Queue::new(15).unwrap_err(), Error::InvalidMaxSize); 1497 let mut q = Queue::new(16).unwrap(); 1498 1499 let expected_val = q.desc_table.0; 1500 assert_eq!( 1501 q.try_set_desc_table_address(GuestAddress(0xf)).unwrap_err(), 1502 Error::InvalidDescTableAlign 1503 ); 1504 assert_eq!(q.desc_table(), expected_val); 1505 1506 let expected_val = q.avail_ring.0; 1507 assert_eq!( 1508 q.try_set_avail_ring_address(GuestAddress(0x1)).unwrap_err(), 1509 Error::InvalidAvailRingAlign 1510 ); 1511 assert_eq!(q.avail_ring(), expected_val); 1512 1513 let expected_val = q.used_ring.0; 1514 assert_eq!( 1515 q.try_set_used_ring_address(GuestAddress(0x3)).unwrap_err(), 1516 Error::InvalidUsedRingAlign 1517 ); 1518 assert_eq!(q.used_ring(), expected_val); 1519 1520 let expected_val = q.size; 1521 assert_eq!(q.try_set_size(15).unwrap_err(), Error::InvalidSize); 1522 assert_eq!(q.size(), expected_val) 1523 } 1524 1525 #[test] 1526 // This is a regression test for a fuzzing finding. If the driver requests a reset of the 1527 // device, but then does not re-initializes the queue then a subsequent call to process 1528 // a request should yield no descriptors to process. Before this fix we were processing 1529 // descriptors that were added to the queue before, and we were ending up processing 255 1530 // descriptors per chain. test_regression_timeout_after_reset()1531 fn test_regression_timeout_after_reset() { 1532 // The input below was generated by libfuzzer and adapted for this test. 1533 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x10000)]).unwrap(); 1534 let vq = MockSplitQueue::new(m, 1024); 1535 1536 // This input below was generated by the fuzzer. 1537 let descriptors: Vec<Descriptor> = vec![ 1538 Descriptor::new(21508325467, 0, 1, 4), 1539 Descriptor::new(2097152, 4096, 3, 0), 1540 Descriptor::new(18374686479672737792, 4294967295, 65535, 29), 1541 Descriptor::new(76842670169653248, 1114115, 0, 0), 1542 Descriptor::new(16, 983040, 126, 3), 1543 Descriptor::new(897648164864, 0, 0, 0), 1544 Descriptor::new(111669149722, 0, 0, 0), 1545 ]; 1546 vq.build_multiple_desc_chains(&descriptors).unwrap(); 1547 1548 let mut q: Queue = vq.create_queue().unwrap(); 1549 1550 // Setting the queue to ready should not allow consuming descriptors after reset. 1551 q.reset(); 1552 q.set_ready(true); 1553 let mut counter = 0; 1554 while let Some(mut desc_chain) = q.pop_descriptor_chain(m) { 1555 // this empty loop is here to check that there are no side effects 1556 // in terms of memory & execution time. 1557 while desc_chain.next().is_some() { 1558 counter += 1; 1559 } 1560 } 1561 assert_eq!(counter, 0); 1562 1563 // Setting the avail_addr to valid should not allow consuming descriptors after reset. 1564 q.reset(); 1565 q.set_avail_ring_address(Some(0x1000), None); 1566 assert_eq!(q.avail_ring, GuestAddress(0x1000)); 1567 counter = 0; 1568 while let Some(mut desc_chain) = q.pop_descriptor_chain(m) { 1569 // this empty loop is here to check that there are no side effects 1570 // in terms of memory & execution time. 1571 while desc_chain.next().is_some() { 1572 counter += 1; 1573 } 1574 } 1575 assert_eq!(counter, 0); 1576 } 1577 } 1578