Skip to content

Commit f140e57

Browse files
Add support for packed virtqueue in message.rs and mod.rs
1 parent 77aed74 commit f140e57

File tree

2 files changed

+87
-26
lines changed

2 files changed

+87
-26
lines changed

vhost/src/vhost_kern/mod.rs

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ use super::{
2626
VringConfigData, VHOST_MAX_MEMORY_REGIONS,
2727
};
2828

29+
#[cfg(feature = "vhost-user")]
30+
use super::vhost_user::message::VhostUserVringAddrFlags;
31+
2932
pub mod vhost_binding;
3033
use self::vhost_binding::*;
3134

@@ -73,26 +76,63 @@ pub trait VhostKernBackend: AsRawFd {
7376
}
7477

7578
let m = self.mem().memory();
76-
let desc_table_size = 16 * u64::from(queue_size) as GuestUsize;
77-
let avail_ring_size = 6 + 2 * u64::from(queue_size) as GuestUsize;
78-
let used_ring_size = 6 + 8 * u64::from(queue_size) as GuestUsize;
79-
if GuestAddress(config_data.desc_table_addr)
80-
.checked_add(desc_table_size)
81-
.is_none_or(|v| !m.address_in_range(v))
82-
{
83-
return false;
84-
}
85-
if GuestAddress(config_data.avail_ring_addr)
86-
.checked_add(avail_ring_size)
87-
.is_none_or(|v| !m.address_in_range(v))
88-
{
89-
return false;
90-
}
91-
if GuestAddress(config_data.used_ring_addr)
92-
.checked_add(used_ring_size)
93-
.is_none_or(|v| !m.address_in_range(v))
94-
{
95-
return false;
79+
80+
// Check if packed ring format is being used
81+
#[cfg(feature = "vhost-user")]
82+
let is_packed = config_data.flags & VhostUserVringAddrFlags::VHOST_VRING_F_PACKED.bits() != 0;
83+
#[cfg(not(feature = "vhost-user"))]
84+
let is_packed = false;
85+
86+
if is_packed {
87+
// Packed ring: single descriptor ring layout
88+
let desc_ring_size = 16 * u64::from(queue_size) as GuestUsize;
89+
let driver_event_size = 4; // 4 bytes for driver event suppression
90+
let device_event_size = 4; // 4 bytes for device event suppression
91+
92+
// Validate packed descriptor ring
93+
if GuestAddress(config_data.desc_table_addr)
94+
.checked_add(desc_ring_size)
95+
.is_none_or(|v| !m.address_in_range(v))
96+
{
97+
return false;
98+
}
99+
// Validate driver event suppression area (available)
100+
if GuestAddress(config_data.avail_ring_addr)
101+
.checked_add(driver_event_size)
102+
.is_none_or(|v| !m.address_in_range(v))
103+
{
104+
return false;
105+
}
106+
// Validate device event suppression area (used)
107+
if GuestAddress(config_data.used_ring_addr)
108+
.checked_add(device_event_size)
109+
.is_none_or(|v| !m.address_in_range(v))
110+
{
111+
return false;
112+
}
113+
} else {
114+
// Split ring validation (existing logic)
115+
let desc_table_size = 16 * u64::from(queue_size) as GuestUsize;
116+
let avail_ring_size = 6 + 2 * u64::from(queue_size) as GuestUsize;
117+
let used_ring_size = 6 + 8 * u64::from(queue_size) as GuestUsize;
118+
if GuestAddress(config_data.desc_table_addr)
119+
.checked_add(desc_table_size)
120+
.is_none_or(|v| !m.address_in_range(v))
121+
{
122+
return false;
123+
}
124+
if GuestAddress(config_data.avail_ring_addr)
125+
.checked_add(avail_ring_size)
126+
.is_none_or(|v| !m.address_in_range(v))
127+
{
128+
return false;
129+
}
130+
if GuestAddress(config_data.used_ring_addr)
131+
.checked_add(used_ring_size)
132+
.is_none_or(|v| !m.address_in_range(v))
133+
{
134+
return false;
135+
}
96136
}
97137

98138
config_data.is_log_addr_valid()

vhost/src/vhost_user/message.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ bitflags! {
386386
const LOG_ALL = 0x400_0000;
387387
/// Feature flag for the protocol feature.
388388
const PROTOCOL_FEATURES = 0x4000_0000;
389+
/// Feature flag for packed virtqueue support (VIRTIO_F_RING_PACKED, bit 34).
390+
const RING_PACKED = 0x4_0000_0000;
389391
}
390392
}
391393

@@ -713,6 +715,9 @@ bitflags! {
713715
/// Support log of vring operations.
714716
/// Modifications to "used" vring should be logged.
715717
const VHOST_VRING_F_LOG = 0x1;
718+
/// Indicates packed virtqueue format.
719+
/// When set, the vring uses packed layout instead of split layout.
720+
const VHOST_VRING_F_PACKED = 0x2;
716721
}
717722
}
718723

@@ -777,12 +782,28 @@ impl VhostUserMsgValidator for VhostUserVringAddr {
777782
fn is_valid(&self) -> bool {
778783
if (self.flags & !VhostUserVringAddrFlags::all().bits()) != 0 {
779784
return false;
780-
} else if self.descriptor & 0xf != 0 {
781-
return false;
782-
} else if self.available & 0x1 != 0 {
783-
return false;
784-
} else if self.used & 0x3 != 0 {
785-
return false;
785+
}
786+
787+
// Check if packed ring format
788+
if self.flags & VhostUserVringAddrFlags::VHOST_VRING_F_PACKED.bits() != 0 {
789+
// Packed ring validation:
790+
// - descriptor ring must be 16-byte aligned
791+
if self.descriptor & 0xf != 0 {
792+
return false;
793+
}
794+
// - driver/device event suppression areas must be 4-byte aligned
795+
if self.available & 0x3 != 0 || self.used & 0x3 != 0 {
796+
return false;
797+
}
798+
} else {
799+
// Split ring validation (current logic)
800+
if self.descriptor & 0xf != 0 {
801+
return false;
802+
} else if self.available & 0x1 != 0 {
803+
return false;
804+
} else if self.used & 0x3 != 0 {
805+
return false;
806+
}
786807
}
787808
true
788809
}

0 commit comments

Comments
 (0)