Skip to content
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

Conversation

fslongjin
Copy link
Contributor

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

src/queue.rs Outdated
avail_idx: u16,
last_used_idx: u16,
avail_idx: Volatile<u16>,
last_used_idx: Volatile<u16>,
Copy link
Collaborator

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.

Copy link
Contributor Author

@fslongjin fslongjin Apr 22, 2024

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.

Copy link
Contributor Author

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) }
}
Copy link
Collaborator

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.

Copy link
Contributor Author

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.
@fslongjin fslongjin force-pushed the patch-set-virtio-queue-members-to-volatile branch from c0bf4a0 to e04e9a8 Compare April 22, 2024 14:58
@qwandor
Copy link
Collaborator

qwandor commented Apr 23, 2024

Merged #125 instead.

@qwandor qwandor closed this Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants