Skip to content

Commit 1c0ff9d

Browse files
cagatay-yGelbpunkt
andcommitted
virtq: use enum_dispatch
Closes hermit-os#989 Co-authored-by: Jens Reidel <[email protected]>
1 parent d7203ed commit 1c0ff9d

File tree

11 files changed

+127
-115
lines changed

11 files changed

+127
-115
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ bitflags = "2"
110110
build-time = "0.1.3"
111111
cfg-if = "1"
112112
crossbeam-utils = { version = "0.8", default-features = false }
113+
enum_dispatch = "0.3"
113114
fdt = { version = "0.1", features = ["pretty-printing"] }
114115
free-list = "0.3"
115116
fuse-abi = { version = "0.2", features = ["linux", "zerocopy"], optional = true }

src/drivers/fs/virtio_fs.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
1919
use crate::drivers::virtio::virtqueue::error::VirtqError;
2020
use crate::drivers::virtio::virtqueue::split::SplitVq;
2121
use crate::drivers::virtio::virtqueue::{
22-
AvailBufferToken, BufferElem, BufferType, Virtq, VqIndex, VqSize,
22+
AvailBufferToken, BufferElem, BufferType, VirtQueue, Virtq, VqIndex, VqSize,
2323
};
2424
use crate::fs::fuse::{self, FuseInterface, Rsp, RspHeader};
2525
use crate::mm::device_alloc::DeviceAlloc;
@@ -43,7 +43,7 @@ pub(crate) struct VirtioFsDriver {
4343
pub(super) com_cfg: ComCfg,
4444
pub(super) isr_stat: IsrStatus,
4545
pub(super) notif_cfg: NotifCfg,
46-
pub(super) vqueues: Vec<Box<dyn Virtq>>,
46+
pub(super) vqueues: Vec<VirtQueue>,
4747
pub(super) irq: InterruptLine,
4848
}
4949

@@ -133,15 +133,17 @@ impl VirtioFsDriver {
133133

134134
// create the queues and tell device about them
135135
for i in 0..vqnum as u16 {
136-
let vq = SplitVq::new(
137-
&mut self.com_cfg,
138-
&self.notif_cfg,
139-
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
140-
VqIndex::from(i),
141-
self.dev_cfg.features.into(),
142-
)
143-
.unwrap();
144-
self.vqueues.push(Box::new(vq));
136+
let vq = VirtQueue::Split(
137+
SplitVq::new(
138+
&mut self.com_cfg,
139+
&self.notif_cfg,
140+
VqSize::from(VIRTIO_MAX_QUEUE_SIZE),
141+
VqIndex::from(i),
142+
self.dev_cfg.features.into(),
143+
)
144+
.unwrap(),
145+
);
146+
self.vqueues.push(vq);
145147
}
146148

147149
// At this point the device is "live"

src/drivers/net/virtio/mmio.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//!
33
//! The module contains ...
44
5-
use alloc::boxed::Box;
65
use alloc::vec::Vec;
76
use core::str::FromStr;
87

@@ -14,7 +13,7 @@ use crate::drivers::InterruptLine;
1413
use crate::drivers::net::virtio::{CtrlQueue, NetDevCfg, RxQueues, TxQueues, VirtioNetDriver};
1514
use crate::drivers::virtio::error::{VirtioError, VirtioNetError};
1615
use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg};
17-
use crate::drivers::virtio::virtqueue::Virtq;
16+
use crate::drivers::virtio::virtqueue::VirtQueue;
1817

1918
// Backend-dependent interface for Virtio network driver
2019
impl VirtioNetDriver {
@@ -48,8 +47,8 @@ impl VirtioNetDriver {
4847
1514
4948
};
5049

51-
let send_vqs = TxQueues::new(Vec::<Box<dyn Virtq>>::new(), &dev_cfg);
52-
let recv_vqs = RxQueues::new(Vec::<Box<dyn Virtq>>::new(), &dev_cfg);
50+
let send_vqs = TxQueues::new(Vec::<VirtQueue>::new(), &dev_cfg);
51+
let recv_vqs = RxQueues::new(Vec::<VirtQueue>::new(), &dev_cfg);
5352
Ok(VirtioNetDriver {
5453
dev_cfg,
5554
com_cfg: ComCfg::new(registers, 1),

src/drivers/net/virtio/mod.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg};
3131
use crate::drivers::virtio::virtqueue::packed::PackedVq;
3232
use crate::drivers::virtio::virtqueue::split::SplitVq;
3333
use crate::drivers::virtio::virtqueue::{
34-
AvailBufferToken, BufferElem, BufferType, UsedBufferToken, Virtq, VqIndex, VqSize,
34+
AvailBufferToken, BufferElem, BufferType, UsedBufferToken, VirtQueue, Virtq, VqIndex, VqSize,
3535
};
3636
use crate::drivers::{Driver, InterruptLine};
3737
use crate::executor::device::{RxToken, TxToken};
@@ -46,21 +46,21 @@ pub(crate) struct NetDevCfg {
4646
pub features: virtio::net::F,
4747
}
4848

49-
pub struct CtrlQueue(Option<Box<dyn Virtq>>);
49+
pub struct CtrlQueue(Option<VirtQueue>);
5050

5151
impl CtrlQueue {
52-
pub fn new(vq: Option<Box<dyn Virtq>>) -> Self {
52+
pub fn new(vq: Option<VirtQueue>) -> Self {
5353
CtrlQueue(vq)
5454
}
5555
}
5656

5757
pub struct RxQueues {
58-
vqs: Vec<Box<dyn Virtq>>,
58+
vqs: Vec<VirtQueue>,
5959
packet_size: u32,
6060
}
6161

6262
impl RxQueues {
63-
pub fn new(vqs: Vec<Box<dyn Virtq>>, dev_cfg: &NetDevCfg) -> Self {
63+
pub fn new(vqs: Vec<VirtQueue>, dev_cfg: &NetDevCfg) -> Self {
6464
// See Virtio specification v1.1 - 5.1.6.3.1
6565
//
6666
let packet_size = if dev_cfg.features.contains(virtio::net::F::MRG_RXBUF) {
@@ -83,10 +83,10 @@ impl RxQueues {
8383
/// Adds a given queue to the underlying vector and populates the queue with RecvBuffers.
8484
///
8585
/// Queues are all populated according to Virtio specification v1.1. - 5.1.6.3.1
86-
fn add(&mut self, mut vq: Box<dyn Virtq>) {
86+
fn add(&mut self, mut vq: VirtQueue) {
8787
const BUFF_PER_PACKET: u16 = 2;
8888
let num_packets: u16 = u16::from(vq.size()) / BUFF_PER_PACKET;
89-
fill_queue(vq.as_mut(), num_packets, self.packet_size);
89+
fill_queue(&mut vq, num_packets, self.packet_size);
9090
self.vqs.push(vq);
9191
}
9292

@@ -111,7 +111,7 @@ impl RxQueues {
111111
}
112112
}
113113

114-
fn fill_queue(vq: &mut dyn Virtq, num_packets: u16, packet_size: u32) {
114+
fn fill_queue(vq: &mut VirtQueue, num_packets: u16, packet_size: u32) {
115115
for _ in 0..num_packets {
116116
let buff_tkn = match AvailBufferToken::new(
117117
vec![],
@@ -143,14 +143,14 @@ fn fill_queue(vq: &mut dyn Virtq, num_packets: u16, packet_size: u32) {
143143
/// Structure which handles transmission of packets and delegation
144144
/// to the respective queue structures.
145145
pub struct TxQueues {
146-
vqs: Vec<Box<dyn Virtq>>,
146+
vqs: Vec<VirtQueue>,
147147
/// Indicates, whether the Driver/Device are using multiple
148148
/// queues for communication.
149149
packet_length: u32,
150150
}
151151

152152
impl TxQueues {
153-
pub fn new(vqs: Vec<Box<dyn Virtq>>, dev_cfg: &NetDevCfg) -> Self {
153+
pub fn new(vqs: Vec<VirtQueue>, dev_cfg: &NetDevCfg) -> Self {
154154
let packet_length = if dev_cfg.features.contains(virtio::net::F::GUEST_TSO4)
155155
| dev_cfg.features.contains(virtio::net::F::GUEST_TSO6)
156156
| dev_cfg.features.contains(virtio::net::F::GUEST_UFO)
@@ -184,7 +184,7 @@ impl TxQueues {
184184
}
185185
}
186186

187-
fn add(&mut self, vq: Box<dyn Virtq>) {
187+
fn add(&mut self, vq: VirtQueue) {
188188
// Currently we are doing nothing with the additional queues. They are inactive and might be used in the
189189
// future
190190
self.vqs.push(vq);
@@ -333,7 +333,7 @@ impl NetworkDriver for VirtioNetDriver {
333333
}
334334

335335
fill_queue(
336-
self.recv_vqs.vqs[0].as_mut(),
336+
&mut self.recv_vqs.vqs[0],
337337
num_buffers,
338338
self.recv_vqs.packet_size,
339339
);
@@ -657,7 +657,7 @@ impl VirtioNetDriver {
657657
// Add a control if feature is negotiated
658658
if self.dev_cfg.features.contains(virtio::net::F::CTRL_VQ) {
659659
if self.dev_cfg.features.contains(virtio::net::F::RING_PACKED) {
660-
self.ctrl_vq = CtrlQueue(Some(Box::new(
660+
self.ctrl_vq = CtrlQueue(Some(VirtQueue::Packed(
661661
PackedVq::new(
662662
&mut self.com_cfg,
663663
&self.notif_cfg,
@@ -668,7 +668,7 @@ impl VirtioNetDriver {
668668
.unwrap(),
669669
)));
670670
} else {
671-
self.ctrl_vq = CtrlQueue(Some(Box::new(
671+
self.ctrl_vq = CtrlQueue(Some(VirtQueue::Split(
672672
SplitVq::new(
673673
&mut self.com_cfg,
674674
&self.notif_cfg,
@@ -744,7 +744,7 @@ impl VirtioNetDriver {
744744
// Interrupt for receiving packets is wanted
745745
vq.enable_notifs();
746746

747-
self.recv_vqs.add(Box::from(vq));
747+
self.recv_vqs.add(VirtQueue::Packed(vq));
748748

749749
let mut vq = PackedVq::new(
750750
&mut self.com_cfg,
@@ -757,7 +757,7 @@ impl VirtioNetDriver {
757757
// Interrupt for communicating that a sended packet left, is not needed
758758
vq.disable_notifs();
759759

760-
self.send_vqs.add(Box::from(vq));
760+
self.send_vqs.add(VirtQueue::Packed(vq));
761761
} else {
762762
let mut vq = SplitVq::new(
763763
&mut self.com_cfg,
@@ -770,7 +770,7 @@ impl VirtioNetDriver {
770770
// Interrupt for receiving packets is wanted
771771
vq.enable_notifs();
772772

773-
self.recv_vqs.add(Box::from(vq));
773+
self.recv_vqs.add(VirtQueue::Split(vq));
774774

775775
let mut vq = SplitVq::new(
776776
&mut self.com_cfg,
@@ -783,7 +783,7 @@ impl VirtioNetDriver {
783783
// Interrupt for communicating that a sended packet left, is not needed
784784
vq.disable_notifs();
785785

786-
self.send_vqs.add(Box::from(vq));
786+
self.send_vqs.add(VirtQueue::Split(vq));
787787
}
788788
}
789789

src/drivers/pci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ pub(crate) fn init() {
542542
}
543543
#[cfg(feature = "vsock")]
544544
Ok(VirtioDriver::Vsock(drv)) => {
545-
register_driver(PciDriver::VirtioVsock(InterruptTicketMutex::new(drv)));
545+
register_driver(PciDriver::VirtioVsock(InterruptTicketMutex::new(*drv)));
546546
}
547547
#[cfg(feature = "fuse")]
548548
Ok(VirtioDriver::FileSystem(drv)) => {

src/drivers/virtio/transport/pci.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! The module contains ...
44
#![allow(dead_code)]
55

6+
use alloc::boxed::Box;
67
use alloc::vec::Vec;
78
use core::ptr::NonNull;
89
use core::{mem, ptr};
@@ -836,7 +837,7 @@ pub(crate) fn init_device(
836837
crate::arch::interrupts::add_irq_name(irq, "virtio");
837838
info!("Virtio interrupt handler at line {irq}");
838839

839-
Ok(VirtioDriver::Vsock(virt_sock_drv))
840+
Ok(VirtioDriver::Vsock(Box::new(virt_sock_drv)))
840841
}
841842
Err(virtio_error) => {
842843
error!("Virtio sock driver could not be initialized with device: {device_id:x}");
@@ -878,7 +879,7 @@ pub(crate) enum VirtioDriver {
878879
))]
879880
Network(VirtioNetDriver),
880881
#[cfg(feature = "vsock")]
881-
Vsock(VirtioVsockDriver),
882+
Vsock(Box<VirtioVsockDriver>),
882883
#[cfg(feature = "fuse")]
883884
FileSystem(VirtioFsDriver),
884885
}

src/drivers/virtio/virtqueue/mod.rs

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,14 @@ use core::any::Any;
1919
use core::mem::MaybeUninit;
2020
use core::{mem, ptr};
2121

22+
use enum_dispatch::enum_dispatch;
2223
use memory_addresses::VirtAddr;
2324
use virtio::{le32, le64, pvirtq, virtq};
2425

2526
use self::error::VirtqError;
26-
#[cfg(not(feature = "pci"))]
27-
use super::transport::mmio::{ComCfg, NotifCfg};
28-
#[cfg(feature = "pci")]
29-
use super::transport::pci::{ComCfg, NotifCfg};
3027
use crate::arch::mm::paging;
28+
use crate::drivers::virtio::virtqueue::packed::PackedVq;
29+
use crate::drivers::virtio::virtqueue::split::SplitVq;
3130
use crate::mm::device_alloc::DeviceAlloc;
3231

3332
/// A u16 newtype. If instantiated via ``VqIndex::from(T)``, the newtype is ensured to be
@@ -97,6 +96,7 @@ impl From<VqSize> for u16 {
9796
/// might not provide the complete feature set of each queue. Drivers who
9897
/// do need these features should refrain from providing support for both
9998
/// Virtqueue types and use the structs directly instead.
99+
#[enum_dispatch]
100100
pub trait Virtq: Send {
101101
/// The `notif` parameter indicates if the driver wants to have a notification for this specific
102102
/// transfer. This is only for performance optimization. As it is NOT ensured, that the device sees the
@@ -185,21 +185,6 @@ pub trait Virtq: Send {
185185
notif: bool,
186186
) -> Result<(), VirtqError>;
187187

188-
/// Creates a new Virtq of the specified [VqSize] and the [VqIndex].
189-
/// The index represents the "ID" of the virtqueue.
190-
/// Upon creation the virtqueue is "registered" at the device via the `ComCfg` struct.
191-
///
192-
/// Be aware, that devices define a maximum number of queues and a maximal size they can handle.
193-
fn new(
194-
com_cfg: &mut ComCfg,
195-
notif_cfg: &NotifCfg,
196-
size: VqSize,
197-
index: VqIndex,
198-
features: virtio::F,
199-
) -> Result<Self, VirtqError>
200-
where
201-
Self: Sized;
202-
203188
/// Returns the size of a Virtqueue. This represents the overall size and not the capacity the
204189
/// queue currently has for new descriptors.
205190
fn size(&self) -> VqSize;
@@ -282,6 +267,12 @@ trait VirtqPrivate {
282267
}
283268
}
284269

270+
#[enum_dispatch(Virtq)]
271+
pub(crate) enum VirtQueue {
272+
Split(SplitVq),
273+
Packed(PackedVq),
274+
}
275+
285276
trait VirtqDescriptor {
286277
fn flags_mut(&mut self) -> &mut virtq::DescF;
287278

0 commit comments

Comments
 (0)