queue.rs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. #[cfg(test)]
  2. use core::cmp::min;
  3. use core::mem::size_of;
  4. use core::ptr::{self, addr_of_mut, NonNull};
  5. use core::sync::atomic::{fence, Ordering};
  6. use super::*;
  7. use crate::transport::Transport;
  8. use bitflags::*;
  9. /// The mechanism for bulk data transport on virtio devices.
  10. ///
  11. /// Each device can have zero or more virtqueues.
  12. #[derive(Debug)]
  13. pub struct VirtQueue<H: Hal> {
  14. /// DMA guard
  15. dma: DMA<H>,
  16. /// Descriptor table
  17. desc: NonNull<[Descriptor]>,
  18. /// Available ring
  19. avail: NonNull<AvailRing>,
  20. /// Used ring
  21. used: NonNull<UsedRing>,
  22. /// The index of queue
  23. queue_idx: u16,
  24. /// The size of the queue.
  25. ///
  26. /// This is both the number of descriptors, and the number of slots in the available and used
  27. /// rings.
  28. queue_size: u16,
  29. /// The number of used queues.
  30. num_used: u16,
  31. /// The head desc index of the free list.
  32. free_head: u16,
  33. avail_idx: u16,
  34. last_used_idx: u16,
  35. }
  36. impl<H: Hal> VirtQueue<H> {
  37. /// Create a new VirtQueue.
  38. pub fn new<T: Transport>(transport: &mut T, idx: u16, size: u16) -> Result<Self> {
  39. if transport.queue_used(idx) {
  40. return Err(Error::AlreadyUsed);
  41. }
  42. if !size.is_power_of_two() || transport.max_queue_size() < size as u32 {
  43. return Err(Error::InvalidParam);
  44. }
  45. let layout = VirtQueueLayout::new(size);
  46. // Allocate contiguous pages.
  47. let dma = DMA::new(layout.size / PAGE_SIZE)?;
  48. transport.queue_set(
  49. idx,
  50. size as u32,
  51. dma.paddr(),
  52. dma.paddr() + layout.avail_offset,
  53. dma.paddr() + layout.used_offset,
  54. );
  55. let desc = NonNull::new(ptr::slice_from_raw_parts_mut(
  56. dma.vaddr() as *mut Descriptor,
  57. size as usize,
  58. ))
  59. .unwrap();
  60. let avail = NonNull::new((dma.vaddr() + layout.avail_offset) as *mut AvailRing).unwrap();
  61. let used = NonNull::new((dma.vaddr() + layout.used_offset) as *mut UsedRing).unwrap();
  62. // Link descriptors together.
  63. for i in 0..(size - 1) {
  64. // Safe because `desc` is properly aligned, dereferenceable, initialised, and the device
  65. // won't access the descriptors for the duration of this unsafe block.
  66. unsafe {
  67. (*desc.as_ptr())[i as usize].next = i + 1;
  68. }
  69. }
  70. Ok(VirtQueue {
  71. dma,
  72. desc,
  73. avail,
  74. used,
  75. queue_size: size,
  76. queue_idx: idx,
  77. num_used: 0,
  78. free_head: 0,
  79. avail_idx: 0,
  80. last_used_idx: 0,
  81. })
  82. }
  83. /// Add buffers to the virtqueue, return a token.
  84. ///
  85. /// Ref: linux virtio_ring.c virtqueue_add
  86. ///
  87. /// # Safety
  88. ///
  89. /// The input and output buffers must remain valid until the token is returned by `pop_used`.
  90. pub unsafe fn add(&mut self, inputs: &[*const [u8]], outputs: &[*mut [u8]]) -> Result<u16> {
  91. if inputs.is_empty() && outputs.is_empty() {
  92. return Err(Error::InvalidParam);
  93. }
  94. if inputs.len() + outputs.len() + self.num_used as usize > self.queue_size as usize {
  95. return Err(Error::BufferTooSmall);
  96. }
  97. // allocate descriptors from free list
  98. let head = self.free_head;
  99. let mut last = self.free_head;
  100. // Safe because self.desc is properly aligned, dereferenceable and initialised, and nothing
  101. // else reads or writes the free descriptors during this block.
  102. unsafe {
  103. for input in inputs.iter() {
  104. let mut desc = self.desc_ptr(self.free_head);
  105. (*desc).set_buf::<H>(NonNull::new(*input as *mut [u8]).unwrap());
  106. (*desc).flags = DescFlags::NEXT;
  107. last = self.free_head;
  108. self.free_head = (*desc).next;
  109. }
  110. for output in outputs.iter() {
  111. let desc = self.desc_ptr(self.free_head);
  112. (*desc).set_buf::<H>(NonNull::new(*output).unwrap());
  113. (*desc).flags = DescFlags::NEXT | DescFlags::WRITE;
  114. last = self.free_head;
  115. self.free_head = (*desc).next;
  116. }
  117. // set last_elem.next = NULL
  118. (*self.desc_ptr(last)).flags.remove(DescFlags::NEXT);
  119. }
  120. self.num_used += (inputs.len() + outputs.len()) as u16;
  121. let avail_slot = self.avail_idx & (self.queue_size - 1);
  122. // Safe because self.avail is properly aligned, dereferenceable and initialised.
  123. unsafe {
  124. (*self.avail.as_ptr()).ring[avail_slot as usize] = head;
  125. }
  126. // Write barrier so that device sees changes to descriptor table and available ring before
  127. // change to available index.
  128. fence(Ordering::SeqCst);
  129. // increase head of avail ring
  130. self.avail_idx = self.avail_idx.wrapping_add(1);
  131. // Safe because self.avail is properly aligned, dereferenceable and initialised.
  132. unsafe {
  133. (*self.avail.as_ptr()).idx = self.avail_idx;
  134. }
  135. // Write barrier so that device can see change to available index after this method returns.
  136. fence(Ordering::SeqCst);
  137. Ok(head)
  138. }
  139. /// Returns a non-null pointer to the descriptor at the given index.
  140. fn desc_ptr(&mut self, index: u16) -> *mut Descriptor {
  141. // Safe because self.desc is properly aligned and dereferenceable.
  142. unsafe { addr_of_mut!((*self.desc.as_ptr())[index as usize]) }
  143. }
  144. /// Returns whether there is a used element that can be popped.
  145. pub fn can_pop(&self) -> bool {
  146. // Read barrier, so we read a fresh value from the device.
  147. fence(Ordering::SeqCst);
  148. // Safe because self.used points to a valid, aligned, initialised, dereferenceable, readable
  149. // instance of UsedRing.
  150. self.last_used_idx != unsafe { (*self.used.as_ptr()).idx }
  151. }
  152. /// Returns the number of free descriptors.
  153. pub fn available_desc(&self) -> usize {
  154. (self.queue_size - self.num_used) as usize
  155. }
  156. /// Recycle descriptors in the list specified by head.
  157. ///
  158. /// This will push all linked descriptors at the front of the free list.
  159. fn recycle_descriptors(&mut self, mut head: u16) {
  160. let original_free_head = self.free_head;
  161. self.free_head = head;
  162. loop {
  163. let desc = self.desc_ptr(head);
  164. // Safe because self.desc is properly aligned, dereferenceable and initialised, and
  165. // nothing else reads or writes the descriptor during this block.
  166. unsafe {
  167. let flags = (*desc).flags;
  168. self.num_used -= 1;
  169. if flags.contains(DescFlags::NEXT) {
  170. head = (*desc).next;
  171. } else {
  172. (*desc).next = original_free_head;
  173. return;
  174. }
  175. }
  176. }
  177. }
  178. /// Get a token from device used buffers, return (token, len).
  179. ///
  180. /// Ref: linux virtio_ring.c virtqueue_get_buf_ctx
  181. pub fn pop_used(&mut self) -> Result<(u16, u32)> {
  182. if !self.can_pop() {
  183. return Err(Error::NotReady);
  184. }
  185. // read barrier
  186. fence(Ordering::SeqCst);
  187. let last_used_slot = self.last_used_idx & (self.queue_size - 1);
  188. let index;
  189. let len;
  190. // Safe because self.used points to a valid, aligned, initialised, dereferenceable, readable
  191. // instance of UsedRing.
  192. unsafe {
  193. index = (*self.used.as_ptr()).ring[last_used_slot as usize].id as u16;
  194. len = (*self.used.as_ptr()).ring[last_used_slot as usize].len;
  195. }
  196. self.recycle_descriptors(index);
  197. self.last_used_idx = self.last_used_idx.wrapping_add(1);
  198. Ok((index, len))
  199. }
  200. /// Return size of the queue.
  201. pub fn size(&self) -> u16 {
  202. self.queue_size
  203. }
  204. }
  205. /// The inner layout of a VirtQueue.
  206. ///
  207. /// Ref: 2.6.2 Legacy Interfaces: A Note on Virtqueue Layout
  208. struct VirtQueueLayout {
  209. avail_offset: usize,
  210. used_offset: usize,
  211. size: usize,
  212. }
  213. impl VirtQueueLayout {
  214. fn new(queue_size: u16) -> Self {
  215. assert!(
  216. queue_size.is_power_of_two(),
  217. "queue size should be a power of 2"
  218. );
  219. let queue_size = queue_size as usize;
  220. let desc = size_of::<Descriptor>() * queue_size;
  221. let avail = size_of::<u16>() * (3 + queue_size);
  222. let used = size_of::<u16>() * 3 + size_of::<UsedElem>() * queue_size;
  223. VirtQueueLayout {
  224. avail_offset: desc,
  225. used_offset: align_up(desc + avail),
  226. size: align_up(desc + avail) + align_up(used),
  227. }
  228. }
  229. }
  230. #[repr(C, align(16))]
  231. #[derive(Debug)]
  232. pub(crate) struct Descriptor {
  233. addr: u64,
  234. len: u32,
  235. flags: DescFlags,
  236. next: u16,
  237. }
  238. impl Descriptor {
  239. /// # Safety
  240. ///
  241. /// The caller must ensure that the buffer lives at least as long as the descriptor is active.
  242. unsafe fn set_buf<H: Hal>(&mut self, buf: NonNull<[u8]>) {
  243. self.addr = H::virt_to_phys(buf.as_ptr() as *mut u8 as usize) as u64;
  244. self.len = buf.len() as u32;
  245. }
  246. }
  247. bitflags! {
  248. /// Descriptor flags
  249. struct DescFlags: u16 {
  250. const NEXT = 1;
  251. const WRITE = 2;
  252. const INDIRECT = 4;
  253. }
  254. }
  255. /// The driver uses the available ring to offer buffers to the device:
  256. /// each ring entry refers to the head of a descriptor chain.
  257. /// It is only written by the driver and read by the device.
  258. #[repr(C)]
  259. #[derive(Debug)]
  260. struct AvailRing {
  261. flags: u16,
  262. /// A driver MUST NOT decrement the idx.
  263. idx: u16,
  264. ring: [u16; 32], // actual size: queue_size
  265. used_event: u16, // unused
  266. }
  267. /// The used ring is where the device returns buffers once it is done with them:
  268. /// it is only written to by the device, and read by the driver.
  269. #[repr(C)]
  270. #[derive(Debug)]
  271. struct UsedRing {
  272. flags: u16,
  273. idx: u16,
  274. ring: [UsedElem; 32], // actual size: queue_size
  275. avail_event: u16, // unused
  276. }
  277. #[repr(C)]
  278. #[derive(Debug)]
  279. struct UsedElem {
  280. id: u32,
  281. len: u32,
  282. }
  283. /// Simulates the device writing to a VirtIO queue, for use in tests.
  284. ///
  285. /// The fake device always uses descriptors in order.
  286. #[cfg(test)]
  287. pub(crate) fn fake_write_to_queue(
  288. queue_size: u16,
  289. receive_queue_descriptors: *const Descriptor,
  290. receive_queue_driver_area: VirtAddr,
  291. receive_queue_device_area: VirtAddr,
  292. data: &[u8],
  293. ) {
  294. let descriptors = ptr::slice_from_raw_parts(receive_queue_descriptors, queue_size as usize);
  295. let available_ring = receive_queue_driver_area as *const AvailRing;
  296. let used_ring = receive_queue_device_area as *mut UsedRing;
  297. // Safe because the various pointers are properly aligned, dereferenceable, initialised, and
  298. // nothing else accesses them during this block.
  299. unsafe {
  300. // Make sure there is actually at least one descriptor available to write to.
  301. assert_ne!((*available_ring).idx, (*used_ring).idx);
  302. // The fake device always uses descriptors in order, like VIRTIO_F_IN_ORDER, so
  303. // `used_ring.idx` marks the next descriptor we should take from the available ring.
  304. let next_slot = (*used_ring).idx & (queue_size - 1);
  305. let head_descriptor_index = (*available_ring).ring[next_slot as usize];
  306. let mut descriptor = &(*descriptors)[head_descriptor_index as usize];
  307. // Loop through all descriptors in the chain, writing data to them.
  308. let mut remaining_data = data;
  309. loop {
  310. // Check the buffer and write to it.
  311. let flags = descriptor.flags;
  312. assert!(flags.contains(DescFlags::WRITE));
  313. let buffer_length = descriptor.len as usize;
  314. let length_to_write = min(remaining_data.len(), buffer_length);
  315. ptr::copy(
  316. remaining_data.as_ptr(),
  317. descriptor.addr as *mut u8,
  318. length_to_write,
  319. );
  320. remaining_data = &remaining_data[length_to_write..];
  321. if flags.contains(DescFlags::NEXT) {
  322. let next = descriptor.next as usize;
  323. descriptor = &(*descriptors)[next];
  324. } else {
  325. assert_eq!(remaining_data.len(), 0);
  326. break;
  327. }
  328. }
  329. // Mark the buffer as used.
  330. (*used_ring).ring[next_slot as usize].id = head_descriptor_index as u32;
  331. (*used_ring).ring[next_slot as usize].len = data.len() as u32;
  332. (*used_ring).idx += 1;
  333. }
  334. }
  335. #[cfg(test)]
  336. mod tests {
  337. use super::*;
  338. use crate::{hal::fake::FakeHal, transport::mmio::MODERN_VERSION};
  339. use core::ptr::NonNull;
  340. #[test]
  341. fn invalid_queue_size() {
  342. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  343. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  344. // Size not a power of 2.
  345. assert_eq!(
  346. VirtQueue::<FakeHal>::new(&mut transport, 0, 3).unwrap_err(),
  347. Error::InvalidParam
  348. );
  349. }
  350. #[test]
  351. fn queue_too_big() {
  352. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  353. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  354. assert_eq!(
  355. VirtQueue::<FakeHal>::new(&mut transport, 0, 5).unwrap_err(),
  356. Error::InvalidParam
  357. );
  358. }
  359. #[test]
  360. fn queue_already_used() {
  361. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  362. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  363. VirtQueue::<FakeHal>::new(&mut transport, 0, 4).unwrap();
  364. assert_eq!(
  365. VirtQueue::<FakeHal>::new(&mut transport, 0, 4).unwrap_err(),
  366. Error::AlreadyUsed
  367. );
  368. }
  369. #[test]
  370. fn add_empty() {
  371. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  372. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  373. let mut queue = VirtQueue::<FakeHal>::new(&mut transport, 0, 4).unwrap();
  374. assert_eq!(
  375. unsafe { queue.add(&[], &[]) }.unwrap_err(),
  376. Error::InvalidParam
  377. );
  378. }
  379. #[test]
  380. fn add_too_big() {
  381. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  382. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  383. let mut queue = VirtQueue::<FakeHal>::new(&mut transport, 0, 4).unwrap();
  384. assert_eq!(queue.available_desc(), 4);
  385. assert_eq!(
  386. unsafe { queue.add(&[&[], &[], &[]], &[&mut [], &mut []]) }.unwrap_err(),
  387. Error::BufferTooSmall
  388. );
  389. }
  390. #[test]
  391. fn add_buffers() {
  392. let mut header = VirtIOHeader::make_fake_header(MODERN_VERSION, 1, 0, 0, 4);
  393. let mut transport = unsafe { MmioTransport::new(NonNull::from(&mut header)) }.unwrap();
  394. let mut queue = VirtQueue::<FakeHal>::new(&mut transport, 0, 4).unwrap();
  395. assert_eq!(queue.size(), 4);
  396. assert_eq!(queue.available_desc(), 4);
  397. // Add a buffer chain consisting of two device-readable parts followed by two
  398. // device-writable parts.
  399. let token = unsafe { queue.add(&[&[1, 2], &[3]], &[&mut [0, 0], &mut [0]]) }.unwrap();
  400. assert_eq!(queue.available_desc(), 0);
  401. assert!(!queue.can_pop());
  402. // Safe because the various parts of the queue are properly aligned, dereferenceable and
  403. // initialised, and nothing else is accessing them at the same time.
  404. unsafe {
  405. let first_descriptor_index = (*queue.avail.as_ptr()).ring[0];
  406. assert_eq!(first_descriptor_index, token);
  407. assert_eq!(
  408. (*queue.desc.as_ptr())[first_descriptor_index as usize].len,
  409. 2
  410. );
  411. assert_eq!(
  412. (*queue.desc.as_ptr())[first_descriptor_index as usize].flags,
  413. DescFlags::NEXT
  414. );
  415. let second_descriptor_index =
  416. (*queue.desc.as_ptr())[first_descriptor_index as usize].next;
  417. assert_eq!(
  418. (*queue.desc.as_ptr())[second_descriptor_index as usize].len,
  419. 1
  420. );
  421. assert_eq!(
  422. (*queue.desc.as_ptr())[second_descriptor_index as usize].flags,
  423. DescFlags::NEXT
  424. );
  425. let third_descriptor_index =
  426. (*queue.desc.as_ptr())[second_descriptor_index as usize].next;
  427. assert_eq!(
  428. (*queue.desc.as_ptr())[third_descriptor_index as usize].len,
  429. 2
  430. );
  431. assert_eq!(
  432. (*queue.desc.as_ptr())[third_descriptor_index as usize].flags,
  433. DescFlags::NEXT | DescFlags::WRITE
  434. );
  435. let fourth_descriptor_index =
  436. (*queue.desc.as_ptr())[third_descriptor_index as usize].next;
  437. assert_eq!(
  438. (*queue.desc.as_ptr())[fourth_descriptor_index as usize].len,
  439. 1
  440. );
  441. assert_eq!(
  442. (*queue.desc.as_ptr())[fourth_descriptor_index as usize].flags,
  443. DescFlags::WRITE
  444. );
  445. }
  446. }
  447. }