Skip to content

Commit cfb8a80

Browse files
authored
Merge pull request #106 from rcore-os/event_idx
Add support for VIRTIO_F_EVENT_IDX buffer notification suppression.
2 parents a2d79f1 + 6dae798 commit cfb8a80

File tree

9 files changed

+220
-77
lines changed

9 files changed

+220
-77
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ VirtIO guest drivers in Rust. For **no_std** environment.
3333
| Feature flag | Supported | |
3434
| ---------------------------- | --------- | --------------------------------------- |
3535
| `VIRTIO_F_INDIRECT_DESC` || Indirect descriptors |
36-
| `VIRTIO_F_EVENT_IDX` | | `avail_event` and `used_event` fields |
36+
| `VIRTIO_F_EVENT_IDX` | | `avail_event` and `used_event` fields |
3737
| `VIRTIO_F_VERSION_1` | TODO | VirtIO version 1 compliance |
3838
| `VIRTIO_F_ACCESS_PLATFORM` || Limited device access to memory |
3939
| `VIRTIO_F_RING_PACKED` || Packed virtqueue layout |

src/device/blk.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ const QUEUE: u16 = 0;
1313
const QUEUE_SIZE: u16 = 16;
1414
const SUPPORTED_FEATURES: BlkFeature = BlkFeature::RO
1515
.union(BlkFeature::FLUSH)
16-
.union(BlkFeature::RING_INDIRECT_DESC);
16+
.union(BlkFeature::RING_INDIRECT_DESC)
17+
.union(BlkFeature::RING_EVENT_IDX);
1718

1819
/// Driver for a VirtIO block device.
1920
///
@@ -51,15 +52,7 @@ pub struct VirtIOBlk<H: Hal, T: Transport> {
5152
impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
5253
/// Create a new VirtIO-Blk driver.
5354
pub fn new(mut transport: T) -> Result<Self> {
54-
let mut negotiated_features = BlkFeature::empty();
55-
56-
transport.begin_init(|features| {
57-
let features = BlkFeature::from_bits_truncate(features);
58-
info!("device features: {:?}", features);
59-
negotiated_features = features & SUPPORTED_FEATURES;
60-
// Negotiate these features only.
61-
negotiated_features.bits()
62-
});
55+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
6356

6457
// Read configuration space.
6558
let config = transport.config_space::<BlkConfig>()?;
@@ -74,6 +67,7 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
7467
&mut transport,
7568
QUEUE,
7669
negotiated_features.contains(BlkFeature::RING_INDIRECT_DESC),
70+
negotiated_features.contains(BlkFeature::RING_EVENT_IDX),
7771
)?;
7872
transport.finish_init();
7973

src/device/console.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use crate::{Result, PAGE_SIZE};
88
use alloc::boxed::Box;
99
use bitflags::bitflags;
1010
use core::ptr::NonNull;
11-
use log::info;
1211

1312
const QUEUE_RECEIVEQ_PORT_0: u16 = 0;
1413
const QUEUE_TRANSMITQ_PORT_0: u16 = 1;
1514
const QUEUE_SIZE: usize = 2;
15+
const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX;
1616

1717
/// Driver for a VirtIO console device.
1818
///
@@ -65,15 +65,20 @@ pub struct ConsoleInfo {
6565
impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
6666
/// Creates a new VirtIO console driver.
6767
pub fn new(mut transport: T) -> Result<Self> {
68-
transport.begin_init(|features| {
69-
let features = Features::from_bits_truncate(features);
70-
info!("Device features {:?}", features);
71-
let supported_features = Features::empty();
72-
(features & supported_features).bits()
73-
});
68+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
7469
let config_space = transport.config_space::<Config>()?;
75-
let receiveq = VirtQueue::new(&mut transport, QUEUE_RECEIVEQ_PORT_0, false)?;
76-
let transmitq = VirtQueue::new(&mut transport, QUEUE_TRANSMITQ_PORT_0, false)?;
70+
let receiveq = VirtQueue::new(
71+
&mut transport,
72+
QUEUE_RECEIVEQ_PORT_0,
73+
false,
74+
negotiated_features.contains(Features::RING_EVENT_IDX),
75+
)?;
76+
let transmitq = VirtQueue::new(
77+
&mut transport,
78+
QUEUE_TRANSMITQ_PORT_0,
79+
false,
80+
negotiated_features.contains(Features::RING_EVENT_IDX),
81+
)?;
7782

7883
// Safe because no alignment or initialisation is required for [u8], the DMA buffer is
7984
// dereferenceable, and the lifetime of the reference matches the lifetime of the DMA buffer

src/device/gpu.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use log::info;
1111
use zerocopy::{AsBytes, FromBytes};
1212

1313
const QUEUE_SIZE: u16 = 2;
14+
const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX;
1415

1516
/// A virtio based graphics adapter.
1617
///
@@ -39,12 +40,7 @@ pub struct VirtIOGpu<H: Hal, T: Transport> {
3940
impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
4041
/// Create a new VirtIO-Gpu driver.
4142
pub fn new(mut transport: T) -> Result<Self> {
42-
transport.begin_init(|features| {
43-
let features = Features::from_bits_truncate(features);
44-
info!("Device features {:?}", features);
45-
let supported_features = Features::empty();
46-
(features & supported_features).bits()
47-
});
43+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
4844

4945
// read configuration space
5046
let config_space = transport.config_space::<Config>()?;
@@ -57,8 +53,18 @@ impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
5753
);
5854
}
5955

60-
let control_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT, false)?;
61-
let cursor_queue = VirtQueue::new(&mut transport, QUEUE_CURSOR, false)?;
56+
let control_queue = VirtQueue::new(
57+
&mut transport,
58+
QUEUE_TRANSMIT,
59+
false,
60+
negotiated_features.contains(Features::RING_EVENT_IDX),
61+
)?;
62+
let cursor_queue = VirtQueue::new(
63+
&mut transport,
64+
QUEUE_CURSOR,
65+
false,
66+
negotiated_features.contains(Features::RING_EVENT_IDX),
67+
)?;
6268

6369
let queue_buf_send = FromBytes::new_box_slice_zeroed(PAGE_SIZE);
6470
let queue_buf_recv = FromBytes::new_box_slice_zeroed(PAGE_SIZE);

src/device/input.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::volatile::{volread, volwrite, ReadOnly, WriteOnly};
88
use crate::Result;
99
use alloc::boxed::Box;
1010
use core::ptr::NonNull;
11-
use log::info;
1211
use zerocopy::{AsBytes, FromBytes};
1312

1413
/// Virtual human interface devices such as keyboards, mice and tablets.
@@ -28,18 +27,23 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
2827
/// Create a new VirtIO-Input driver.
2928
pub fn new(mut transport: T) -> Result<Self> {
3029
let mut event_buf = Box::new([InputEvent::default(); QUEUE_SIZE]);
31-
transport.begin_init(|features| {
32-
let features = Feature::from_bits_truncate(features);
33-
info!("Device features: {:?}", features);
34-
// negotiate these flags only
35-
let supported_features = Feature::empty();
36-
(features & supported_features).bits()
37-
});
30+
31+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
3832

3933
let config = transport.config_space::<Config>()?;
4034

41-
let mut event_queue = VirtQueue::new(&mut transport, QUEUE_EVENT, false)?;
42-
let status_queue = VirtQueue::new(&mut transport, QUEUE_STATUS, false)?;
35+
let mut event_queue = VirtQueue::new(
36+
&mut transport,
37+
QUEUE_EVENT,
38+
false,
39+
negotiated_features.contains(Feature::RING_EVENT_IDX),
40+
)?;
41+
let status_queue = VirtQueue::new(
42+
&mut transport,
43+
QUEUE_STATUS,
44+
false,
45+
negotiated_features.contains(Feature::RING_EVENT_IDX),
46+
)?;
4347
for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
4448
// Safe because the buffer lasts as long as the queue.
4549
let token = unsafe { event_queue.add(&[], &mut [event.as_bytes_mut()])? };
@@ -193,6 +197,7 @@ pub struct InputEvent {
193197

194198
const QUEUE_EVENT: u16 = 0;
195199
const QUEUE_STATUS: u16 = 1;
200+
const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX;
196201

197202
// a parameter that can change
198203
const QUEUE_SIZE: usize = 32;

src/device/net.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{Error, Result};
88
use alloc::{vec, vec::Vec};
99
use bitflags::bitflags;
1010
use core::{convert::TryInto, mem::size_of};
11-
use log::{debug, info, warn};
11+
use log::{debug, warn};
1212
use zerocopy::{AsBytes, FromBytes};
1313

1414
const MAX_BUFFER_LEN: usize = 65535;
@@ -112,12 +112,7 @@ pub struct VirtIONet<H: Hal, T: Transport, const QUEUE_SIZE: usize> {
112112
impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE> {
113113
/// Create a new VirtIO-Net driver.
114114
pub fn new(mut transport: T, buf_len: usize) -> Result<Self> {
115-
transport.begin_init(|features| {
116-
let features = Features::from_bits_truncate(features);
117-
info!("Device features {:?}", features);
118-
let supported_features = Features::MAC | Features::STATUS;
119-
(features & supported_features).bits()
120-
});
115+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
121116
// read configuration space
122117
let config = transport.config_space::<Config>()?;
123118
let mac;
@@ -139,8 +134,18 @@ impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE>
139134
return Err(Error::InvalidParam);
140135
}
141136

142-
let send_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT, false)?;
143-
let mut recv_queue = VirtQueue::new(&mut transport, QUEUE_RECEIVE, false)?;
137+
let send_queue = VirtQueue::new(
138+
&mut transport,
139+
QUEUE_TRANSMIT,
140+
false,
141+
negotiated_features.contains(Features::RING_EVENT_IDX),
142+
)?;
143+
let mut recv_queue = VirtQueue::new(
144+
&mut transport,
145+
QUEUE_RECEIVE,
146+
false,
147+
negotiated_features.contains(Features::RING_EVENT_IDX),
148+
)?;
144149

145150
const NONE_BUF: Option<RxBuffer> = None;
146151
let mut rx_buffers = [NONE_BUF; QUEUE_SIZE];
@@ -403,3 +408,6 @@ impl GsoType {
403408

404409
const QUEUE_RECEIVE: u16 = 0;
405410
const QUEUE_TRANSMIT: u16 = 1;
411+
const SUPPORTED_FEATURES: Features = Features::MAC
412+
.union(Features::STATUS)
413+
.union(Features::RING_EVENT_IDX);

src/device/socket/vsock.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) const TX_QUEUE_IDX: u16 = 1;
1919
const EVENT_QUEUE_IDX: u16 = 2;
2020

2121
pub(crate) const QUEUE_SIZE: usize = 8;
22+
const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX;
2223

2324
/// The size in bytes of each buffer used in the RX virtqueue. This must be bigger than size_of::<VirtioVsockHdr>().
2425
const RX_BUFFER_SIZE: usize = 512;
@@ -241,13 +242,7 @@ impl<H: Hal, T: Transport> Drop for VirtIOSocket<H, T> {
241242
impl<H: Hal, T: Transport> VirtIOSocket<H, T> {
242243
/// Create a new VirtIO Vsock driver.
243244
pub fn new(mut transport: T) -> Result<Self> {
244-
transport.begin_init(|features| {
245-
let features = Feature::from_bits_truncate(features);
246-
debug!("Device features: {:?}", features);
247-
// negotiate these flags only
248-
let supported_features = Feature::empty();
249-
(features & supported_features).bits()
250-
});
245+
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
251246

252247
let config = transport.config_space::<VirtioVsockConfig>()?;
253248
debug!("config: {:?}", config);
@@ -257,9 +252,24 @@ impl<H: Hal, T: Transport> VirtIOSocket<H, T> {
257252
};
258253
debug!("guest cid: {guest_cid:?}");
259254

260-
let mut rx = VirtQueue::new(&mut transport, RX_QUEUE_IDX, false)?;
261-
let tx = VirtQueue::new(&mut transport, TX_QUEUE_IDX, false)?;
262-
let event = VirtQueue::new(&mut transport, EVENT_QUEUE_IDX, false)?;
255+
let mut rx = VirtQueue::new(
256+
&mut transport,
257+
RX_QUEUE_IDX,
258+
false,
259+
negotiated_features.contains(Feature::RING_EVENT_IDX),
260+
)?;
261+
let tx = VirtQueue::new(
262+
&mut transport,
263+
TX_QUEUE_IDX,
264+
false,
265+
negotiated_features.contains(Feature::RING_EVENT_IDX),
266+
)?;
267+
let event = VirtQueue::new(
268+
&mut transport,
269+
EVENT_QUEUE_IDX,
270+
false,
271+
negotiated_features.contains(Feature::RING_EVENT_IDX),
272+
)?;
263273

264274
// Allocate and add buffers for the RX queue.
265275
let mut rx_queue_buffers = [null_mut(); QUEUE_SIZE];

0 commit comments

Comments
 (0)