From 6152b0cee34d55327d8d99ffe47a5450d9591585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 10:55:21 +0200 Subject: [PATCH 1/8] fix(virtqueue/packed): simplify `DrvNotif::enable_specific` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/packed.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index c15ab572bc..933e305366 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -881,10 +881,7 @@ impl DrvNotif { // Check if VIRTIO_F_RING_EVENT_IDX has been negotiated if self.f_notif_idx { self.raw.flags |= 1 << 1; - // Reset event fields - self.raw.event = 0; - self.raw.event = at_offset; - self.raw.event |= (at_wrap as u16) << 15; + self.raw.event = at_offset | (at_wrap as u16) << 15; } } } From 8eccee62d411bdbfed918192dd97650287162492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 12:56:10 +0200 Subject: [PATCH 2/8] refactor(virtqueue): extract `NotificationData` creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/transport/mmio.rs | 11 +++-------- src/drivers/virtio/transport/pci.rs | 12 +++--------- src/drivers/virtio/virtqueue/packed.rs | 22 ++++++++++++++++------ src/drivers/virtio/virtqueue/split.rs | 8 ++++++-- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/drivers/virtio/transport/mmio.rs b/src/drivers/virtio/transport/mmio.rs index 1344e392ef..7de2cda493 100644 --- a/src/drivers/virtio/transport/mmio.rs +++ b/src/drivers/virtio/transport/mmio.rs @@ -304,16 +304,11 @@ impl NotifCtrl { self.f_notif_data = true; } - pub fn notify_dev(&self, vqn: u16, next_off: u16, next_wrap: u8) { - let notification_data = NotificationData::new() - .with_vqn(vqn) - .with_next_off(next_off) - .with_next_wrap(next_wrap); - + pub fn notify_dev(&self, data: NotificationData) { let notification_data = if self.f_notif_data { - notification_data.into_bits() + data.into_bits() } else { - u32::from(notification_data.vqn()).into() + u32::from(data.vqn()).into() }; unsafe { diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index e4ca160d38..085676b1dc 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -579,26 +579,20 @@ impl NotifCtrl { self.f_notif_data = true; } - pub fn notify_dev(&self, vqn: u16, next_off: u16, next_wrap: u8) { + pub fn notify_dev(&self, data: NotificationData) { // See Virtio specification v.1.1. - 4.1.5.2 // Depending in the feature negotiation, we write either only the // virtqueue index or the index and the next position inside the queue. - let notification_data = NotificationData::new() - .with_vqn(vqn) - .with_next_off(next_off) - .with_next_wrap(next_wrap); - if self.f_notif_data { unsafe { - self.notif_addr - .write_volatile(notification_data.into_bits()); + self.notif_addr.write_volatile(data.into_bits()); } } else { unsafe { self.notif_addr .cast::() - .write_volatile(notification_data.vqn().into()); + .write_volatile(data.vqn().into()); } } } diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 933e305366..75c0627797 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -11,6 +11,7 @@ use core::ptr; use core::sync::atomic::{fence, Ordering}; use align_address::Align; +use virtio::pci::NotificationData; use zerocopy::little_endian; #[cfg(not(feature = "pci"))] @@ -969,8 +970,11 @@ impl Virtq for PackedVq { } if self.dev_event.is_notif() | self.dev_event.is_notif_specfic(next_off, next_wrap) { - self.notif_ctrl - .notify_dev(self.index.0, next_off, next_wrap); + let notification_data = NotificationData::new() + .with_vqn(self.index.0) + .with_next_off(next_off) + .with_next_wrap(next_wrap); + self.notif_ctrl.notify_dev(notification_data); } } @@ -997,8 +1001,11 @@ impl Virtq for PackedVq { } if self.dev_event.is_notif() { - self.notif_ctrl - .notify_dev(self.index.0, next_off, next_wrap); + let notification_data = NotificationData::new() + .with_vqn(self.index.0) + .with_next_off(next_off) + .with_next_wrap(next_wrap); + self.notif_ctrl.notify_dev(notification_data); } } @@ -1012,8 +1019,11 @@ impl Virtq for PackedVq { } if self.dev_event.is_notif() { - self.notif_ctrl - .notify_dev(self.index.0, next_off, next_wrap); + let notification_data = NotificationData::new() + .with_vqn(self.index.0) + .with_next_off(next_off) + .with_next_wrap(next_wrap); + self.notif_ctrl.notify_dev(notification_data); } } diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index d83d11bd8b..e94ff65f3d 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -10,6 +10,7 @@ use core::cell::{RefCell, UnsafeCell}; use core::mem::{size_of, MaybeUninit}; use core::ptr::{self, NonNull}; +use virtio::pci::NotificationData; use virtio::{le16, le32, le64}; use volatile::access::ReadOnly; use volatile::{map_field, VolatilePtr, VolatileRef}; @@ -378,8 +379,11 @@ impl Virtq for SplitVq { } if self.ring.borrow().dev_is_notif() { - self.notif_ctrl - .notify_dev(self.index.0, next_off, next_wrap); + let notification_data = NotificationData::new() + .with_vqn(self.index.0) + .with_next_off(next_off) + .with_next_wrap(next_wrap); + self.notif_ctrl.notify_dev(notification_data); } } From 525a96425994de30be5452ab054798aba381779e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 13:43:36 +0200 Subject: [PATCH 3/8] feat(virtio-spec): add `Notification::idx` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- virtio-spec/src/pci.rs | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/virtio-spec/src/pci.rs b/virtio-spec/src/pci.rs index bb9c08e689..14cd6ca911 100644 --- a/virtio-spec/src/pci.rs +++ b/virtio-spec/src/pci.rs @@ -471,3 +471,52 @@ pub struct NotificationData { #[bits(1)] pub next_wrap: u8, } + +impl NotificationData { + const NEXT_IDX_BITS: usize = 16; + const NEXT_IDX_OFFSET: usize = 16; + + /// Available index + /// + ///
+ /// + /// This collides with [`Self::next_off`] and [`Self::next_wrap`]. + /// + ///
+ /// + /// Bits: 16..32 + pub const fn next_idx(&self) -> u16 { + let mask = u32::MAX >> (u32::BITS - Self::NEXT_IDX_BITS as u32); + let this = (le32::to_ne(self.0) >> Self::NEXT_IDX_OFFSET) & mask; + this as u16 + } + + /// Available index + /// + ///
+ /// + /// This collides with [`Self::with_next_off`] and [`Self::with_next_wrap`]. + /// + ///
+ /// + /// Bits: 16..32 + pub const fn with_next_idx(self, value: u16) -> Self { + let mask = u32::MAX >> (u32::BITS - Self::NEXT_IDX_BITS as u32); + let bits = le32::to_ne(self.0) & !(mask << Self::NEXT_IDX_OFFSET) + | (value as u32 & mask) << Self::NEXT_IDX_OFFSET; + Self(le32::from_ne(bits)) + } + + /// Available index + /// + ///
+ /// + /// This collides with [`Self::set_next_off`] and [`Self::set_next_wrap`]. + /// + ///
+ /// + /// Bits: 16..32 + pub fn set_next_idx(&mut self, value: u16) { + *self = self.with_next_idx(value); + } +} From 1723d3e44ba82669476c4eeeb7c3c4321e0ff79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 13:49:19 +0200 Subject: [PATCH 4/8] fix(virtqueue/split): set `next_idx` for driver notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/split.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/drivers/virtio/virtqueue/split.rs b/src/drivers/virtio/virtqueue/split.rs index e94ff65f3d..c2a8488693 100644 --- a/src/drivers/virtio/virtqueue/split.rs +++ b/src/drivers/virtio/virtqueue/split.rs @@ -148,7 +148,7 @@ impl DescrRing { unsafe { VolatileRef::new_read_only(NonNull::new(self.used_ring_cell.get()).unwrap()) } } - fn push(&mut self, tkn: TransferToken) -> (u16, u8) { + fn push(&mut self, tkn: TransferToken) -> u16 { let mut desc_lst = Vec::new(); let mut is_indirect = false; @@ -271,9 +271,10 @@ impl DescrRing { .write(MaybeUninit::new((index as u16).into())); memory_barrier(); - map_field!(avail_ring.index).update(|val| (val.to_ne().wrapping_add(1)).into()); + let next_idx = idx.wrapping_add(1); + map_field!(avail_ring.index).write(next_idx.into()); - (0, 0) + next_idx } fn poll(&mut self) { @@ -370,7 +371,7 @@ impl Virtq for SplitVq { } fn dispatch(&self, tkn: TransferToken, notif: bool) { - let (next_off, next_wrap) = self.ring.borrow_mut().push(tkn); + let next_idx = self.ring.borrow_mut().push(tkn); if notif { // TODO: Check whether the splitvirtquue has notifications for specific descriptors @@ -381,8 +382,7 @@ impl Virtq for SplitVq { if self.ring.borrow().dev_is_notif() { let notification_data = NotificationData::new() .with_vqn(self.index.0) - .with_next_off(next_off) - .with_next_wrap(next_wrap); + .with_next_idx(next_idx); self.notif_ctrl.notify_dev(notification_data); } } From 8e06b30e25a420f02afc3946f6ba421741cc3e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 13:58:10 +0200 Subject: [PATCH 5/8] refactor(virtqueue/packed): add `RingIdx` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/packed.rs | 70 ++++++++++++++------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 75c0627797..a3759bc83a 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -26,6 +26,12 @@ use super::{ use crate::arch::mm::paging::{BasePageSize, PageSize}; use crate::arch::mm::{paging, VirtAddr}; +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +struct RingIdx { + off: u16, + wrap: u8, +} + /// A newtype of bool used for convenience in context with /// packed queues wrap counter. /// @@ -142,7 +148,7 @@ impl DescriptorRing { } } - fn push_batch(&mut self, tkn_lst: Vec) -> (u16, u8) { + fn push_batch(&mut self, tkn_lst: Vec) -> RingIdx { // Catch empty push, in order to allow zero initialized first_ctrl_settings struct // which will be overwritten in the first iteration of the for-loop assert!(!tkn_lst.is_empty()); @@ -279,11 +285,13 @@ impl DescriptorRing { self.ring[usize::from(first_ctrl_settings.0)].flags |= first_ctrl_settings.2.as_flags_avail().into(); - // Converting a boolean as u8 is fine - (first_ctrl_settings.0, first_ctrl_settings.2 .0 as u8) + RingIdx { + off: first_ctrl_settings.0, + wrap: first_ctrl_settings.2 .0.into(), + } } - fn push(&mut self, tkn: TransferToken) -> (u16, u8) { + fn push(&mut self, tkn: TransferToken) -> RingIdx { // Check length and if its fits. This should always be true due to the restriction of // the memory pool, but to be sure. assert!(tkn.buff_tkn.as_ref().unwrap().num_consuming_descr() <= self.capacity); @@ -391,8 +399,10 @@ impl DescriptorRing { ctrl.make_avail(Box::new(tkn)); fence(Ordering::SeqCst); - // Converting a boolean as u8 is fine - (ctrl.start, ctrl.wrap_at_init.0 as u8) + RingIdx { + off: ctrl.start, + wrap: ctrl.wrap_at_init.0.into(), + } } /// # Unsafe @@ -878,11 +888,11 @@ impl DrvNotif { } /// Enables a notification by the device for a specific descriptor. - fn enable_specific(&mut self, at_offset: u16, at_wrap: u8) { + fn enable_specific(&mut self, idx: RingIdx) { // Check if VIRTIO_F_RING_EVENT_IDX has been negotiated if self.f_notif_idx { self.raw.flags |= 1 << 1; - self.raw.event = at_offset | (at_wrap as u16) << 15; + self.raw.event = idx.off | (idx.wrap as u16) << 15; } } } @@ -899,15 +909,15 @@ impl DevNotif { self.raw.flags & (1 << 0) == 0 } - fn is_notif_specfic(&self, next_off: u16, next_wrap: u8) -> bool { + fn is_notif_specfic(&self, idx: RingIdx) -> bool { if self.f_notif_idx { if self.raw.flags & 1 << 1 == 2 { - // as u16 is okay for usize, as size of queue is restricted to 2^15 - // it is also okay to just loose the upper 8 bits, as we only check the LSB in second clause. - let desc_event_off = self.raw.event & !(1 << 15); - let desc_event_wrap = (self.raw.event >> 15) as u8; + let event_idx = RingIdx { + off: self.raw.event & !(1 << 15), + wrap: (self.raw.event >> 15) as u8, + }; - desc_event_off == next_off && desc_event_wrap == next_wrap + event_idx == idx } else { false } @@ -961,19 +971,17 @@ impl Virtq for PackedVq { // Zero transfers are not allowed assert!(!tkns.is_empty()); - let (next_off, next_wrap) = self.descr_ring.borrow_mut().push_batch(tkns); + let next_idx = self.descr_ring.borrow_mut().push_batch(tkns); if notif { - self.drv_event - .borrow_mut() - .enable_specific(next_off, next_wrap); + self.drv_event.borrow_mut().enable_specific(next_idx); } - if self.dev_event.is_notif() | self.dev_event.is_notif_specfic(next_off, next_wrap) { + if self.dev_event.is_notif() | self.dev_event.is_notif_specfic(next_idx) { let notification_data = NotificationData::new() .with_vqn(self.index.0) - .with_next_off(next_off) - .with_next_wrap(next_wrap); + .with_next_off(next_idx.off) + .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); } } @@ -992,37 +1000,33 @@ impl Virtq for PackedVq { tkn.await_queue = Some(await_queue.clone()); } - let (next_off, next_wrap) = self.descr_ring.borrow_mut().push_batch(tkns); + let next_idx = self.descr_ring.borrow_mut().push_batch(tkns); if notif { - self.drv_event - .borrow_mut() - .enable_specific(next_off, next_wrap); + self.drv_event.borrow_mut().enable_specific(next_idx); } if self.dev_event.is_notif() { let notification_data = NotificationData::new() .with_vqn(self.index.0) - .with_next_off(next_off) - .with_next_wrap(next_wrap); + .with_next_off(next_idx.off) + .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); } } fn dispatch(&self, tkn: TransferToken, notif: bool) { - let (next_off, next_wrap) = self.descr_ring.borrow_mut().push(tkn); + let next_idx = self.descr_ring.borrow_mut().push(tkn); if notif { - self.drv_event - .borrow_mut() - .enable_specific(next_off, next_wrap); + self.drv_event.borrow_mut().enable_specific(next_idx); } if self.dev_event.is_notif() { let notification_data = NotificationData::new() .with_vqn(self.index.0) - .with_next_off(next_off) - .with_next_wrap(next_wrap); + .with_next_off(next_idx.off) + .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); } } From a042e47f141dbde277191bdf6acb26d1332cce8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 12 Jun 2024 22:26:35 +0200 Subject: [PATCH 6/8] fix(virtqueue/packed): fix `EventSuppr` bitfield operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/packed.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index a3759bc83a..bd56119c40 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -875,24 +875,24 @@ impl EventSuppr { } impl DrvNotif { - /// Enables notifications by setting the LSB. + /// Enables notifications by unsetting the LSB. /// See Virito specification v1.1. - 2.7.10 fn enable_notif(&mut self) { self.raw.flags = 0; } - /// Disables notifications by unsetting the LSB. + /// Disables notifications by setting the LSB. /// See Virtio specification v1.1. - 2.7.10 fn disable_notif(&mut self) { - self.raw.flags = 0; + self.raw.flags = 1; } /// Enables a notification by the device for a specific descriptor. fn enable_specific(&mut self, idx: RingIdx) { // Check if VIRTIO_F_RING_EVENT_IDX has been negotiated if self.f_notif_idx { - self.raw.flags |= 1 << 1; - self.raw.event = idx.off | (idx.wrap as u16) << 15; + self.raw.flags = 2; + self.raw.event = idx.off & !(1 << 15) | (idx.wrap as u16) << 15; } } } @@ -906,12 +906,12 @@ impl DevNotif { /// Reads notification bit (i.e. LSB) and returns value. /// If notifications are enabled returns true, else false. fn is_notif(&self) -> bool { - self.raw.flags & (1 << 0) == 0 + self.raw.flags & 0b11 == 0 } fn is_notif_specfic(&self, idx: RingIdx) -> bool { if self.f_notif_idx { - if self.raw.flags & 1 << 1 == 2 { + if self.raw.flags & 0b11 == 2 { let event_idx = RingIdx { off: self.raw.event & !(1 << 15), wrap: (self.raw.event >> 15) as u8, From 46063a1550a741d3d2e05a64b1225001f3c8233a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 14:39:18 +0200 Subject: [PATCH 7/8] fix(virtqueue/packed): check range on `RING_EVENT_FLAGS_DESC` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/packed.rs | 74 +++++++++++++++++++------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index bd56119c40..25387fdba4 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -5,10 +5,10 @@ use alloc::boxed::Box; use alloc::rc::Rc; use alloc::vec::Vec; -use core::cell::RefCell; +use core::cell::{Cell, RefCell}; use core::mem::MaybeUninit; -use core::ptr; use core::sync::atomic::{fence, Ordering}; +use core::{ops, ptr}; use align_address::Align; use virtio::pci::NotificationData; @@ -26,12 +26,31 @@ use super::{ use crate::arch::mm::paging::{BasePageSize, PageSize}; use crate::arch::mm::{paging, VirtAddr}; -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)] struct RingIdx { off: u16, wrap: u8, } +trait RingIndexRange { + fn wrapping_contains(&self, item: &RingIdx) -> bool; +} + +impl RingIndexRange for ops::Range { + fn wrapping_contains(&self, item: &RingIdx) -> bool { + let ops::Range { start, end } = self; + + if start.wrap == end.wrap { + item.wrap == start.wrap && start.off <= item.off && item.off < end.off + } else if item.wrap == start.wrap { + start.off <= item.off + } else { + debug_assert!(item.wrap == end.wrap); + item.off < end.off + } + } +} + /// A newtype of bool used for convenience in context with /// packed queues wrap counter. /// @@ -909,21 +928,19 @@ impl DevNotif { self.raw.flags & 0b11 == 0 } - fn is_notif_specfic(&self, idx: RingIdx) -> bool { - if self.f_notif_idx { - if self.raw.flags & 0b11 == 2 { - let event_idx = RingIdx { - off: self.raw.event & !(1 << 15), - wrap: (self.raw.event >> 15) as u8, - }; + fn notif_specific(&self) -> Option { + if !self.f_notif_idx { + return None; + } - event_idx == idx - } else { - false - } - } else { - false + if self.raw.flags & 0b11 != 2 { + return None; } + + let off = self.raw.event & !(1 << 15); + let wrap = (self.raw.event >> 15) as u8; + + Some(RingIdx { off, wrap }) } } @@ -948,6 +965,7 @@ pub struct PackedVq { /// The virtqueues index. This identifies the virtqueue to the /// device and is unique on a per device basis. index: VqIndex, + last_next: Cell, } // Public interface of PackedVq @@ -977,12 +995,19 @@ impl Virtq for PackedVq { self.drv_event.borrow_mut().enable_specific(next_idx); } - if self.dev_event.is_notif() | self.dev_event.is_notif_specfic(next_idx) { + let range = self.last_next.get()..next_idx; + let notif_specific = self + .dev_event + .notif_specific() + .map_or(false, |idx| range.wrapping_contains(&idx)); + + if self.dev_event.is_notif() || notif_specific { let notification_data = NotificationData::new() .with_vqn(self.index.0) .with_next_off(next_idx.off) .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); + self.last_next.set(next_idx); } } @@ -1006,12 +1031,19 @@ impl Virtq for PackedVq { self.drv_event.borrow_mut().enable_specific(next_idx); } - if self.dev_event.is_notif() { + let range = self.last_next.get()..next_idx; + let notif_specific = self + .dev_event + .notif_specific() + .map_or(false, |idx| range.wrapping_contains(&idx)); + + if self.dev_event.is_notif() | notif_specific { let notification_data = NotificationData::new() .with_vqn(self.index.0) .with_next_off(next_idx.off) .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); + self.last_next.set(next_idx); } } @@ -1022,12 +1054,15 @@ impl Virtq for PackedVq { self.drv_event.borrow_mut().enable_specific(next_idx); } - if self.dev_event.is_notif() { + let notif_specific = self.dev_event.notif_specific() == Some(self.last_next.get()); + + if self.dev_event.is_notif() || notif_specific { let notification_data = NotificationData::new() .with_vqn(self.index.0) .with_next_off(next_idx.off) .with_next_wrap(next_idx.wrap); self.notif_ctrl.notify_dev(notification_data); + self.last_next.set(next_idx); } } @@ -1126,6 +1161,7 @@ impl Virtq for PackedVq { mem_pool, size: VqSize::from(vq_size), index, + last_next: Default::default(), }) } From a8c57755954d72aafa40aac39383cdeef8586dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Tue, 18 Jun 2024 16:37:24 +0200 Subject: [PATCH 8/8] fix(virtqueue/packed): use correct `next_idx` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/drivers/virtio/virtqueue/packed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/drivers/virtio/virtqueue/packed.rs b/src/drivers/virtio/virtqueue/packed.rs index 25387fdba4..f2f1b4b53b 100644 --- a/src/drivers/virtio/virtqueue/packed.rs +++ b/src/drivers/virtio/virtqueue/packed.rs @@ -305,8 +305,8 @@ impl DescriptorRing { first_ctrl_settings.2.as_flags_avail().into(); RingIdx { - off: first_ctrl_settings.0, - wrap: first_ctrl_settings.2 .0.into(), + off: self.write_index, + wrap: self.drv_wc.0.into(), } } @@ -419,8 +419,8 @@ impl DescriptorRing { fence(Ordering::SeqCst); RingIdx { - off: ctrl.start, - wrap: ctrl.wrap_at_init.0.into(), + off: self.write_index, + wrap: self.drv_wc.0.into(), } }