mod.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //! VirtIO transports.
  2. #[cfg(test)]
  3. pub mod fake;
  4. pub mod mmio;
  5. pub mod pci;
  6. use crate::{PhysAddr, Result, PAGE_SIZE};
  7. use bitflags::bitflags;
  8. use core::ptr::NonNull;
  9. /// A VirtIO transport layer.
  10. pub trait Transport {
  11. /// Gets the device type.
  12. fn device_type(&self) -> DeviceType;
  13. /// Reads device features.
  14. fn read_device_features(&mut self) -> u64;
  15. /// Writes device features.
  16. fn write_driver_features(&mut self, driver_features: u64);
  17. /// Gets the max size of queue.
  18. fn max_queue_size(&self) -> u32;
  19. /// Notifies the given queue on the device.
  20. fn notify(&mut self, queue: u16);
  21. /// Sets the device status.
  22. fn set_status(&mut self, status: DeviceStatus);
  23. /// Sets the guest page size.
  24. fn set_guest_page_size(&mut self, guest_page_size: u32);
  25. /// Returns whether the transport requires queues to use the legacy layout.
  26. ///
  27. /// Ref: 2.6.2 Legacy Interfaces: A Note on Virtqueue Layout
  28. fn requires_legacy_layout(&self) -> bool;
  29. /// Sets up the given queue.
  30. fn queue_set(
  31. &mut self,
  32. queue: u16,
  33. size: u32,
  34. descriptors: PhysAddr,
  35. driver_area: PhysAddr,
  36. device_area: PhysAddr,
  37. );
  38. /// Disables and resets the given queue.
  39. fn queue_unset(&mut self, queue: u16);
  40. /// Returns whether the queue is in use, i.e. has a nonzero PFN or is marked as ready.
  41. fn queue_used(&mut self, queue: u16) -> bool;
  42. /// Acknowledges an interrupt.
  43. ///
  44. /// Returns true on success.
  45. fn ack_interrupt(&mut self) -> bool;
  46. /// Begins initializing the device.
  47. ///
  48. /// Ref: virtio 3.1.1 Device Initialization
  49. fn begin_init(&mut self, negotiate_features: impl FnOnce(u64) -> u64) {
  50. self.set_status(DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER);
  51. let features = self.read_device_features();
  52. self.write_driver_features(negotiate_features(features));
  53. self.set_status(
  54. DeviceStatus::ACKNOWLEDGE | DeviceStatus::DRIVER | DeviceStatus::FEATURES_OK,
  55. );
  56. self.set_guest_page_size(PAGE_SIZE as u32);
  57. }
  58. /// Finishes initializing the device.
  59. fn finish_init(&mut self) {
  60. self.set_status(
  61. DeviceStatus::ACKNOWLEDGE
  62. | DeviceStatus::DRIVER
  63. | DeviceStatus::FEATURES_OK
  64. | DeviceStatus::DRIVER_OK,
  65. );
  66. }
  67. /// Gets the pointer to the config space.
  68. fn config_space<T: 'static>(&self) -> Result<NonNull<T>>;
  69. }
  70. bitflags! {
  71. /// The device status field.
  72. #[derive(Default)]
  73. pub struct DeviceStatus: u32 {
  74. /// Indicates that the guest OS has found the device and recognized it
  75. /// as a valid virtio device.
  76. const ACKNOWLEDGE = 1;
  77. /// Indicates that the guest OS knows how to drive the device.
  78. const DRIVER = 2;
  79. /// Indicates that something went wrong in the guest, and it has given
  80. /// up on the device. This could be an internal error, or the driver
  81. /// didn’t like the device for some reason, or even a fatal error
  82. /// during device operation.
  83. const FAILED = 128;
  84. /// Indicates that the driver has acknowledged all the features it
  85. /// understands, and feature negotiation is complete.
  86. const FEATURES_OK = 8;
  87. /// Indicates that the driver is set up and ready to drive the device.
  88. const DRIVER_OK = 4;
  89. /// Indicates that the device has experienced an error from which it
  90. /// can’t recover.
  91. const DEVICE_NEEDS_RESET = 64;
  92. }
  93. }
  94. /// Types of virtio devices.
  95. #[repr(u8)]
  96. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  97. #[allow(missing_docs)]
  98. pub enum DeviceType {
  99. Invalid = 0,
  100. Network = 1,
  101. Block = 2,
  102. Console = 3,
  103. EntropySource = 4,
  104. MemoryBallooning = 5,
  105. IoMemory = 6,
  106. Rpmsg = 7,
  107. ScsiHost = 8,
  108. _9P = 9,
  109. Mac80211 = 10,
  110. RprocSerial = 11,
  111. VirtioCAIF = 12,
  112. MemoryBalloon = 13,
  113. GPU = 16,
  114. Timer = 17,
  115. Input = 18,
  116. Socket = 19,
  117. Crypto = 20,
  118. SignalDistributionModule = 21,
  119. Pstore = 22,
  120. IOMMU = 23,
  121. Memory = 24,
  122. }
  123. impl From<u32> for DeviceType {
  124. fn from(virtio_device_id: u32) -> Self {
  125. match virtio_device_id {
  126. 1 => DeviceType::Network,
  127. 2 => DeviceType::Block,
  128. 3 => DeviceType::Console,
  129. 4 => DeviceType::EntropySource,
  130. 5 => DeviceType::MemoryBalloon,
  131. 6 => DeviceType::IoMemory,
  132. 7 => DeviceType::Rpmsg,
  133. 8 => DeviceType::ScsiHost,
  134. 9 => DeviceType::_9P,
  135. 10 => DeviceType::Mac80211,
  136. 11 => DeviceType::RprocSerial,
  137. 12 => DeviceType::VirtioCAIF,
  138. 13 => DeviceType::MemoryBalloon,
  139. 16 => DeviceType::GPU,
  140. 17 => DeviceType::Timer,
  141. 18 => DeviceType::Input,
  142. 19 => DeviceType::Socket,
  143. 20 => DeviceType::Crypto,
  144. 21 => DeviceType::SignalDistributionModule,
  145. 22 => DeviceType::Pstore,
  146. 23 => DeviceType::IOMMU,
  147. 24 => DeviceType::Memory,
  148. _ => DeviceType::Invalid,
  149. }
  150. }
  151. }
  152. impl From<u16> for DeviceType {
  153. fn from(virtio_device_id: u16) -> Self {
  154. u32::from(virtio_device_id).into()
  155. }
  156. }
  157. impl From<u8> for DeviceType {
  158. fn from(virtio_device_id: u8) -> Self {
  159. u32::from(virtio_device_id).into()
  160. }
  161. }