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 487 // TODO: Turn this into a doc comment/example. 488 // With the current implementation, a common way of consuming entries from the available ring 489 // while also leveraging notification suppression is to use a loop, for example: 490 // 491 // loop { 492 // // We have to explicitly disable notifications if `VIRTIO_F_EVENT_IDX` has not been 493 // // negotiated. 494 // self.disable_notification()?; 495 // 496 // for chain in self.iter()? { 497 // // Do something with each chain ... 498 // // Let's assume we process all available chains here. 499 // } 500 // 501 // // If `enable_notification` returns `true`, the driver has added more entries to the 502 // // available ring. 503 // if !self.enable_notification()? { 504 // break; 505 // } 506 // } enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error>507 fn enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> { 508 self.set_notification(mem, true)?; 509 // Ensures the following read is not reordered before any previous write operation. 510 fence(Ordering::SeqCst); 511 512 // We double check here to avoid the situation where the available ring has been updated 513 // just before we re-enabled notifications, and it's possible to miss one. We compare the 514 // current `avail_idx` value to `self.next_avail` because it's where we stopped processing 515 // entries. There are situations where we intentionally avoid processing everything in the 516 // available ring (which will cause this method to return `true`), but in that case we'll 517 // probably not re-enable notifications as we already know there are pending entries. 518 self.avail_idx(mem, Ordering::Relaxed) 519 .map(|idx| idx != self.next_avail) 520 } 521 disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error>522 fn disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error> { 523 self.set_notification(mem, false) 524 } 525 needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error>526 fn needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> { 527 let used_idx = self.next_used; 528 529 // Complete all the writes in add_used() before reading the event. 530 fence(Ordering::SeqCst); 531 532 // The VRING_AVAIL_F_NO_INTERRUPT flag isn't supported yet. 533 534 // When the `EVENT_IDX` feature is negotiated, the driver writes into `used_event` 535 // a value that's used by the device to determine whether a notification must 536 // be submitted after adding a descriptor chain to the used ring. According to the 537 // standard, the notification must be sent when `next_used == used_event + 1`, but 538 // various device model implementations rely on an inequality instead, most likely 539 // to also support use cases where a bunch of descriptor chains are added to the used 540 // ring first, and only afterwards the `needs_notification` logic is called. For example, 541 // the approach based on `num_added` below is taken from the Linux Kernel implementation 542 // (i.e. https://elixir.bootlin.com/linux/v5.15.35/source/drivers/virtio/virtio_ring.c#L661) 543 544 // The `old` variable below is used to determine the value of `next_used` from when 545 // `needs_notification` was called last (each `needs_notification` call resets `num_added` 546 // to zero, while each `add_used` called increments it by one). Then, the logic below 547 // uses wrapped arithmetic to see whether `used_event` can be found between `old` and 548 // `next_used` in the circular sequence space of the used ring. 549 if self.event_idx_enabled { 550 let used_event = self.used_event(mem, Ordering::Relaxed)?; 551 let old = used_idx - self.num_added; 552 self.num_added = Wrapping(0); 553 554 return Ok(used_idx - used_event - Wrapping(1) < used_idx - old); 555 } 556 557 Ok(true) 558 } 559 next_avail(&self) -> u16560 fn next_avail(&self) -> u16 { 561 self.next_avail.0 562 } 563 set_next_avail(&mut self, next_avail: u16)564 fn set_next_avail(&mut self, next_avail: u16) { 565 self.next_avail = Wrapping(next_avail); 566 } 567 next_used(&self) -> u16568 fn next_used(&self) -> u16 { 569 self.next_used.0 570 } 571 set_next_used(&mut self, next_used: u16)572 fn set_next_used(&mut self, next_used: u16) { 573 self.next_used = Wrapping(next_used); 574 } 575 desc_table(&self) -> u64576 fn desc_table(&self) -> u64 { 577 self.desc_table.0 578 } 579 avail_ring(&self) -> u64580 fn avail_ring(&self) -> u64 { 581 self.avail_ring.0 582 } 583 used_ring(&self) -> u64584 fn used_ring(&self) -> u64 { 585 self.used_ring.0 586 } 587 event_idx_enabled(&self) -> bool588 fn event_idx_enabled(&self) -> bool { 589 self.event_idx_enabled 590 } 591 pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>> where M: Clone + Deref, M::Target: GuestMemory,592 fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>> 593 where 594 M: Clone + Deref, 595 M::Target: GuestMemory, 596 { 597 // Default, iter-based impl. Will be subsequently improved. 598 match self.iter(mem) { 599 Ok(mut iter) => iter.next(), 600 Err(e) => { 601 error!("Iterator error {}", e); 602 None 603 } 604 } 605 } 606 } 607 608 impl QueueOwnedT for Queue { iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error> where M: Deref, M::Target: GuestMemory,609 fn iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error> 610 where 611 M: Deref, 612 M::Target: GuestMemory, 613 { 614 // We're checking here that a reset did not happen without re-initializing the queue. 615 // TODO: In the future we might want to also check that the other parameters in the 616 // queue are valid. 617 if !self.ready || self.avail_ring == GuestAddress(0) { 618 return Err(Error::QueueNotReady); 619 } 620 621 self.avail_idx(mem.deref(), Ordering::Acquire) 622 .map(move |idx| AvailIter::new(mem, idx, self))? 623 } 624 go_to_previous_position(&mut self)625 fn go_to_previous_position(&mut self) { 626 self.next_avail -= Wrapping(1); 627 } 628 } 629 630 /// Consuming iterator over all available descriptor chain heads in the queue. 631 /// 632 /// # Example 633 /// 634 /// ```rust 635 /// # use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE}; 636 /// # use virtio_queue::mock::MockSplitQueue; 637 /// use virtio_queue::{Descriptor, Queue, QueueOwnedT}; 638 /// use vm_memory::{GuestAddress, GuestMemoryMmap}; 639 /// 640 /// # fn populate_queue(m: &GuestMemoryMmap) -> Queue { 641 /// # let vq = MockSplitQueue::new(m, 16); 642 /// # let mut q: Queue = vq.create_queue().unwrap(); 643 /// # 644 /// # // The chains are (0, 1), (2, 3, 4) and (5, 6). 645 /// # let mut descs = Vec::new(); 646 /// # for i in 0..7 { 647 /// # let flags = match i { 648 /// # 1 | 6 => 0, 649 /// # 2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, 650 /// # 4 => VRING_DESC_F_WRITE, 651 /// # _ => VRING_DESC_F_NEXT, 652 /// # }; 653 /// # 654 /// # descs.push(Descriptor::new((0x1000 * (i + 1)) as u64, 0x1000, flags as u16, i + 1)); 655 /// # } 656 /// # 657 /// # vq.add_desc_chains(&descs, 0).unwrap(); 658 /// # q 659 /// # } 660 /// let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 661 /// // Populate the queue with descriptor chains and update the available ring accordingly. 662 /// let mut queue = populate_queue(m); 663 /// let mut i = queue.iter(m).unwrap(); 664 /// 665 /// { 666 /// let mut c = i.next().unwrap(); 667 /// let _first_head_index = c.head_index(); 668 /// // We should have two descriptors in the first chain. 669 /// let _desc1 = c.next().unwrap(); 670 /// let _desc2 = c.next().unwrap(); 671 /// } 672 /// 673 /// { 674 /// let c = i.next().unwrap(); 675 /// let _second_head_index = c.head_index(); 676 /// 677 /// let mut iter = c.writable(); 678 /// // We should have two writable descriptors in the second chain. 679 /// let _desc1 = iter.next().unwrap(); 680 /// let _desc2 = iter.next().unwrap(); 681 /// } 682 /// 683 /// { 684 /// let c = i.next().unwrap(); 685 /// let _third_head_index = c.head_index(); 686 /// 687 /// let mut iter = c.readable(); 688 /// // We should have one readable descriptor in the third chain. 689 /// let _desc1 = iter.next().unwrap(); 690 /// } 691 /// // Let's go back one position in the available ring. 692 /// i.go_to_previous_position(); 693 /// // We should be able to access again the third descriptor chain. 694 /// let c = i.next().unwrap(); 695 /// let _third_head_index = c.head_index(); 696 /// ``` 697 #[derive(Debug)] 698 pub struct AvailIter<'b, M> { 699 mem: M, 700 desc_table: GuestAddress, 701 avail_ring: GuestAddress, 702 queue_size: u16, 703 last_index: Wrapping<u16>, 704 next_avail: &'b mut Wrapping<u16>, 705 } 706 707 impl<'b, M> AvailIter<'b, M> 708 where 709 M: Deref, 710 M::Target: GuestMemory, 711 { 712 /// Create a new instance of `AvailInter`. 713 /// 714 /// # Arguments 715 /// * `mem` - the `GuestMemory` object that can be used to access the queue buffers. 716 /// * `idx` - the index of the available ring entry where the driver would put the next 717 /// available descriptor chain. 718 /// * `queue` - the `Queue` object from which the needed data to create the `AvailIter` can 719 /// be retrieved. new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error>720 pub(crate) fn new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error> { 721 // The number of descriptor chain heads to process should always 722 // be smaller or equal to the queue size, as the driver should 723 // never ask the VMM to process a available ring entry more than 724 // once. Checking and reporting such incorrect driver behavior 725 // can prevent potential hanging and Denial-of-Service from 726 // happening on the VMM side. 727 if (idx - queue.next_avail).0 > queue.size { 728 return Err(Error::InvalidAvailRingIndex); 729 } 730 731 Ok(AvailIter { 732 mem, 733 desc_table: queue.desc_table, 734 avail_ring: queue.avail_ring, 735 queue_size: queue.size, 736 last_index: idx, 737 next_avail: &mut queue.next_avail, 738 }) 739 } 740 741 /// Goes back one position in the available descriptor chain offered by the driver. 742 /// 743 /// Rust does not support bidirectional iterators. This is the only way to revert the effect 744 /// of an iterator increment on the queue. 745 /// 746 /// Note: this method assumes there's only one thread manipulating the queue, so it should only 747 /// be invoked in single-threaded context. go_to_previous_position(&mut self)748 pub fn go_to_previous_position(&mut self) { 749 *self.next_avail -= Wrapping(1); 750 } 751 } 752 753 impl<'b, M> Iterator for AvailIter<'b, M> 754 where 755 M: Clone + Deref, 756 M::Target: GuestMemory, 757 { 758 type Item = DescriptorChain<M>; 759 next(&mut self) -> Option<Self::Item>760 fn next(&mut self) -> Option<Self::Item> { 761 if *self.next_avail == self.last_index { 762 return None; 763 } 764 765 // These two operations can not overflow an u64 since they're working with relatively small 766 // numbers compared to u64::MAX. 767 let elem_off = 768 u64::from(self.next_avail.0.checked_rem(self.queue_size)?) * VIRTQ_AVAIL_ELEMENT_SIZE; 769 let offset = VIRTQ_AVAIL_RING_HEADER_SIZE + elem_off; 770 771 let addr = self.avail_ring.checked_add(offset)?; 772 let head_index: u16 = self 773 .mem 774 .load(addr, Ordering::Acquire) 775 .map(u16::from_le) 776 .map_err(|_| error!("Failed to read from memory {:x}", addr.raw_value())) 777 .ok()?; 778 779 *self.next_avail += Wrapping(1); 780 781 Some(DescriptorChain::new( 782 self.mem.clone(), 783 self.desc_table, 784 self.queue_size, 785 head_index, 786 )) 787 } 788 } 789 790 #[cfg(any(test, feature = "test-utils"))] 791 // It is convenient for tests to implement `PartialEq`, but it is not a 792 // proper implementation as `GuestMemory` errors cannot implement `PartialEq`. 793 impl PartialEq for Error { eq(&self, other: &Self) -> bool794 fn eq(&self, other: &Self) -> bool { 795 format!("{}", &self) == format!("{}", other) 796 } 797 } 798 799 #[cfg(test)] 800 mod tests { 801 use super::*; 802 use crate::defs::{DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR}; 803 use crate::mock::MockSplitQueue; 804 use crate::Descriptor; 805 use virtio_bindings::bindings::virtio_ring::{ 806 VRING_DESC_F_NEXT, VRING_DESC_F_WRITE, VRING_USED_F_NO_NOTIFY, 807 }; 808 809 use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap}; 810 811 #[test] test_queue_is_valid()812 fn test_queue_is_valid() { 813 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 814 let vq = MockSplitQueue::new(m, 16); 815 let mut q: Queue = vq.create_queue().unwrap(); 816 817 // q is currently valid 818 assert!(q.is_valid(m)); 819 820 // shouldn't be valid when not marked as ready 821 q.set_ready(false); 822 assert!(!q.ready()); 823 assert!(!q.is_valid(m)); 824 q.set_ready(true); 825 826 // shouldn't be allowed to set a size > max_size 827 q.set_size(q.max_size() << 1); 828 assert_eq!(q.size, q.max_size()); 829 830 // or set the size to 0 831 q.set_size(0); 832 assert_eq!(q.size, q.max_size()); 833 834 // or set a size which is not a power of 2 835 q.set_size(11); 836 assert_eq!(q.size, q.max_size()); 837 838 // but should be allowed to set a size if 0 < size <= max_size and size is a power of two 839 q.set_size(4); 840 assert_eq!(q.size, 4); 841 q.size = q.max_size(); 842 843 // shouldn't be allowed to set an address that breaks the alignment constraint 844 q.set_desc_table_address(Some(0xf), None); 845 assert_eq!(q.desc_table.0, vq.desc_table_addr().0); 846 // should be allowed to set an aligned out of bounds address 847 q.set_desc_table_address(Some(0xffff_fff0), None); 848 assert_eq!(q.desc_table.0, 0xffff_fff0); 849 // but shouldn't be valid 850 assert!(!q.is_valid(m)); 851 // but should be allowed to set a valid description table address 852 q.set_desc_table_address(Some(0x10), None); 853 assert_eq!(q.desc_table.0, 0x10); 854 assert!(q.is_valid(m)); 855 let addr = vq.desc_table_addr().0; 856 q.set_desc_table_address(Some(addr as u32), Some((addr >> 32) as u32)); 857 858 // shouldn't be allowed to set an address that breaks the alignment constraint 859 q.set_avail_ring_address(Some(0x1), None); 860 assert_eq!(q.avail_ring.0, vq.avail_addr().0); 861 // should be allowed to set an aligned out of bounds address 862 q.set_avail_ring_address(Some(0xffff_fffe), None); 863 assert_eq!(q.avail_ring.0, 0xffff_fffe); 864 // but shouldn't be valid 865 assert!(!q.is_valid(m)); 866 // but should be allowed to set a valid available ring address 867 q.set_avail_ring_address(Some(0x2), None); 868 assert_eq!(q.avail_ring.0, 0x2); 869 assert!(q.is_valid(m)); 870 let addr = vq.avail_addr().0; 871 q.set_avail_ring_address(Some(addr as u32), Some((addr >> 32) as u32)); 872 873 // shouldn't be allowed to set an address that breaks the alignment constraint 874 q.set_used_ring_address(Some(0x3), None); 875 assert_eq!(q.used_ring.0, vq.used_addr().0); 876 // should be allowed to set an aligned out of bounds address 877 q.set_used_ring_address(Some(0xffff_fffc), None); 878 assert_eq!(q.used_ring.0, 0xffff_fffc); 879 // but shouldn't be valid 880 assert!(!q.is_valid(m)); 881 // but should be allowed to set a valid used ring address 882 q.set_used_ring_address(Some(0x4), None); 883 assert_eq!(q.used_ring.0, 0x4); 884 let addr = vq.used_addr().0; 885 q.set_used_ring_address(Some(addr as u32), Some((addr >> 32) as u32)); 886 assert!(q.is_valid(m)); 887 } 888 889 #[test] test_add_used()890 fn test_add_used() { 891 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 892 let vq = MockSplitQueue::new(mem, 16); 893 let mut q: Queue = vq.create_queue().unwrap(); 894 895 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(0)); 896 assert_eq!(u16::from_le(vq.used().idx().load()), 0); 897 898 // index too large 899 assert!(q.add_used(mem, 16, 0x1000).is_err()); 900 assert_eq!(u16::from_le(vq.used().idx().load()), 0); 901 902 // should be ok 903 q.add_used(mem, 1, 0x1000).unwrap(); 904 assert_eq!(q.next_used, Wrapping(1)); 905 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(1)); 906 assert_eq!(u16::from_le(vq.used().idx().load()), 1); 907 908 let x = vq.used().ring().ref_at(0).unwrap().load(); 909 assert_eq!(x.id(), 1); 910 assert_eq!(x.len(), 0x1000); 911 } 912 913 #[test] test_reset_queue()914 fn test_reset_queue() { 915 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 916 let vq = MockSplitQueue::new(m, 16); 917 let mut q: Queue = vq.create_queue().unwrap(); 918 919 q.set_size(8); 920 // The address set by `MockSplitQueue` for the descriptor table is DEFAULT_DESC_TABLE_ADDR, 921 // so let's change it for testing the reset. 922 q.set_desc_table_address(Some(0x5000), None); 923 // Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`. 924 q.set_event_idx(true); 925 q.set_next_avail(2); 926 q.set_next_used(4); 927 q.num_added = Wrapping(15); 928 assert_eq!(q.size, 8); 929 // `create_queue` also marks the queue as ready. 930 assert!(q.ready); 931 assert_ne!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR)); 932 assert_ne!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR)); 933 assert_ne!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR)); 934 assert_ne!(q.next_avail, Wrapping(0)); 935 assert_ne!(q.next_used, Wrapping(0)); 936 assert_ne!(q.num_added, Wrapping(0)); 937 assert!(q.event_idx_enabled); 938 939 q.reset(); 940 assert_eq!(q.size, 16); 941 assert!(!q.ready); 942 assert_eq!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR)); 943 assert_eq!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR)); 944 assert_eq!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR)); 945 assert_eq!(q.next_avail, Wrapping(0)); 946 assert_eq!(q.next_used, Wrapping(0)); 947 assert_eq!(q.num_added, Wrapping(0)); 948 assert!(!q.event_idx_enabled); 949 } 950 951 #[test] test_needs_notification()952 fn test_needs_notification() { 953 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 954 let qsize = 16; 955 let vq = MockSplitQueue::new(mem, qsize); 956 let mut q: Queue = vq.create_queue().unwrap(); 957 let avail_addr = vq.avail_addr(); 958 959 // It should always return true when EVENT_IDX isn't enabled. 960 for i in 0..qsize { 961 q.next_used = Wrapping(i); 962 assert!(q.needs_notification(mem).unwrap()); 963 } 964 965 mem.write_obj::<u16>( 966 u16::to_le(4), 967 avail_addr.unchecked_add(4 + qsize as u64 * 2), 968 ) 969 .unwrap(); 970 q.set_event_idx(true); 971 972 // Incrementing up to this value causes an `u16` to wrap back to 0. 973 let wrap = u32::from(u16::MAX) + 1; 974 975 for i in 0..wrap + 12 { 976 q.next_used = Wrapping(i as u16); 977 // Let's test wrapping around the maximum index value as well. 978 // `num_added` needs to be at least `1` to represent the fact that new descriptor 979 // chains have be added to the used ring since the last time `needs_notification` 980 // returned. 981 q.num_added = Wrapping(1); 982 let expected = i == 5 || i == (5 + wrap); 983 assert_eq!((q.needs_notification(mem).unwrap(), i), (expected, i)); 984 } 985 986 mem.write_obj::<u16>( 987 u16::to_le(8), 988 avail_addr.unchecked_add(4 + qsize as u64 * 2), 989 ) 990 .unwrap(); 991 992 // Returns `false` because the current `used_event` value is behind both `next_used` and 993 // the value of `next_used` at the time when `needs_notification` last returned (which is 994 // computed based on `num_added` as described in the comments for `needs_notification`. 995 assert!(!q.needs_notification(mem).unwrap()); 996 997 mem.write_obj::<u16>( 998 u16::to_le(15), 999 avail_addr.unchecked_add(4 + qsize as u64 * 2), 1000 ) 1001 .unwrap(); 1002 1003 q.num_added = Wrapping(1); 1004 assert!(!q.needs_notification(mem).unwrap()); 1005 1006 q.next_used = Wrapping(15); 1007 q.num_added = Wrapping(1); 1008 assert!(!q.needs_notification(mem).unwrap()); 1009 1010 q.next_used = Wrapping(16); 1011 q.num_added = Wrapping(1); 1012 assert!(q.needs_notification(mem).unwrap()); 1013 1014 // Calling `needs_notification` again immediately returns `false`. 1015 assert!(!q.needs_notification(mem).unwrap()); 1016 1017 mem.write_obj::<u16>( 1018 u16::to_le(u16::MAX - 3), 1019 avail_addr.unchecked_add(4 + qsize as u64 * 2), 1020 ) 1021 .unwrap(); 1022 q.next_used = Wrapping(u16::MAX - 2); 1023 q.num_added = Wrapping(1); 1024 // Returns `true` because, when looking at circular sequence of indices of the used ring, 1025 // the value we wrote in the `used_event` appears between the "old" value of `next_used` 1026 // (i.e. `next_used` - `num_added`) and the current `next_used`, thus suggesting that we 1027 // need to notify the driver. 1028 assert!(q.needs_notification(mem).unwrap()); 1029 } 1030 1031 #[test] test_enable_disable_notification()1032 fn test_enable_disable_notification() { 1033 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1034 let vq = MockSplitQueue::new(mem, 16); 1035 1036 let mut q: Queue = vq.create_queue().unwrap(); 1037 let used_addr = vq.used_addr(); 1038 1039 assert!(!q.event_idx_enabled); 1040 1041 q.enable_notification(mem).unwrap(); 1042 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1043 assert_eq!(v, 0); 1044 1045 q.disable_notification(mem).unwrap(); 1046 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1047 assert_eq!(v, VRING_USED_F_NO_NOTIFY as u16); 1048 1049 q.enable_notification(mem).unwrap(); 1050 let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap(); 1051 assert_eq!(v, 0); 1052 1053 q.set_event_idx(true); 1054 let avail_addr = vq.avail_addr(); 1055 mem.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2)) 1056 .unwrap(); 1057 1058 assert!(q.enable_notification(mem).unwrap()); 1059 q.next_avail = Wrapping(2); 1060 assert!(!q.enable_notification(mem).unwrap()); 1061 1062 mem.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2)) 1063 .unwrap(); 1064 1065 assert!(q.enable_notification(mem).unwrap()); 1066 q.next_avail = Wrapping(8); 1067 assert!(!q.enable_notification(mem).unwrap()); 1068 } 1069 1070 #[test] test_consume_chains_with_notif()1071 fn test_consume_chains_with_notif() { 1072 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1073 let vq = MockSplitQueue::new(mem, 16); 1074 1075 let mut q: Queue = vq.create_queue().unwrap(); 1076 1077 // q is currently valid. 1078 assert!(q.is_valid(mem)); 1079 1080 // The chains are (0, 1), (2, 3, 4), (5, 6), (7, 8), (9, 10, 11, 12). 1081 let mut descs = Vec::new(); 1082 for i in 0..13 { 1083 let flags = match i { 1084 1 | 4 | 6 | 8 | 12 => 0, 1085 _ => VRING_DESC_F_NEXT, 1086 }; 1087 1088 descs.push(Descriptor::new( 1089 (0x1000 * (i + 1)) as u64, 1090 0x1000, 1091 flags as u16, 1092 i + 1, 1093 )); 1094 } 1095 1096 vq.add_desc_chains(&descs, 0).unwrap(); 1097 // Update the index of the chain that can be consumed to not be the last one. 1098 // This enables us to consume chains in multiple iterations as opposed to consuming 1099 // all the driver written chains at once. 1100 vq.avail().idx().store(u16::to_le(2)); 1101 // No descriptor chains are consumed at this point. 1102 assert_eq!(q.next_avail(), 0); 1103 1104 let mut i = 0; 1105 1106 loop { 1107 i += 1; 1108 q.disable_notification(mem).unwrap(); 1109 1110 while let Some(chain) = q.iter(mem).unwrap().next() { 1111 // Process the descriptor chain, and then add entries to the 1112 // used ring. 1113 let head_index = chain.head_index(); 1114 let mut desc_len = 0; 1115 chain.for_each(|d| { 1116 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1117 desc_len += d.len(); 1118 } 1119 }); 1120 q.add_used(mem, head_index, desc_len).unwrap(); 1121 } 1122 if !q.enable_notification(mem).unwrap() { 1123 break; 1124 } 1125 } 1126 // The chains should be consumed in a single loop iteration because there's nothing updating 1127 // the `idx` field of the available ring in the meantime. 1128 assert_eq!(i, 1); 1129 // The next chain that can be consumed should have index 2. 1130 assert_eq!(q.next_avail(), 2); 1131 assert_eq!(q.next_used(), 2); 1132 // Let the device know it can consume one more chain. 1133 vq.avail().idx().store(u16::to_le(3)); 1134 i = 0; 1135 1136 loop { 1137 i += 1; 1138 q.disable_notification(mem).unwrap(); 1139 1140 while let Some(chain) = q.iter(mem).unwrap().next() { 1141 // Process the descriptor chain, and then add entries to the 1142 // used ring. 1143 let head_index = chain.head_index(); 1144 let mut desc_len = 0; 1145 chain.for_each(|d| { 1146 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1147 desc_len += d.len(); 1148 } 1149 }); 1150 q.add_used(mem, head_index, desc_len).unwrap(); 1151 } 1152 1153 // For the simplicity of the test we are updating here the `idx` value of the available 1154 // ring. Ideally this should be done on a separate thread. 1155 // Because of this update, the loop should be iterated again to consume the new 1156 // available descriptor chains. 1157 vq.avail().idx().store(u16::to_le(4)); 1158 if !q.enable_notification(mem).unwrap() { 1159 break; 1160 } 1161 } 1162 assert_eq!(i, 2); 1163 // The next chain that can be consumed should have index 4. 1164 assert_eq!(q.next_avail(), 4); 1165 assert_eq!(q.next_used(), 4); 1166 1167 // Set an `idx` that is bigger than the number of entries added in the ring. 1168 // This is an allowed scenario, but the indexes of the chain will have unexpected values. 1169 vq.avail().idx().store(u16::to_le(7)); 1170 loop { 1171 q.disable_notification(mem).unwrap(); 1172 1173 while let Some(chain) = q.iter(mem).unwrap().next() { 1174 // Process the descriptor chain, and then add entries to the 1175 // used ring. 1176 let head_index = chain.head_index(); 1177 let mut desc_len = 0; 1178 chain.for_each(|d| { 1179 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1180 desc_len += d.len(); 1181 } 1182 }); 1183 q.add_used(mem, head_index, desc_len).unwrap(); 1184 } 1185 if !q.enable_notification(mem).unwrap() { 1186 break; 1187 } 1188 } 1189 assert_eq!(q.next_avail(), 7); 1190 assert_eq!(q.next_used(), 7); 1191 } 1192 1193 #[test] test_invalid_avail_idx()1194 fn test_invalid_avail_idx() { 1195 // This is a negative test for the following MUST from the spec: `A driver MUST NOT 1196 // decrement the available idx on a virtqueue (ie. there is no way to “unexpose” buffers).`. 1197 // We validate that for this misconfiguration, the device does not panic. 1198 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1199 let vq = MockSplitQueue::new(mem, 16); 1200 1201 let mut q: Queue = vq.create_queue().unwrap(); 1202 1203 // q is currently valid. 1204 assert!(q.is_valid(mem)); 1205 1206 // The chains are (0, 1), (2, 3, 4), (5, 6). 1207 let mut descs = Vec::new(); 1208 for i in 0..7 { 1209 let flags = match i { 1210 1 | 4 | 6 => 0, 1211 _ => VRING_DESC_F_NEXT, 1212 }; 1213 1214 descs.push(Descriptor::new( 1215 (0x1000 * (i + 1)) as u64, 1216 0x1000, 1217 flags as u16, 1218 i + 1, 1219 )); 1220 } 1221 1222 vq.add_desc_chains(&descs, 0).unwrap(); 1223 // Let the device know it can consume chains with the index < 2. 1224 vq.avail().idx().store(u16::to_le(3)); 1225 // No descriptor chains are consumed at this point. 1226 assert_eq!(q.next_avail(), 0); 1227 assert_eq!(q.next_used(), 0); 1228 1229 loop { 1230 q.disable_notification(mem).unwrap(); 1231 1232 while let Some(chain) = q.iter(mem).unwrap().next() { 1233 // Process the descriptor chain, and then add entries to the 1234 // used ring. 1235 let head_index = chain.head_index(); 1236 let mut desc_len = 0; 1237 chain.for_each(|d| { 1238 if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE { 1239 desc_len += d.len(); 1240 } 1241 }); 1242 q.add_used(mem, head_index, desc_len).unwrap(); 1243 } 1244 if !q.enable_notification(mem).unwrap() { 1245 break; 1246 } 1247 } 1248 // The next chain that can be consumed should have index 3. 1249 assert_eq!(q.next_avail(), 3); 1250 assert_eq!(q.avail_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3)); 1251 assert_eq!(q.next_used(), 3); 1252 assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3)); 1253 assert!(q.lock().ready()); 1254 1255 // Decrement `idx` which should be forbidden. We don't enforce this thing, but we should 1256 // test that we don't panic in case the driver decrements it. 1257 vq.avail().idx().store(u16::to_le(1)); 1258 // Invalid available ring index 1259 assert!(q.iter(mem).is_err()); 1260 } 1261 1262 #[test] test_iterator_and_avail_idx()1263 fn test_iterator_and_avail_idx() { 1264 // This test ensures constructing a descriptor chain iterator succeeds 1265 // with valid available ring indexes while produces an error with invalid 1266 // indexes. 1267 let queue_size = 2; 1268 let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1269 let vq = MockSplitQueue::new(mem, queue_size); 1270 1271 let mut q: Queue = vq.create_queue().unwrap(); 1272 1273 // q is currently valid. 1274 assert!(q.is_valid(mem)); 1275 1276 // Create descriptors to fill up the queue 1277 let mut descs = Vec::new(); 1278 for i in 0..queue_size { 1279 descs.push(Descriptor::new( 1280 (0x1000 * (i + 1)) as u64, 1281 0x1000, 1282 0_u16, 1283 i + 1, 1284 )); 1285 } 1286 vq.add_desc_chains(&descs, 0).unwrap(); 1287 1288 // Set the 'next_available' index to 'u16:MAX' to test the wrapping scenarios 1289 q.set_next_avail(u16::MAX); 1290 1291 // When the number of chains exposed by the driver is equal to or less than the queue 1292 // size, the available ring index is valid and constructs an iterator successfully. 1293 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size); 1294 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1295 assert!(q.iter(mem).is_ok()); 1296 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size - 1); 1297 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1298 assert!(q.iter(mem).is_ok()); 1299 1300 // When the number of chains exposed by the driver is larger than the queue size, the 1301 // available ring index is invalid and produces an error from constructing an iterator. 1302 let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size + 1); 1303 vq.avail().idx().store(u16::to_le(avail_idx.0)); 1304 assert!(q.iter(mem).is_err()); 1305 } 1306 1307 #[test] test_descriptor_and_iterator()1308 fn test_descriptor_and_iterator() { 1309 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1310 let vq = MockSplitQueue::new(m, 16); 1311 1312 let mut q: Queue = vq.create_queue().unwrap(); 1313 1314 // q is currently valid 1315 assert!(q.is_valid(m)); 1316 1317 // the chains are (0, 1), (2, 3, 4) and (5, 6) 1318 let mut descs = Vec::new(); 1319 for j in 0..7 { 1320 let flags = match j { 1321 1 | 6 => 0, 1322 2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE, 1323 4 => VRING_DESC_F_WRITE, 1324 _ => VRING_DESC_F_NEXT, 1325 }; 1326 1327 descs.push(Descriptor::new( 1328 (0x1000 * (j + 1)) as u64, 1329 0x1000, 1330 flags as u16, 1331 j + 1, 1332 )); 1333 } 1334 1335 vq.add_desc_chains(&descs, 0).unwrap(); 1336 1337 let mut i = q.iter(m).unwrap(); 1338 1339 { 1340 let c = i.next().unwrap(); 1341 assert_eq!(c.head_index(), 0); 1342 1343 let mut iter = c; 1344 assert!(iter.next().is_some()); 1345 assert!(iter.next().is_some()); 1346 assert!(iter.next().is_none()); 1347 assert!(iter.next().is_none()); 1348 } 1349 1350 { 1351 let c = i.next().unwrap(); 1352 assert_eq!(c.head_index(), 2); 1353 1354 let mut iter = c.writable(); 1355 assert!(iter.next().is_some()); 1356 assert!(iter.next().is_some()); 1357 assert!(iter.next().is_none()); 1358 assert!(iter.next().is_none()); 1359 } 1360 1361 { 1362 let c = i.next().unwrap(); 1363 assert_eq!(c.head_index(), 5); 1364 1365 let mut iter = c.readable(); 1366 assert!(iter.next().is_some()); 1367 assert!(iter.next().is_none()); 1368 assert!(iter.next().is_none()); 1369 } 1370 } 1371 1372 #[test] test_iterator()1373 fn test_iterator() { 1374 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1375 let vq = MockSplitQueue::new(m, 16); 1376 1377 let mut q: Queue = vq.create_queue().unwrap(); 1378 1379 q.size = q.max_size; 1380 q.desc_table = vq.desc_table_addr(); 1381 q.avail_ring = vq.avail_addr(); 1382 q.used_ring = vq.used_addr(); 1383 assert!(q.is_valid(m)); 1384 1385 { 1386 // an invalid queue should return an iterator with no next 1387 q.ready = false; 1388 assert!(q.iter(m).is_err()); 1389 } 1390 1391 q.ready = true; 1392 1393 // now let's create two simple descriptor chains 1394 // the chains are (0, 1) and (2, 3, 4) 1395 { 1396 let mut descs = Vec::new(); 1397 for j in 0..5u16 { 1398 let flags = match j { 1399 1 | 4 => 0, 1400 _ => VRING_DESC_F_NEXT, 1401 }; 1402 1403 descs.push(Descriptor::new( 1404 (0x1000 * (j + 1)) as u64, 1405 0x1000, 1406 flags as u16, 1407 j + 1, 1408 )); 1409 } 1410 vq.add_desc_chains(&descs, 0).unwrap(); 1411 1412 let mut i = q.iter(m).unwrap(); 1413 1414 { 1415 let mut c = i.next().unwrap(); 1416 assert_eq!(c.head_index(), 0); 1417 1418 c.next().unwrap(); 1419 assert!(c.next().is_some()); 1420 assert!(c.next().is_none()); 1421 assert_eq!(c.head_index(), 0); 1422 } 1423 1424 { 1425 let mut c = i.next().unwrap(); 1426 assert_eq!(c.head_index(), 2); 1427 1428 c.next().unwrap(); 1429 c.next().unwrap(); 1430 c.next().unwrap(); 1431 assert!(c.next().is_none()); 1432 assert_eq!(c.head_index(), 2); 1433 } 1434 1435 // also test go_to_previous_position() works as expected 1436 { 1437 assert!(i.next().is_none()); 1438 i.go_to_previous_position(); 1439 let mut c = q.iter(m).unwrap().next().unwrap(); 1440 c.next().unwrap(); 1441 c.next().unwrap(); 1442 c.next().unwrap(); 1443 assert!(c.next().is_none()); 1444 } 1445 } 1446 1447 // Test that iterating some broken descriptor chain does not exceed 1448 // 2^32 bytes in total (VIRTIO spec version 1.2, 2.7.5.2: 1449 // Drivers MUST NOT add a descriptor chain longer than 2^32 bytes in 1450 // total) 1451 { 1452 let descs = vec![ 1453 Descriptor::new(0x1000, 0xffff_ffff, VRING_DESC_F_NEXT as u16, 1), 1454 Descriptor::new(0x1000, 0x1234_5678, 0, 2), 1455 ]; 1456 vq.add_desc_chains(&descs, 0).unwrap(); 1457 let mut yielded_bytes_by_iteration = 0_u32; 1458 for d in q.iter(m).unwrap().next().unwrap() { 1459 yielded_bytes_by_iteration = yielded_bytes_by_iteration 1460 .checked_add(d.len()) 1461 .expect("iterator should not yield more than 2^32 bytes"); 1462 } 1463 } 1464 1465 // Same as above, but test with a descriptor which is self-referential 1466 { 1467 let descs = vec![Descriptor::new( 1468 0x1000, 1469 0xffff_ffff, 1470 VRING_DESC_F_NEXT as u16, 1471 0, 1472 )]; 1473 vq.add_desc_chains(&descs, 0).unwrap(); 1474 let mut yielded_bytes_by_iteration = 0_u32; 1475 for d in q.iter(m).unwrap().next().unwrap() { 1476 yielded_bytes_by_iteration = yielded_bytes_by_iteration 1477 .checked_add(d.len()) 1478 .expect("iterator should not yield more than 2^32 bytes"); 1479 } 1480 } 1481 } 1482 1483 #[test] test_regression_iterator_division()1484 fn test_regression_iterator_division() { 1485 // This is a regression test that tests that the iterator does not try to divide 1486 // by 0 when the queue size is 0 1487 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(); 1488 let vq = MockSplitQueue::new(m, 1); 1489 // This input was generated by the fuzzer, both for the QueueS and the Descriptor 1490 let descriptors: Vec<Descriptor> = vec![Descriptor::new( 1491 14178673876262995140, 1492 3301229764, 1493 50372, 1494 50372, 1495 )]; 1496 vq.build_desc_chain(&descriptors).unwrap(); 1497 1498 let mut q = Queue { 1499 max_size: 38, 1500 next_avail: Wrapping(0), 1501 next_used: Wrapping(0), 1502 event_idx_enabled: false, 1503 num_added: Wrapping(0), 1504 size: 0, 1505 ready: false, 1506 desc_table: GuestAddress(12837708984796196), 1507 avail_ring: GuestAddress(0), 1508 used_ring: GuestAddress(9943947977301164032), 1509 }; 1510 1511 assert!(q.pop_descriptor_chain(m).is_none()); 1512 } 1513 1514 #[test] test_setters_error_cases()1515 fn test_setters_error_cases() { 1516 assert_eq!(Queue::new(15).unwrap_err(), Error::InvalidMaxSize); 1517 let mut q = Queue::new(16).unwrap(); 1518 1519 let expected_val = q.desc_table.0; 1520 assert_eq!( 1521 q.try_set_desc_table_address(GuestAddress(0xf)).unwrap_err(), 1522 Error::InvalidDescTableAlign 1523 ); 1524 assert_eq!(q.desc_table(), expected_val); 1525 1526 let expected_val = q.avail_ring.0; 1527 assert_eq!( 1528 q.try_set_avail_ring_address(GuestAddress(0x1)).unwrap_err(), 1529 Error::InvalidAvailRingAlign 1530 ); 1531 assert_eq!(q.avail_ring(), expected_val); 1532 1533 let expected_val = q.used_ring.0; 1534 assert_eq!( 1535 q.try_set_used_ring_address(GuestAddress(0x3)).unwrap_err(), 1536 Error::InvalidUsedRingAlign 1537 ); 1538 assert_eq!(q.used_ring(), expected_val); 1539 1540 let expected_val = q.size; 1541 assert_eq!(q.try_set_size(15).unwrap_err(), Error::InvalidSize); 1542 assert_eq!(q.size(), expected_val) 1543 } 1544 1545 #[test] 1546 // This is a regression test for a fuzzing finding. If the driver requests a reset of the 1547 // device, but then does not re-initializes the queue then a subsequent call to process 1548 // a request should yield no descriptors to process. Before this fix we were processing 1549 // descriptors that were added to the queue before, and we were ending up processing 255 1550 // descriptors per chain. test_regression_timeout_after_reset()1551 fn test_regression_timeout_after_reset() { 1552 // The input below was generated by libfuzzer and adapted for this test. 1553 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x10000)]).unwrap(); 1554 let vq = MockSplitQueue::new(m, 1024); 1555 1556 // This input below was generated by the fuzzer. 1557 let descriptors: Vec<Descriptor> = vec![ 1558 Descriptor::new(21508325467, 0, 1, 4), 1559 Descriptor::new(2097152, 4096, 3, 0), 1560 Descriptor::new(18374686479672737792, 4294967295, 65535, 29), 1561 Descriptor::new(76842670169653248, 1114115, 0, 0), 1562 Descriptor::new(16, 983040, 126, 3), 1563 Descriptor::new(897648164864, 0, 0, 0), 1564 Descriptor::new(111669149722, 0, 0, 0), 1565 ]; 1566 vq.build_multiple_desc_chains(&descriptors).unwrap(); 1567 1568 let mut q: Queue = vq.create_queue().unwrap(); 1569 1570 // Setting the queue to ready should not allow consuming descriptors after reset. 1571 q.reset(); 1572 q.set_ready(true); 1573 let mut counter = 0; 1574 while let Some(mut desc_chain) = q.pop_descriptor_chain(m) { 1575 // this empty loop is here to check that there are no side effects 1576 // in terms of memory & execution time. 1577 while desc_chain.next().is_some() { 1578 counter += 1; 1579 } 1580 } 1581 assert_eq!(counter, 0); 1582 1583 // Setting the avail_addr to valid should not allow consuming descriptors after reset. 1584 q.reset(); 1585 q.set_avail_ring_address(Some(0x1000), None); 1586 assert_eq!(q.avail_ring, GuestAddress(0x1000)); 1587 counter = 0; 1588 while let Some(mut desc_chain) = q.pop_descriptor_chain(m) { 1589 // this empty loop is here to check that there are no side effects 1590 // in terms of memory & execution time. 1591 while desc_chain.next().is_some() { 1592 counter += 1; 1593 } 1594 } 1595 assert_eq!(counter, 0); 1596 } 1597 } 1598