header.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. use crate::PAGE_SIZE;
  2. use bitflags::*;
  3. use volatile::{ReadOnly, Volatile, WriteOnly};
  4. const MAGIC_VALUE: u32 = 0x7472_6976;
  5. /// MMIO Device Legacy Register Interface.
  6. ///
  7. /// Ref: 4.2.4 Legacy interface
  8. #[repr(C)]
  9. pub struct VirtIOHeader {
  10. /// Magic value
  11. magic: ReadOnly<u32>,
  12. /// Device version number
  13. ///
  14. /// Legacy device returns value 0x1.
  15. version: ReadOnly<u32>,
  16. /// Virtio Subsystem Device ID
  17. device_id: ReadOnly<u32>,
  18. /// Virtio Subsystem Vendor ID
  19. vendor_id: ReadOnly<u32>,
  20. /// Flags representing features the device supports
  21. device_features: ReadOnly<u32>,
  22. /// Device (host) features word selection
  23. device_features_sel: WriteOnly<u32>,
  24. /// Reserved
  25. __r1: [ReadOnly<u32>; 2],
  26. /// Flags representing device features understood and activated by the driver
  27. driver_features: WriteOnly<u32>,
  28. /// Activated (guest) features word selection
  29. driver_features_sel: WriteOnly<u32>,
  30. /// Guest page size
  31. ///
  32. /// The driver writes the guest page size in bytes to the register during
  33. /// initialization, before any queues are used. This value should be a
  34. /// power of 2 and is used by the device to calculate the Guest address
  35. /// of the first queue page (see QueuePFN).
  36. guest_page_size: WriteOnly<u32>,
  37. /// Reserved
  38. __r2: ReadOnly<u32>,
  39. /// Virtual queue index
  40. ///
  41. /// Writing to this register selects the virtual queue that the following
  42. /// operations on the QueueNumMax, QueueNum, QueueAlign and QueuePFN
  43. /// registers apply to. The index number of the first queue is zero (0x0).
  44. queue_sel: WriteOnly<u32>,
  45. /// Maximum virtual queue size
  46. ///
  47. /// Reading from the register returns the maximum size of the queue the
  48. /// device is ready to process or zero (0x0) if the queue is not available.
  49. /// This applies to the queue selected by writing to QueueSel and is
  50. /// allowed only when QueuePFN is set to zero (0x0), so when the queue is
  51. /// not actively used.
  52. queue_num_max: ReadOnly<u32>,
  53. /// Virtual queue size
  54. ///
  55. /// Queue size is the number of elements in the queue. Writing to this
  56. /// register notifies the device what size of the queue the driver will use.
  57. /// This applies to the queue selected by writing to QueueSel.
  58. queue_num: WriteOnly<u32>,
  59. /// Used Ring alignment in the virtual queue
  60. ///
  61. /// Writing to this register notifies the device about alignment boundary
  62. /// of the Used Ring in bytes. This value should be a power of 2 and
  63. /// applies to the queue selected by writing to QueueSel.
  64. queue_align: WriteOnly<u32>,
  65. /// Guest physical page number of the virtual queue
  66. ///
  67. /// Writing to this register notifies the device about location of the
  68. /// virtual queue in the Guest’s physical address space. This value is
  69. /// the index number of a page starting with the queue Descriptor Table.
  70. /// Value zero (0x0) means physical address zero (0x00000000) and is illegal.
  71. /// When the driver stops using the queue it writes zero (0x0) to this
  72. /// register. Reading from this register returns the currently used page
  73. /// number of the queue, therefore a value other than zero (0x0) means that
  74. /// the queue is in use. Both read and write accesses apply to the queue
  75. /// selected by writing to QueueSel.
  76. queue_pfn: Volatile<u32>,
  77. /// new interface only
  78. queue_ready: Volatile<u32>,
  79. /// Reserved
  80. __r3: [ReadOnly<u32>; 2],
  81. /// Queue notifier
  82. queue_notify: WriteOnly<u32>,
  83. /// Reserved
  84. __r4: [ReadOnly<u32>; 3],
  85. /// Interrupt status
  86. interrupt_status: ReadOnly<u32>,
  87. /// Interrupt acknowledge
  88. interrupt_ack: WriteOnly<u32>,
  89. /// Reserved
  90. __r5: [ReadOnly<u32>; 2],
  91. /// Device status
  92. ///
  93. /// Reading from this register returns the current device status flags.
  94. /// Writing non-zero values to this register sets the status flags,
  95. /// indicating the OS/driver progress. Writing zero (0x0) to this register
  96. /// triggers a device reset. The device sets QueuePFN to zero (0x0) for
  97. /// all queues in the device. Also see 3.1 Device Initialization.
  98. status: Volatile<DeviceStatus>,
  99. /// Reserved
  100. __r6: [ReadOnly<u32>; 3],
  101. // new interface only since here
  102. queue_desc_low: WriteOnly<u32>,
  103. queue_desc_high: WriteOnly<u32>,
  104. /// Reserved
  105. __r7: [ReadOnly<u32>; 2],
  106. queue_avail_low: WriteOnly<u32>,
  107. queue_avail_high: WriteOnly<u32>,
  108. /// Reserved
  109. __r8: [ReadOnly<u32>; 2],
  110. queue_used_low: WriteOnly<u32>,
  111. queue_used_high: WriteOnly<u32>,
  112. /// Reserved
  113. __r9: [ReadOnly<u32>; 21],
  114. config_generation: ReadOnly<u32>,
  115. }
  116. impl VirtIOHeader {
  117. /// Verify a valid header.
  118. pub fn verify(&self) -> bool {
  119. self.magic.read() == MAGIC_VALUE && self.version.read() == 1 && self.device_id.read() != 0
  120. }
  121. /// Get the device type.
  122. pub fn device_type(&self) -> DeviceType {
  123. match self.device_id.read() {
  124. x @ 1..=13 | x @ 16..=24 => unsafe { core::mem::transmute(x as u8) },
  125. _ => DeviceType::Invalid,
  126. }
  127. }
  128. /// Get the vendor ID.
  129. pub fn vendor_id(&self) -> u32 {
  130. self.vendor_id.read()
  131. }
  132. /// Begin initializing the device.
  133. ///
  134. /// Ref: virtio 3.1.1 Device Initialization
  135. pub fn begin_init(&mut self, negotiate_features: impl FnOnce(u64) -> u64) {
  136. self.status.write(DeviceStatus::ACKNOWLEDGE);
  137. self.status.write(DeviceStatus::DRIVER);
  138. let features = self.read_device_features();
  139. self.write_driver_features(negotiate_features(features));
  140. self.status.write(DeviceStatus::FEATURES_OK);
  141. self.guest_page_size.write(PAGE_SIZE as u32);
  142. }
  143. /// Finish initializing the device.
  144. pub fn finish_init(&mut self) {
  145. self.status.write(DeviceStatus::DRIVER_OK);
  146. }
  147. /// Read device features.
  148. fn read_device_features(&mut self) -> u64 {
  149. self.device_features_sel.write(0); // device features [0, 32)
  150. let mut device_features_bits = self.device_features.read().into();
  151. self.device_features_sel.write(1); // device features [32, 64)
  152. device_features_bits += (self.device_features.read() as u64) << 32;
  153. device_features_bits
  154. }
  155. /// Write device features.
  156. fn write_driver_features(&mut self, driver_features: u64) {
  157. self.driver_features_sel.write(0); // driver features [0, 32)
  158. self.driver_features.write(driver_features as u32);
  159. self.driver_features_sel.write(1); // driver features [32, 64)
  160. self.driver_features.write((driver_features >> 32) as u32);
  161. }
  162. /// Set queue.
  163. pub fn queue_set(&mut self, queue: u32, size: u32, align: u32, pfn: u32) {
  164. self.queue_sel.write(queue);
  165. self.queue_num.write(size);
  166. self.queue_align.write(align);
  167. self.queue_pfn.write(pfn);
  168. }
  169. /// Get guest physical page number of the virtual queue.
  170. pub fn queue_physical_page_number(&mut self, queue: u32) -> u32 {
  171. self.queue_sel.write(queue);
  172. self.queue_pfn.read()
  173. }
  174. /// Whether the queue is in used.
  175. pub fn queue_used(&mut self, queue: u32) -> bool {
  176. self.queue_physical_page_number(queue) != 0
  177. }
  178. /// Get the max size of queue.
  179. pub fn max_queue_size(&self) -> u32 {
  180. self.queue_num_max.read()
  181. }
  182. /// Notify device.
  183. pub fn notify(&mut self, queue: u32) {
  184. self.queue_notify.write(queue);
  185. }
  186. /// Acknowledge interrupt and return true if success.
  187. pub fn ack_interrupt(&mut self) -> bool {
  188. let interrupt = self.interrupt_status.read();
  189. if interrupt != 0 {
  190. self.interrupt_ack.write(interrupt);
  191. true
  192. } else {
  193. false
  194. }
  195. }
  196. /// Get the pointer to config space (at offset 0x100)
  197. pub fn config_space(&self) -> *mut u64 {
  198. (self as *const _ as usize + CONFIG_SPACE_OFFSET) as _
  199. }
  200. /// Constructs a fake virtio header for use in unit tests.
  201. #[cfg(test)]
  202. pub fn make_fake_header(
  203. device_id: u32,
  204. vendor_id: u32,
  205. device_features: u32,
  206. queue_num_max: u32,
  207. ) -> Self {
  208. Self {
  209. magic: ReadOnly::new(MAGIC_VALUE),
  210. version: ReadOnly::new(1),
  211. device_id: ReadOnly::new(device_id),
  212. vendor_id: ReadOnly::new(vendor_id),
  213. device_features: ReadOnly::new(device_features),
  214. device_features_sel: WriteOnly::default(),
  215. __r1: Default::default(),
  216. driver_features: Default::default(),
  217. driver_features_sel: Default::default(),
  218. guest_page_size: Default::default(),
  219. __r2: Default::default(),
  220. queue_sel: Default::default(),
  221. queue_num_max: ReadOnly::new(queue_num_max),
  222. queue_num: Default::default(),
  223. queue_align: Default::default(),
  224. queue_pfn: Default::default(),
  225. queue_ready: Default::default(),
  226. __r3: Default::default(),
  227. queue_notify: Default::default(),
  228. __r4: Default::default(),
  229. interrupt_status: Default::default(),
  230. interrupt_ack: Default::default(),
  231. __r5: Default::default(),
  232. status: Volatile::new(DeviceStatus::empty()),
  233. __r6: Default::default(),
  234. queue_desc_low: Default::default(),
  235. queue_desc_high: Default::default(),
  236. __r7: Default::default(),
  237. queue_avail_low: Default::default(),
  238. queue_avail_high: Default::default(),
  239. __r8: Default::default(),
  240. queue_used_low: Default::default(),
  241. queue_used_high: Default::default(),
  242. __r9: Default::default(),
  243. config_generation: Default::default(),
  244. }
  245. }
  246. }
  247. bitflags! {
  248. /// The device status field.
  249. struct DeviceStatus: u32 {
  250. /// Indicates that the guest OS has found the device and recognized it
  251. /// as a valid virtio device.
  252. const ACKNOWLEDGE = 1;
  253. /// Indicates that the guest OS knows how to drive the device.
  254. const DRIVER = 2;
  255. /// Indicates that something went wrong in the guest, and it has given
  256. /// up on the device. This could be an internal error, or the driver
  257. /// didn’t like the device for some reason, or even a fatal error
  258. /// during device operation.
  259. const FAILED = 128;
  260. /// Indicates that the driver has acknowledged all the features it
  261. /// understands, and feature negotiation is complete.
  262. const FEATURES_OK = 8;
  263. /// Indicates that the driver is set up and ready to drive the device.
  264. const DRIVER_OK = 4;
  265. /// Indicates that the device has experienced an error from which it
  266. /// can’t recover.
  267. const DEVICE_NEEDS_RESET = 64;
  268. }
  269. }
  270. const CONFIG_SPACE_OFFSET: usize = 0x100;
  271. /// Types of virtio devices.
  272. #[repr(u8)]
  273. #[derive(Debug, Eq, PartialEq)]
  274. #[allow(missing_docs)]
  275. pub enum DeviceType {
  276. Invalid = 0,
  277. Network = 1,
  278. Block = 2,
  279. Console = 3,
  280. EntropySource = 4,
  281. MemoryBallooning = 5,
  282. IoMemory = 6,
  283. Rpmsg = 7,
  284. ScsiHost = 8,
  285. _9P = 9,
  286. Mac80211 = 10,
  287. RprocSerial = 11,
  288. VirtioCAIF = 12,
  289. MemoryBalloon = 13,
  290. GPU = 16,
  291. Timer = 17,
  292. Input = 18,
  293. Socket = 19,
  294. Crypto = 20,
  295. SignalDistributionModule = 21,
  296. Pstore = 22,
  297. IOMMU = 23,
  298. Memory = 24,
  299. }