blk.rs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. //! Driver for VirtIO block devices.
  2. use crate::hal::Hal;
  3. use crate::queue::VirtQueue;
  4. use crate::transport::Transport;
  5. use crate::volatile::{volread, Volatile};
  6. use crate::{Error, Result};
  7. use bitflags::bitflags;
  8. use log::info;
  9. use zerocopy::{AsBytes, FromBytes, FromZeroes};
  10. const QUEUE: u16 = 0;
  11. const QUEUE_SIZE: u16 = 16;
  12. const SUPPORTED_FEATURES: BlkFeature = BlkFeature::RO
  13. .union(BlkFeature::FLUSH)
  14. .union(BlkFeature::RING_INDIRECT_DESC)
  15. .union(BlkFeature::RING_EVENT_IDX);
  16. /// Driver for a VirtIO block device.
  17. ///
  18. /// This is a simple virtual block device, e.g. disk.
  19. ///
  20. /// Read and write requests (and other exotic requests) are placed in the queue and serviced
  21. /// (probably out of order) by the device except where noted.
  22. ///
  23. /// # Example
  24. ///
  25. /// ```
  26. /// # use virtio_drivers::{Error, Hal};
  27. /// # use virtio_drivers::transport::Transport;
  28. /// use virtio_drivers::device::blk::{VirtIOBlk, SECTOR_SIZE};
  29. ///
  30. /// # fn example<HalImpl: Hal, T: Transport>(transport: T) -> Result<(), Error> {
  31. /// let mut disk = VirtIOBlk::<HalImpl, _>::new(transport)?;
  32. ///
  33. /// println!("VirtIO block device: {} kB", disk.capacity() * SECTOR_SIZE as u64 / 2);
  34. ///
  35. /// // Read sector 0 and then copy it to sector 1.
  36. /// let mut buf = [0; SECTOR_SIZE];
  37. /// disk.read_blocks(0, &mut buf)?;
  38. /// disk.write_blocks(1, &buf)?;
  39. /// # Ok(())
  40. /// # }
  41. /// ```
  42. pub struct VirtIOBlk<H: Hal, T: Transport> {
  43. transport: T,
  44. queue: VirtQueue<H, { QUEUE_SIZE as usize }>,
  45. capacity: u64,
  46. negotiated_features: BlkFeature,
  47. }
  48. impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
  49. /// Create a new VirtIO-Blk driver.
  50. pub fn new(mut transport: T) -> Result<Self> {
  51. let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
  52. // Read configuration space.
  53. let config = transport.config_space::<BlkConfig>()?;
  54. info!("config: {:?}", config);
  55. // Safe because config is a valid pointer to the device configuration space.
  56. let capacity = unsafe {
  57. volread!(config, capacity_low) as u64 | (volread!(config, capacity_high) as u64) << 32
  58. };
  59. info!("found a block device of size {}KB", capacity / 2);
  60. let queue = VirtQueue::new(
  61. &mut transport,
  62. QUEUE,
  63. negotiated_features.contains(BlkFeature::RING_INDIRECT_DESC),
  64. negotiated_features.contains(BlkFeature::RING_EVENT_IDX),
  65. )?;
  66. transport.finish_init();
  67. Ok(VirtIOBlk {
  68. transport,
  69. queue,
  70. capacity,
  71. negotiated_features,
  72. })
  73. }
  74. /// Gets the capacity of the block device, in 512 byte ([`SECTOR_SIZE`]) sectors.
  75. pub fn capacity(&self) -> u64 {
  76. self.capacity
  77. }
  78. /// Returns true if the block device is read-only, or false if it allows writes.
  79. pub fn readonly(&self) -> bool {
  80. self.negotiated_features.contains(BlkFeature::RO)
  81. }
  82. /// Acknowledges a pending interrupt, if any.
  83. ///
  84. /// Returns true if there was an interrupt to acknowledge.
  85. pub fn ack_interrupt(&mut self) -> bool {
  86. self.transport.ack_interrupt()
  87. }
  88. /// Enables interrupts from the device.
  89. pub fn enable_interrupts(&mut self) {
  90. self.queue.set_dev_notify(true);
  91. }
  92. /// Disables interrupts from the device.
  93. pub fn disable_interrupts(&mut self) {
  94. self.queue.set_dev_notify(false);
  95. }
  96. /// Sends the given request to the device and waits for a response, with no extra data.
  97. fn request(&mut self, request: BlkReq) -> Result {
  98. let mut resp = BlkResp::default();
  99. self.queue.add_notify_wait_pop(
  100. &[request.as_bytes()],
  101. &mut [resp.as_bytes_mut()],
  102. &mut self.transport,
  103. )?;
  104. resp.status.into()
  105. }
  106. /// Sends the given request to the device and waits for a response, including the given data.
  107. fn request_read(&mut self, request: BlkReq, data: &mut [u8]) -> Result {
  108. let mut resp = BlkResp::default();
  109. self.queue.add_notify_wait_pop(
  110. &[request.as_bytes()],
  111. &mut [data, resp.as_bytes_mut()],
  112. &mut self.transport,
  113. )?;
  114. resp.status.into()
  115. }
  116. /// Sends the given request and data to the device and waits for a response.
  117. fn request_write(&mut self, request: BlkReq, data: &[u8]) -> Result {
  118. let mut resp = BlkResp::default();
  119. self.queue.add_notify_wait_pop(
  120. &[request.as_bytes(), data],
  121. &mut [resp.as_bytes_mut()],
  122. &mut self.transport,
  123. )?;
  124. resp.status.into()
  125. }
  126. /// Requests the device to flush any pending writes to storage.
  127. ///
  128. /// This will be ignored if the device doesn't support the `VIRTIO_BLK_F_FLUSH` feature.
  129. pub fn flush(&mut self) -> Result {
  130. if self.negotiated_features.contains(BlkFeature::FLUSH) {
  131. self.request(BlkReq {
  132. type_: ReqType::Flush,
  133. ..Default::default()
  134. })
  135. } else {
  136. Ok(())
  137. }
  138. }
  139. /// Gets the device ID.
  140. ///
  141. /// The ID is written as ASCII into the given buffer, which must be 20 bytes long, and the used
  142. /// length returned.
  143. pub fn device_id(&mut self, id: &mut [u8; 20]) -> Result<usize> {
  144. self.request_read(
  145. BlkReq {
  146. type_: ReqType::GetId,
  147. ..Default::default()
  148. },
  149. id,
  150. )?;
  151. let length = id.iter().position(|&x| x == 0).unwrap_or(20);
  152. Ok(length)
  153. }
  154. /// Reads one or more blocks into the given buffer.
  155. ///
  156. /// The buffer length must be a non-zero multiple of [`SECTOR_SIZE`].
  157. ///
  158. /// Blocks until the read completes or there is an error.
  159. pub fn read_blocks(&mut self, block_id: usize, buf: &mut [u8]) -> Result {
  160. assert_ne!(buf.len(), 0);
  161. assert_eq!(buf.len() % SECTOR_SIZE, 0);
  162. self.request_read(
  163. BlkReq {
  164. type_: ReqType::In,
  165. reserved: 0,
  166. sector: block_id as u64,
  167. },
  168. buf,
  169. )
  170. }
  171. /// Submits a request to read one or more blocks, but returns immediately without waiting for
  172. /// the read to complete.
  173. ///
  174. /// # Arguments
  175. ///
  176. /// * `block_id` - The identifier of the first block to read.
  177. /// * `req` - A buffer which the driver can use for the request to send to the device. The
  178. /// contents don't matter as `read_blocks_nb` will initialise it, but like the other buffers
  179. /// it needs to be valid (and not otherwise used) until the corresponding
  180. /// `complete_read_blocks` call. Its length must be a non-zero multiple of [`SECTOR_SIZE`].
  181. /// * `buf` - The buffer in memory into which the block should be read.
  182. /// * `resp` - A mutable reference to a variable provided by the caller
  183. /// to contain the status of the request. The caller can safely
  184. /// read the variable only after the request is complete.
  185. ///
  186. /// # Usage
  187. ///
  188. /// It will submit request to the VirtIO block device and return a token identifying
  189. /// the position of the first Descriptor in the chain. If there are not enough
  190. /// Descriptors to allocate, then it returns [`Error::QueueFull`].
  191. ///
  192. /// The caller can then call `peek_used` with the returned token to check whether the device has
  193. /// finished handling the request. Once it has, the caller must call `complete_read_blocks` with
  194. /// the same buffers before reading the response.
  195. ///
  196. /// ```
  197. /// # use virtio_drivers::{Error, Hal};
  198. /// # use virtio_drivers::device::blk::VirtIOBlk;
  199. /// # use virtio_drivers::transport::Transport;
  200. /// use virtio_drivers::device::blk::{BlkReq, BlkResp, RespStatus};
  201. ///
  202. /// # fn example<H: Hal, T: Transport>(blk: &mut VirtIOBlk<H, T>) -> Result<(), Error> {
  203. /// let mut request = BlkReq::default();
  204. /// let mut buffer = [0; 512];
  205. /// let mut response = BlkResp::default();
  206. /// let token = unsafe { blk.read_blocks_nb(42, &mut request, &mut buffer, &mut response) }?;
  207. ///
  208. /// // Wait for an interrupt to tell us that the request completed...
  209. /// assert_eq!(blk.peek_used(), Some(token));
  210. ///
  211. /// unsafe {
  212. /// blk.complete_read_blocks(token, &request, &mut buffer, &mut response)?;
  213. /// }
  214. /// if response.status() == RespStatus::OK {
  215. /// println!("Successfully read block.");
  216. /// } else {
  217. /// println!("Error {:?} reading block.", response.status());
  218. /// }
  219. /// # Ok(())
  220. /// # }
  221. /// ```
  222. ///
  223. /// # Safety
  224. ///
  225. /// `req`, `buf` and `resp` are still borrowed by the underlying VirtIO block device even after
  226. /// this method returns. Thus, it is the caller's responsibility to guarantee that they are not
  227. /// accessed before the request is completed in order to avoid data races.
  228. pub unsafe fn read_blocks_nb(
  229. &mut self,
  230. block_id: usize,
  231. req: &mut BlkReq,
  232. buf: &mut [u8],
  233. resp: &mut BlkResp,
  234. ) -> Result<u16> {
  235. assert_ne!(buf.len(), 0);
  236. assert_eq!(buf.len() % SECTOR_SIZE, 0);
  237. *req = BlkReq {
  238. type_: ReqType::In,
  239. reserved: 0,
  240. sector: block_id as u64,
  241. };
  242. let token = self
  243. .queue
  244. .add(&[req.as_bytes()], &mut [buf, resp.as_bytes_mut()])?;
  245. if self.queue.should_notify() {
  246. self.transport.notify(QUEUE);
  247. }
  248. Ok(token)
  249. }
  250. /// Completes a read operation which was started by `read_blocks_nb`.
  251. ///
  252. /// # Safety
  253. ///
  254. /// The same buffers must be passed in again as were passed to `read_blocks_nb` when it returned
  255. /// the token.
  256. pub unsafe fn complete_read_blocks(
  257. &mut self,
  258. token: u16,
  259. req: &BlkReq,
  260. buf: &mut [u8],
  261. resp: &mut BlkResp,
  262. ) -> Result<()> {
  263. self.queue
  264. .pop_used(token, &[req.as_bytes()], &mut [buf, resp.as_bytes_mut()])?;
  265. resp.status.into()
  266. }
  267. /// Writes the contents of the given buffer to a block or blocks.
  268. ///
  269. /// The buffer length must be a non-zero multiple of [`SECTOR_SIZE`].
  270. ///
  271. /// Blocks until the write is complete or there is an error.
  272. pub fn write_blocks(&mut self, block_id: usize, buf: &[u8]) -> Result {
  273. assert_ne!(buf.len(), 0);
  274. assert_eq!(buf.len() % SECTOR_SIZE, 0);
  275. self.request_write(
  276. BlkReq {
  277. type_: ReqType::Out,
  278. sector: block_id as u64,
  279. ..Default::default()
  280. },
  281. buf,
  282. )
  283. }
  284. /// Submits a request to write one or more blocks, but returns immediately without waiting for
  285. /// the write to complete.
  286. ///
  287. /// # Arguments
  288. ///
  289. /// * `block_id` - The identifier of the first block to write.
  290. /// * `req` - A buffer which the driver can use for the request to send to the device. The
  291. /// contents don't matter as `read_blocks_nb` will initialise it, but like the other buffers
  292. /// it needs to be valid (and not otherwise used) until the corresponding
  293. /// `complete_write_blocks` call.
  294. /// * `buf` - The buffer in memory containing the data to write to the blocks. Its length must
  295. /// be a non-zero multiple of [`SECTOR_SIZE`].
  296. /// * `resp` - A mutable reference to a variable provided by the caller
  297. /// to contain the status of the request. The caller can safely
  298. /// read the variable only after the request is complete.
  299. ///
  300. /// # Usage
  301. ///
  302. /// See [VirtIOBlk::read_blocks_nb].
  303. ///
  304. /// # Safety
  305. ///
  306. /// See [VirtIOBlk::read_blocks_nb].
  307. pub unsafe fn write_blocks_nb(
  308. &mut self,
  309. block_id: usize,
  310. req: &mut BlkReq,
  311. buf: &[u8],
  312. resp: &mut BlkResp,
  313. ) -> Result<u16> {
  314. assert_ne!(buf.len(), 0);
  315. assert_eq!(buf.len() % SECTOR_SIZE, 0);
  316. *req = BlkReq {
  317. type_: ReqType::Out,
  318. reserved: 0,
  319. sector: block_id as u64,
  320. };
  321. let token = self
  322. .queue
  323. .add(&[req.as_bytes(), buf], &mut [resp.as_bytes_mut()])?;
  324. if self.queue.should_notify() {
  325. self.transport.notify(QUEUE);
  326. }
  327. Ok(token)
  328. }
  329. /// Completes a write operation which was started by `write_blocks_nb`.
  330. ///
  331. /// # Safety
  332. ///
  333. /// The same buffers must be passed in again as were passed to `write_blocks_nb` when it
  334. /// returned the token.
  335. pub unsafe fn complete_write_blocks(
  336. &mut self,
  337. token: u16,
  338. req: &BlkReq,
  339. buf: &[u8],
  340. resp: &mut BlkResp,
  341. ) -> Result<()> {
  342. self.queue
  343. .pop_used(token, &[req.as_bytes(), buf], &mut [resp.as_bytes_mut()])?;
  344. resp.status.into()
  345. }
  346. /// Fetches the token of the next completed request from the used ring and returns it, without
  347. /// removing it from the used ring. If there are no pending completed requests returns `None`.
  348. pub fn peek_used(&mut self) -> Option<u16> {
  349. self.queue.peek_used()
  350. }
  351. /// Returns the size of the device's VirtQueue.
  352. ///
  353. /// This can be used to tell the caller how many channels to monitor on.
  354. pub fn virt_queue_size(&self) -> u16 {
  355. QUEUE_SIZE
  356. }
  357. }
  358. impl<H: Hal, T: Transport> Drop for VirtIOBlk<H, T> {
  359. fn drop(&mut self) {
  360. // Clear any pointers pointing to DMA regions, so the device doesn't try to access them
  361. // after they have been freed.
  362. self.transport.queue_unset(QUEUE);
  363. }
  364. }
  365. #[repr(C)]
  366. struct BlkConfig {
  367. /// Number of 512 Bytes sectors
  368. capacity_low: Volatile<u32>,
  369. capacity_high: Volatile<u32>,
  370. size_max: Volatile<u32>,
  371. seg_max: Volatile<u32>,
  372. cylinders: Volatile<u16>,
  373. heads: Volatile<u8>,
  374. sectors: Volatile<u8>,
  375. blk_size: Volatile<u32>,
  376. physical_block_exp: Volatile<u8>,
  377. alignment_offset: Volatile<u8>,
  378. min_io_size: Volatile<u16>,
  379. opt_io_size: Volatile<u32>,
  380. // ... ignored
  381. }
  382. /// A VirtIO block device request.
  383. #[repr(C)]
  384. #[derive(AsBytes, Debug)]
  385. pub struct BlkReq {
  386. type_: ReqType,
  387. reserved: u32,
  388. sector: u64,
  389. }
  390. impl Default for BlkReq {
  391. fn default() -> Self {
  392. Self {
  393. type_: ReqType::In,
  394. reserved: 0,
  395. sector: 0,
  396. }
  397. }
  398. }
  399. /// Response of a VirtIOBlk request.
  400. #[repr(C)]
  401. #[derive(AsBytes, Debug, FromBytes, FromZeroes)]
  402. pub struct BlkResp {
  403. status: RespStatus,
  404. }
  405. impl BlkResp {
  406. /// Return the status of a VirtIOBlk request.
  407. pub fn status(&self) -> RespStatus {
  408. self.status
  409. }
  410. }
  411. #[repr(u32)]
  412. #[derive(AsBytes, Debug)]
  413. enum ReqType {
  414. In = 0,
  415. Out = 1,
  416. Flush = 4,
  417. GetId = 8,
  418. GetLifetime = 10,
  419. Discard = 11,
  420. WriteZeroes = 13,
  421. SecureErase = 14,
  422. }
  423. /// Status of a VirtIOBlk request.
  424. #[repr(transparent)]
  425. #[derive(AsBytes, Copy, Clone, Debug, Eq, FromBytes, FromZeroes, PartialEq)]
  426. pub struct RespStatus(u8);
  427. impl RespStatus {
  428. /// Ok.
  429. pub const OK: RespStatus = RespStatus(0);
  430. /// IoErr.
  431. pub const IO_ERR: RespStatus = RespStatus(1);
  432. /// Unsupported yet.
  433. pub const UNSUPPORTED: RespStatus = RespStatus(2);
  434. /// Not ready.
  435. pub const NOT_READY: RespStatus = RespStatus(3);
  436. }
  437. impl From<RespStatus> for Result {
  438. fn from(status: RespStatus) -> Self {
  439. match status {
  440. RespStatus::OK => Ok(()),
  441. RespStatus::IO_ERR => Err(Error::IoError),
  442. RespStatus::UNSUPPORTED => Err(Error::Unsupported),
  443. RespStatus::NOT_READY => Err(Error::NotReady),
  444. _ => Err(Error::IoError),
  445. }
  446. }
  447. }
  448. impl Default for BlkResp {
  449. fn default() -> Self {
  450. BlkResp {
  451. status: RespStatus::NOT_READY,
  452. }
  453. }
  454. }
  455. /// The standard sector size of a VirtIO block device. Data is read and written in multiples of this
  456. /// size.
  457. pub const SECTOR_SIZE: usize = 512;
  458. bitflags! {
  459. #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
  460. struct BlkFeature: u64 {
  461. /// Device supports request barriers. (legacy)
  462. const BARRIER = 1 << 0;
  463. /// Maximum size of any single segment is in `size_max`.
  464. const SIZE_MAX = 1 << 1;
  465. /// Maximum number of segments in a request is in `seg_max`.
  466. const SEG_MAX = 1 << 2;
  467. /// Disk-style geometry specified in geometry.
  468. const GEOMETRY = 1 << 4;
  469. /// Device is read-only.
  470. const RO = 1 << 5;
  471. /// Block size of disk is in `blk_size`.
  472. const BLK_SIZE = 1 << 6;
  473. /// Device supports scsi packet commands. (legacy)
  474. const SCSI = 1 << 7;
  475. /// Cache flush command support.
  476. const FLUSH = 1 << 9;
  477. /// Device exports information on optimal I/O alignment.
  478. const TOPOLOGY = 1 << 10;
  479. /// Device can toggle its cache between writeback and writethrough modes.
  480. const CONFIG_WCE = 1 << 11;
  481. /// Device supports multiqueue.
  482. const MQ = 1 << 12;
  483. /// Device can support discard command, maximum discard sectors size in
  484. /// `max_discard_sectors` and maximum discard segment number in
  485. /// `max_discard_seg`.
  486. const DISCARD = 1 << 13;
  487. /// Device can support write zeroes command, maximum write zeroes sectors
  488. /// size in `max_write_zeroes_sectors` and maximum write zeroes segment
  489. /// number in `max_write_zeroes_seg`.
  490. const WRITE_ZEROES = 1 << 14;
  491. /// Device supports providing storage lifetime information.
  492. const LIFETIME = 1 << 15;
  493. /// Device can support the secure erase command.
  494. const SECURE_ERASE = 1 << 16;
  495. // device independent
  496. const NOTIFY_ON_EMPTY = 1 << 24; // legacy
  497. const ANY_LAYOUT = 1 << 27; // legacy
  498. const RING_INDIRECT_DESC = 1 << 28;
  499. const RING_EVENT_IDX = 1 << 29;
  500. const UNUSED = 1 << 30; // legacy
  501. const VERSION_1 = 1 << 32; // detect legacy
  502. // the following since virtio v1.1
  503. const ACCESS_PLATFORM = 1 << 33;
  504. const RING_PACKED = 1 << 34;
  505. const IN_ORDER = 1 << 35;
  506. const ORDER_PLATFORM = 1 << 36;
  507. const SR_IOV = 1 << 37;
  508. const NOTIFICATION_DATA = 1 << 38;
  509. }
  510. }
  511. #[cfg(test)]
  512. mod tests {
  513. use super::*;
  514. use crate::{
  515. hal::fake::FakeHal,
  516. transport::{
  517. fake::{FakeTransport, QueueStatus, State},
  518. DeviceType,
  519. },
  520. };
  521. use alloc::{sync::Arc, vec};
  522. use core::{mem::size_of, ptr::NonNull};
  523. use std::{sync::Mutex, thread};
  524. #[test]
  525. fn config() {
  526. let mut config_space = BlkConfig {
  527. capacity_low: Volatile::new(0x42),
  528. capacity_high: Volatile::new(0x02),
  529. size_max: Volatile::new(0),
  530. seg_max: Volatile::new(0),
  531. cylinders: Volatile::new(0),
  532. heads: Volatile::new(0),
  533. sectors: Volatile::new(0),
  534. blk_size: Volatile::new(0),
  535. physical_block_exp: Volatile::new(0),
  536. alignment_offset: Volatile::new(0),
  537. min_io_size: Volatile::new(0),
  538. opt_io_size: Volatile::new(0),
  539. };
  540. let state = Arc::new(Mutex::new(State {
  541. queues: vec![QueueStatus::default()],
  542. ..Default::default()
  543. }));
  544. let transport = FakeTransport {
  545. device_type: DeviceType::Block,
  546. max_queue_size: QUEUE_SIZE.into(),
  547. device_features: BlkFeature::RO.bits(),
  548. config_space: NonNull::from(&mut config_space),
  549. state: state.clone(),
  550. };
  551. let blk = VirtIOBlk::<FakeHal, FakeTransport<BlkConfig>>::new(transport).unwrap();
  552. assert_eq!(blk.capacity(), 0x02_0000_0042);
  553. assert_eq!(blk.readonly(), true);
  554. }
  555. #[test]
  556. fn read() {
  557. let mut config_space = BlkConfig {
  558. capacity_low: Volatile::new(66),
  559. capacity_high: Volatile::new(0),
  560. size_max: Volatile::new(0),
  561. seg_max: Volatile::new(0),
  562. cylinders: Volatile::new(0),
  563. heads: Volatile::new(0),
  564. sectors: Volatile::new(0),
  565. blk_size: Volatile::new(0),
  566. physical_block_exp: Volatile::new(0),
  567. alignment_offset: Volatile::new(0),
  568. min_io_size: Volatile::new(0),
  569. opt_io_size: Volatile::new(0),
  570. };
  571. let state = Arc::new(Mutex::new(State {
  572. queues: vec![QueueStatus::default()],
  573. ..Default::default()
  574. }));
  575. let transport = FakeTransport {
  576. device_type: DeviceType::Block,
  577. max_queue_size: QUEUE_SIZE.into(),
  578. device_features: BlkFeature::RING_INDIRECT_DESC.bits(),
  579. config_space: NonNull::from(&mut config_space),
  580. state: state.clone(),
  581. };
  582. let mut blk = VirtIOBlk::<FakeHal, FakeTransport<BlkConfig>>::new(transport).unwrap();
  583. // Start a thread to simulate the device waiting for a read request.
  584. let handle = thread::spawn(move || {
  585. println!("Device waiting for a request.");
  586. State::wait_until_queue_notified(&state, QUEUE);
  587. println!("Transmit queue was notified.");
  588. state
  589. .lock()
  590. .unwrap()
  591. .read_write_queue::<{ QUEUE_SIZE as usize }>(QUEUE, |request| {
  592. assert_eq!(
  593. request,
  594. BlkReq {
  595. type_: ReqType::In,
  596. reserved: 0,
  597. sector: 42
  598. }
  599. .as_bytes()
  600. );
  601. let mut response = vec![0; SECTOR_SIZE];
  602. response[0..9].copy_from_slice(b"Test data");
  603. response.extend_from_slice(
  604. BlkResp {
  605. status: RespStatus::OK,
  606. }
  607. .as_bytes(),
  608. );
  609. response
  610. });
  611. });
  612. // Read a block from the device.
  613. let mut buffer = [0; 512];
  614. blk.read_blocks(42, &mut buffer).unwrap();
  615. assert_eq!(&buffer[0..9], b"Test data");
  616. handle.join().unwrap();
  617. }
  618. #[test]
  619. fn write() {
  620. let mut config_space = BlkConfig {
  621. capacity_low: Volatile::new(66),
  622. capacity_high: Volatile::new(0),
  623. size_max: Volatile::new(0),
  624. seg_max: Volatile::new(0),
  625. cylinders: Volatile::new(0),
  626. heads: Volatile::new(0),
  627. sectors: Volatile::new(0),
  628. blk_size: Volatile::new(0),
  629. physical_block_exp: Volatile::new(0),
  630. alignment_offset: Volatile::new(0),
  631. min_io_size: Volatile::new(0),
  632. opt_io_size: Volatile::new(0),
  633. };
  634. let state = Arc::new(Mutex::new(State {
  635. queues: vec![QueueStatus::default()],
  636. ..Default::default()
  637. }));
  638. let transport = FakeTransport {
  639. device_type: DeviceType::Block,
  640. max_queue_size: QUEUE_SIZE.into(),
  641. device_features: BlkFeature::RING_INDIRECT_DESC.bits(),
  642. config_space: NonNull::from(&mut config_space),
  643. state: state.clone(),
  644. };
  645. let mut blk = VirtIOBlk::<FakeHal, FakeTransport<BlkConfig>>::new(transport).unwrap();
  646. // Start a thread to simulate the device waiting for a write request.
  647. let handle = thread::spawn(move || {
  648. println!("Device waiting for a request.");
  649. State::wait_until_queue_notified(&state, QUEUE);
  650. println!("Transmit queue was notified.");
  651. state
  652. .lock()
  653. .unwrap()
  654. .read_write_queue::<{ QUEUE_SIZE as usize }>(QUEUE, |request| {
  655. assert_eq!(
  656. &request[0..size_of::<BlkReq>()],
  657. BlkReq {
  658. type_: ReqType::Out,
  659. reserved: 0,
  660. sector: 42
  661. }
  662. .as_bytes()
  663. );
  664. let data = &request[size_of::<BlkReq>()..];
  665. assert_eq!(data.len(), SECTOR_SIZE);
  666. assert_eq!(&data[0..9], b"Test data");
  667. let mut response = Vec::new();
  668. response.extend_from_slice(
  669. BlkResp {
  670. status: RespStatus::OK,
  671. }
  672. .as_bytes(),
  673. );
  674. response
  675. });
  676. });
  677. // Write a block to the device.
  678. let mut buffer = [0; 512];
  679. buffer[0..9].copy_from_slice(b"Test data");
  680. blk.write_blocks(42, &mut buffer).unwrap();
  681. // Request to flush should be ignored as the device doesn't support it.
  682. blk.flush().unwrap();
  683. handle.join().unwrap();
  684. }
  685. #[test]
  686. fn flush() {
  687. let mut config_space = BlkConfig {
  688. capacity_low: Volatile::new(66),
  689. capacity_high: Volatile::new(0),
  690. size_max: Volatile::new(0),
  691. seg_max: Volatile::new(0),
  692. cylinders: Volatile::new(0),
  693. heads: Volatile::new(0),
  694. sectors: Volatile::new(0),
  695. blk_size: Volatile::new(0),
  696. physical_block_exp: Volatile::new(0),
  697. alignment_offset: Volatile::new(0),
  698. min_io_size: Volatile::new(0),
  699. opt_io_size: Volatile::new(0),
  700. };
  701. let state = Arc::new(Mutex::new(State {
  702. queues: vec![QueueStatus::default()],
  703. ..Default::default()
  704. }));
  705. let transport = FakeTransport {
  706. device_type: DeviceType::Block,
  707. max_queue_size: QUEUE_SIZE.into(),
  708. device_features: (BlkFeature::RING_INDIRECT_DESC | BlkFeature::FLUSH).bits(),
  709. config_space: NonNull::from(&mut config_space),
  710. state: state.clone(),
  711. };
  712. let mut blk = VirtIOBlk::<FakeHal, FakeTransport<BlkConfig>>::new(transport).unwrap();
  713. // Start a thread to simulate the device waiting for a flush request.
  714. let handle = thread::spawn(move || {
  715. println!("Device waiting for a request.");
  716. State::wait_until_queue_notified(&state, QUEUE);
  717. println!("Transmit queue was notified.");
  718. state
  719. .lock()
  720. .unwrap()
  721. .read_write_queue::<{ QUEUE_SIZE as usize }>(QUEUE, |request| {
  722. assert_eq!(
  723. request,
  724. BlkReq {
  725. type_: ReqType::Flush,
  726. reserved: 0,
  727. sector: 0,
  728. }
  729. .as_bytes()
  730. );
  731. let mut response = Vec::new();
  732. response.extend_from_slice(
  733. BlkResp {
  734. status: RespStatus::OK,
  735. }
  736. .as_bytes(),
  737. );
  738. response
  739. });
  740. });
  741. // Request to flush.
  742. blk.flush().unwrap();
  743. handle.join().unwrap();
  744. }
  745. #[test]
  746. fn device_id() {
  747. let mut config_space = BlkConfig {
  748. capacity_low: Volatile::new(66),
  749. capacity_high: Volatile::new(0),
  750. size_max: Volatile::new(0),
  751. seg_max: Volatile::new(0),
  752. cylinders: Volatile::new(0),
  753. heads: Volatile::new(0),
  754. sectors: Volatile::new(0),
  755. blk_size: Volatile::new(0),
  756. physical_block_exp: Volatile::new(0),
  757. alignment_offset: Volatile::new(0),
  758. min_io_size: Volatile::new(0),
  759. opt_io_size: Volatile::new(0),
  760. };
  761. let state = Arc::new(Mutex::new(State {
  762. queues: vec![QueueStatus::default()],
  763. ..Default::default()
  764. }));
  765. let transport = FakeTransport {
  766. device_type: DeviceType::Block,
  767. max_queue_size: QUEUE_SIZE.into(),
  768. device_features: BlkFeature::RING_INDIRECT_DESC.bits(),
  769. config_space: NonNull::from(&mut config_space),
  770. state: state.clone(),
  771. };
  772. let mut blk = VirtIOBlk::<FakeHal, FakeTransport<BlkConfig>>::new(transport).unwrap();
  773. // Start a thread to simulate the device waiting for a flush request.
  774. let handle = thread::spawn(move || {
  775. println!("Device waiting for a request.");
  776. State::wait_until_queue_notified(&state, QUEUE);
  777. println!("Transmit queue was notified.");
  778. state
  779. .lock()
  780. .unwrap()
  781. .read_write_queue::<{ QUEUE_SIZE as usize }>(QUEUE, |request| {
  782. assert_eq!(
  783. request,
  784. BlkReq {
  785. type_: ReqType::GetId,
  786. reserved: 0,
  787. sector: 0,
  788. }
  789. .as_bytes()
  790. );
  791. let mut response = Vec::new();
  792. response.extend_from_slice(b"device_id\0\0\0\0\0\0\0\0\0\0\0");
  793. response.extend_from_slice(
  794. BlkResp {
  795. status: RespStatus::OK,
  796. }
  797. .as_bytes(),
  798. );
  799. response
  800. });
  801. });
  802. let mut id = [0; 20];
  803. let length = blk.device_id(&mut id).unwrap();
  804. assert_eq!(&id[0..length], b"device_id");
  805. handle.join().unwrap();
  806. }
  807. }