-
Notifications
You must be signed in to change notification settings - Fork 65
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
fix: Set the member variables of the virtio queue to volatile. #127
fix: Set the member variables of the virtio queue to volatile. #127
Conversation
src/queue.rs
Outdated
avail_idx: u16, | ||
last_used_idx: u16, | ||
avail_idx: Volatile<u16>, | ||
last_used_idx: Volatile<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.
These fields are just internal state, not MMIO or even shared memory. It doesn't make sense for them to be volatile. I think the fact that this fixes the bug you're seeing must be a side-effect of the increased synchronisation, and the real issue is probably a missing fence somewhere.
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.
and the real issue is probably a missing fence somewhere.
I've tried to add fence(Ordering::SeqCst)
in can_pop()
, but cannot solve the problem. After I set the last_used_idx
and used.idx
to Volatile, the problem solved.
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.
Oh, I realized the problem. We should set all fields in usedring and avail ring Volatile
, but not the VirtQueue
. I'll fix this.
#[inline(always)] | ||
pub fn write_volatile(&mut self, value: T) { | ||
unsafe { self.self_ptr().as_ptr().write_volatile(value) } | ||
} |
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.
These methods don't make sense. If a memory location must be accessed through volatile reads or writes, e.g. because it is MMIO, then it's not sound to hold a reference to it, because the Rust memory model allows the compiler to dereference references whenever it wants. So the only case where these methods can be called is when Volatile
is being used incorrectly. The intention of this type is that it is only ever referred to via a pointer, and read and written via the VolatileReadable
and VolatileWritable
traits, possibly via the volread!
and volwrite!
macros.
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.
If I do not implement this method, then when changing the volatile variables of itself in the used ring and avail ring, I would also need to implement a method similar to self_ref(). However, that would lead to rather redundant code, so that's why I wrote it like this.
…lve the issue of the virtioblk test case hanging under RISC-V.
c0bf4a0
to
e04e9a8
Compare
Merged #125 instead. |
fix: Set the member variables of the virtio queue to volatile to resolve the issue of the virtioblk test case hanging under RISC-V.
This PR fixed issue: #125