-
Notifications
You must be signed in to change notification settings - Fork 82
Add packed virtqueue support #301
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
base: main
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.
@prakash-shekhar please instead of merge main, can you rebase?
Also please write better commit messages with description other than title, explaining the why of changes.
vhost/src/vhost_kern/mod.rs
Outdated
#[cfg(feature = "vhost-user")] | ||
let is_packed = config_data.flags & VhostUserVringAddrFlags::VHOST_VRING_F_PACKED.bits() != 0; | ||
#[cfg(not(feature = "vhost-user"))] | ||
let is_packed = false; |
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.
Maybe we should add a new function for this.
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.
BTW, I'm confused, we are in VhostKernBackend
why checking for vhost-user
feature?
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.
Yep you're right vhost-kern should work independently, I'll fix that.
vhost/src/vhost_user/message.rs
Outdated
@@ -386,6 +386,8 @@ bitflags! { | |||
const LOG_ALL = 0x400_0000; | |||
/// Feature flag for the protocol feature. | |||
const PROTOCOL_FEATURES = 0x4000_0000; | |||
/// Feature flag for packed virtqueue support (VIRTIO_F_RING_PACKED, bit 34). | |||
const RING_PACKED = 0x4_0000_0000; |
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.
Is this a virtio feature or a vhost-user feature?
vhost/src/vhost_kern/mod.rs
Outdated
@@ -79,7 +79,8 @@ pub trait VhostKernBackend: AsRawFd { | |||
|
|||
// Check if packed ring format is being used | |||
#[cfg(feature = "vhost-user")] | |||
let is_packed = config_data.flags & VhostUserVringAddrFlags::VHOST_VRING_F_PACKED.bits() != 0; | |||
let is_packed = |
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 this change?
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.
Ah, please squash them where you add
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.
Can you clarify what squash means, like squashing commits?
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 unit of review is the commit, each commit should compile, pass all the test, etc. Don't add a new commit to fix a previous one in the same PR.
If you need to change a previous commit, edit, and amend
vhost/CHANGELOG.md
Outdated
@@ -3,6 +3,7 @@ | |||
## [Unreleased] | |||
|
|||
### Added | |||
- Add support for packed virtqueues in vhost-user and vhost-kern backends |
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.
Please follow the style, e.g. link to the pr, etc.
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.
Understood, will fix.
vhost-user-backend/Cargo.toml
Outdated
name = "vhost-user-backend" | ||
version = "0.18.0" | ||
version = "0.19.0" | ||
authors = ["The Cloud Hypervisor Authors"] |
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.
@stefano-garzarella is it ok to add a feature and create a release i the same PR?
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.
nope, but I think this come up from merging main
in this branch, indeed I asked to rebase it on main instead of merging, otherwise review it's a mess
vhost/src/vhost_user/message.rs
Outdated
if self.descriptor & 0xf != 0 { | ||
return false; | ||
} | ||
// - driver/device event suppression areas must be 4-byte aligned | ||
if self.available & 0x3 != 0 || self.used & 0x3 != 0 { | ||
return false; | ||
} | ||
} else { | ||
// Split ring validation (current logic) | ||
if self.descriptor & 0xf != 0 { | ||
return false; | ||
} else if self.available & 0x1 != 0 { | ||
return false; | ||
} else if self.used & 0x3 != 0 { | ||
return false; | ||
} |
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 is almost duplicated code, the only difference is the available's alignment, could this be simplified?
vhost/src/vhost_kern/mod.rs
Outdated
if is_packed { | ||
// Packed ring: single descriptor ring layout | ||
let desc_ring_size = 16 * u64::from(queue_size) as GuestUsize; | ||
let driver_event_size = 4; // 4 bytes for driver event suppression | ||
let device_event_size = 4; // 4 bytes for device event suppression | ||
|
||
// Validate packed descriptor ring | ||
if GuestAddress(config_data.desc_table_addr) | ||
.checked_add(desc_ring_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} | ||
// Validate driver event suppression area (available) | ||
if GuestAddress(config_data.avail_ring_addr) | ||
.checked_add(driver_event_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} | ||
// Validate device event suppression area (used) | ||
if GuestAddress(config_data.used_ring_addr) | ||
.checked_add(device_event_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} | ||
} else { | ||
// Split ring validation (existing logic) | ||
let desc_table_size = 16 * u64::from(queue_size) as GuestUsize; | ||
let avail_ring_size = 6 + 2 * u64::from(queue_size) as GuestUsize; | ||
let used_ring_size = 6 + 8 * u64::from(queue_size) as GuestUsize; | ||
if GuestAddress(config_data.desc_table_addr) | ||
.checked_add(desc_table_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} | ||
if GuestAddress(config_data.avail_ring_addr) | ||
.checked_add(avail_ring_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} | ||
if GuestAddress(config_data.used_ring_addr) | ||
.checked_add(used_ring_size) | ||
.is_none_or(|v| !m.address_in_range(v)) | ||
{ | ||
return false; | ||
} |
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.
can we reduce the code duplication?
Implement packed virtqueue support to improve performance through better cache locality and reduced memory overhead compared to split virtqueues. This addresses the VirtIO specification. Changes: - Add shared vring flag constants in backend.rs for architecture independence - Support packed virtqueue detection in both vhost-kern and vhost-user - Implement proper feature classification (device vs transport features) - Add validation for packed ring memory layout - Reduce code duplication in validation logic - Add test coverage for packed virtqueue functionality Signed-off-by: Prakash Shekhar <[email protected]>
Hey thank you all for the feedback. I appreciate all the comments, I'm still trying to get better at this. I won't make these mistakes again. I consolidated everything into one commit, rebased, and fixed the issues you mentioned. I'd appreciate any further feedback as well. |
don't worry, everyone makes mistakes, we are humans after all
I don't want to give you the wrong impression that we want a single commit PR, the changes (I'm not talking about this particular PR, just in general) should be divided in multiple commits if it makes sense, but always following what I said before each commit must not "fix" previous commits in the same PR(*), break the build, test, etc. Otherwise, we cannot use git bisect when we need to find an issue. (*) there are some exceptions of course, for instance, let's say in one commit you add a new function that you plan to use in another commit:
the linter will complain about dead code, so It's ok to add the function:
and in the next commit, when you call the function, to remove that attribute
|
Summary of the PR
Adds support for packed virtqueues, implementing the VirtIO packed virtqueue format alongside the existing split virtqueue support. Packed virtqueues offer improved performance through better cache locality and reduced memory overhead compared to traditional split virtqueues.
Changes:
- Updated documentation to clearly distinguish between split and packed virtqueue address semantics
- For packed virtqueues: desc_table_addr becomes the packed descriptor ring, used_ring_addr becomes driver event suppression, avail_ring_addr becomes device event suppression
- Added RING_PACKED feature flag (bit 34, value 0x4_0000_0000)
- Added VHOST_VRING_F_PACKED vring flag (bit 1, value 0x2)
- Implemented packed virtqueue inflight I/O structures (DescStatePacked, QueueRegionPacked)
- Extended kernel backend to support packed virtqueue address configuration
- Added handling of packed layout in vring setup
- Added test_packed_virtqueue_features() to validate feature flag definitions
- Added test_packed_vring_addr_validation() to test packed virtqueue address validation/alignment
Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s
), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafe
code is properly documented.