-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New virtio blk driver #96
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add several new features to virtio-blk driver, including:
- packed queue
- indirect descriptor for packed queue and split queue
- complete two device commands: VIRTIO_BLK_T_IN and VIRTIO_BLK_T_OUT (supporting read/write multiple blocks in one request)
- add six new commands: VIRTIO_BLK_T_DISCARD, VIRTIO_BLK_T_WRITE_ZEROES, VIRTIO_BLK_T_FLUSH, VIRTIO_BLK_T_GET_ID, VIRTIO_BLK_T_SECURE_ERASE, VIRTIO_BLK_T_GET_LIFETIME (polling and interrupt)
- support asynchronous I/O (future in Rust)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! There's a lot going on here, so it's going to take a while to review it all. For a start, I've reviewed the indirect descriptor support and a few related parts.
If you'd like to get this merged more quickly it might be better to split out the other changes (packed queue, more block device features) into separate PRs.
src/device/console.rs
Outdated
@@ -65,15 +65,18 @@ pub struct ConsoleInfo { | |||
impl<H: Hal, T: Transport> VirtIOConsole<H, T> { | |||
/// Creates a new VirtIO console driver. | |||
pub fn new(mut transport: T) -> Result<Self> { | |||
// TODO: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to do something or write something more here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My primary focus is on improving the virtio-blk driver, and the usage of "TODO" here is to notify someone that the indirect descriptor is not supported in the virtio-console driver. I will make the necessary modifications to clearly convey my intention.
src/lib.rs
Outdated
pub mod transport; | ||
mod virtio_queue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why rename the module? Given that this is the virtio-drivers crate, it seems like it should be fairly clear that the queue module is for virt queues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the rename is unnecessary and I will fix it
src/virtio_queue/split_queue.rs
Outdated
@@ -1,4 +1,4 @@ | |||
#![deny(unsafe_op_in_unsafe_fn)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep this deny please, it helps keep unsafe code a bit more contained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
src/virtio_queue/packed_queue.rs
Outdated
use core::sync::atomic::{fence, Ordering}; | ||
use log::info; | ||
use zerocopy::FromBytes; | ||
// use log::{debug, info}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line, there's no point keeping it commented-out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will fix it
src/virtio_queue/split_queue.rs
Outdated
/// The mechanism for bulk data transport on virtio devices. | ||
/// | ||
/// Each device can have zero or more virtqueues. | ||
/// | ||
/// * `SIZE`: The size of the queue. This is both the number of descriptors, and the number of slots | ||
/// in the available and used rings. | ||
/// * `SIZE`: The size of the queue. This is both the number of descriptors, and the number of slots in the available and used rings. Queue Size value is always a power of 2. The maximum Queue Size value is 32768. This value is specified in a bus-specific way. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: wrap comments to 100 columns, to match the rest of the file. (Both this and the rest of the comments lower down.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will fix it
src/virtio_queue/split_queue.rs
Outdated
/// | ||
/// Ref: virtio_ring.c virtqueue_kick_prepare_split | ||
/// This will be false if the device has supressed notifications. | ||
pub fn should_notify_old(&self) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise, please just change the callers to pass false rather than having two versions of the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
src/virtio_queue/split_queue.rs
Outdated
@@ -1,4 +1,4 @@ | |||
#![deny(unsafe_op_in_unsafe_fn)] | |||
extern crate alloc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be necessary here, only in the top-level lib.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will fix it
src/virtio_queue/split_queue.rs
Outdated
@@ -280,11 +409,57 @@ impl<H: Hal, const SIZE: usize> VirtQueue<H, SIZE> { | |||
self.free_head = head; | |||
let mut next = Some(head); | |||
|
|||
for (buffer, direction) in InputOutputIter::new(inputs, outputs) { | |||
if self.indirect_desc { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still need to loop through all the buffers and unshare them with H::unshare
, to avoid leaking DMA memory on platforms that allocate it separately (and potentially missing the response entirely, as unshare
may also copy the data back to the original buffer).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let me fix it
src/virtio_queue/split_queue.rs
Outdated
// TODO: will be deleted in the further | ||
/// The buffers in `inputs` and `outputs` must match the set of buffers originally added to the | ||
/// queue by `add`. | ||
unsafe fn recycle_descriptors_async<'a>(&mut self, head: u16) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also needs to call H::unshare
on each buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will fix it
src/virtio_queue/split_queue.rs
Outdated
@@ -553,6 +794,15 @@ impl Descriptor { | |||
None | |||
} | |||
} | |||
|
|||
fn new() -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: you could just derive Default
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, nice suggestion
I've split out some of the new block device driver features into #100 so we can get that in first. Please take a look. The support for packed queues and indirect descriptors is going to require more thought, as the approach taken in this PR doesn't handle DMA memory properly. The async IO parts of this PR have some soundness issues. |
src/virtio_queue/split_queue.rs
Outdated
// Read barrier, so we read a fresh value from the device. | ||
fence(Ordering::SeqCst); | ||
|
||
// Safe because self.used points to a valid, aligned, initialised, dereferenceable, readable | ||
// instance of UsedRing. | ||
if support_event { | ||
unsafe { (*self.avail.as_ptr()).idx == (*self.used.as_ptr()).avail_event } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use self.avail_idx
rather than reading from the available ring directly, because we don't trust the device not to modify the available ring (even though it shouldn't).
Also, from my reading of the spec, it sounds like we should be checking for avail_idx == avail_event.wrapping_add(1)
, as should_notify
is called after avail_idx
is updated. See 2.7.10.2: "equivalently, until idx in the available ring will reach the value avail_event + 1".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll send a separate PR to add event_idx support with this fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me read the spec again to figure it out
No description provided.