mod.rs 5.0 KB

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