Skip to content

Commit

Permalink
Merge pull request #106 from rcore-os/event_idx
Browse files Browse the repository at this point in the history
Add support for VIRTIO_F_EVENT_IDX buffer notification suppression.
  • Loading branch information
qwandor authored Jul 26, 2023
2 parents a2d79f1 + 6dae798 commit cfb8a80
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 77 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ VirtIO guest drivers in Rust. For **no_std** environment.
| Feature flag | Supported | |
| ---------------------------- | --------- | --------------------------------------- |
| `VIRTIO_F_INDIRECT_DESC` || Indirect descriptors |
| `VIRTIO_F_EVENT_IDX` | | `avail_event` and `used_event` fields |
| `VIRTIO_F_EVENT_IDX` | | `avail_event` and `used_event` fields |
| `VIRTIO_F_VERSION_1` | TODO | VirtIO version 1 compliance |
| `VIRTIO_F_ACCESS_PLATFORM` || Limited device access to memory |
| `VIRTIO_F_RING_PACKED` || Packed virtqueue layout |
Expand Down
14 changes: 4 additions & 10 deletions src/device/blk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const QUEUE: u16 = 0;
const QUEUE_SIZE: u16 = 16;
const SUPPORTED_FEATURES: BlkFeature = BlkFeature::RO
.union(BlkFeature::FLUSH)
.union(BlkFeature::RING_INDIRECT_DESC);
.union(BlkFeature::RING_INDIRECT_DESC)
.union(BlkFeature::RING_EVENT_IDX);

/// Driver for a VirtIO block device.
///
Expand Down Expand Up @@ -51,15 +52,7 @@ pub struct VirtIOBlk<H: Hal, T: Transport> {
impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
/// Create a new VirtIO-Blk driver.
pub fn new(mut transport: T) -> Result<Self> {
let mut negotiated_features = BlkFeature::empty();

transport.begin_init(|features| {
let features = BlkFeature::from_bits_truncate(features);
info!("device features: {:?}", features);
negotiated_features = features & SUPPORTED_FEATURES;
// Negotiate these features only.
negotiated_features.bits()
});
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);

// Read configuration space.
let config = transport.config_space::<BlkConfig>()?;
Expand All @@ -74,6 +67,7 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
&mut transport,
QUEUE,
negotiated_features.contains(BlkFeature::RING_INDIRECT_DESC),
negotiated_features.contains(BlkFeature::RING_EVENT_IDX),
)?;
transport.finish_init();

Expand Down
23 changes: 14 additions & 9 deletions src/device/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use crate::{Result, PAGE_SIZE};
use alloc::boxed::Box;
use bitflags::bitflags;
use core::ptr::NonNull;
use log::info;

const QUEUE_RECEIVEQ_PORT_0: u16 = 0;
const QUEUE_TRANSMITQ_PORT_0: u16 = 1;
const QUEUE_SIZE: usize = 2;
const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX;

/// Driver for a VirtIO console device.
///
Expand Down Expand Up @@ -65,15 +65,20 @@ pub struct ConsoleInfo {
impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
/// Creates a new VirtIO console driver.
pub fn new(mut transport: T) -> Result<Self> {
transport.begin_init(|features| {
let features = Features::from_bits_truncate(features);
info!("Device features {:?}", features);
let supported_features = Features::empty();
(features & supported_features).bits()
});
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
let config_space = transport.config_space::<Config>()?;
let receiveq = VirtQueue::new(&mut transport, QUEUE_RECEIVEQ_PORT_0, false)?;
let transmitq = VirtQueue::new(&mut transport, QUEUE_TRANSMITQ_PORT_0, false)?;
let receiveq = VirtQueue::new(
&mut transport,
QUEUE_RECEIVEQ_PORT_0,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;
let transmitq = VirtQueue::new(
&mut transport,
QUEUE_TRANSMITQ_PORT_0,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;

// Safe because no alignment or initialisation is required for [u8], the DMA buffer is
// dereferenceable, and the lifetime of the reference matches the lifetime of the DMA buffer
Expand Down
22 changes: 14 additions & 8 deletions src/device/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use log::info;
use zerocopy::{AsBytes, FromBytes};

const QUEUE_SIZE: u16 = 2;
const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX;

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

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

let control_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT, false)?;
let cursor_queue = VirtQueue::new(&mut transport, QUEUE_CURSOR, false)?;
let control_queue = VirtQueue::new(
&mut transport,
QUEUE_TRANSMIT,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;
let cursor_queue = VirtQueue::new(
&mut transport,
QUEUE_CURSOR,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;

let queue_buf_send = FromBytes::new_box_slice_zeroed(PAGE_SIZE);
let queue_buf_recv = FromBytes::new_box_slice_zeroed(PAGE_SIZE);
Expand Down
25 changes: 15 additions & 10 deletions src/device/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::volatile::{volread, volwrite, ReadOnly, WriteOnly};
use crate::Result;
use alloc::boxed::Box;
use core::ptr::NonNull;
use log::info;
use zerocopy::{AsBytes, FromBytes};

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

let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);

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

let mut event_queue = VirtQueue::new(&mut transport, QUEUE_EVENT, false)?;
let status_queue = VirtQueue::new(&mut transport, QUEUE_STATUS, false)?;
let mut event_queue = VirtQueue::new(
&mut transport,
QUEUE_EVENT,
false,
negotiated_features.contains(Feature::RING_EVENT_IDX),
)?;
let status_queue = VirtQueue::new(
&mut transport,
QUEUE_STATUS,
false,
negotiated_features.contains(Feature::RING_EVENT_IDX),
)?;
for (i, event) in event_buf.as_mut().iter_mut().enumerate() {
// Safe because the buffer lasts as long as the queue.
let token = unsafe { event_queue.add(&[], &mut [event.as_bytes_mut()])? };
Expand Down Expand Up @@ -193,6 +197,7 @@ pub struct InputEvent {

const QUEUE_EVENT: u16 = 0;
const QUEUE_STATUS: u16 = 1;
const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX;

// a parameter that can change
const QUEUE_SIZE: usize = 32;
26 changes: 17 additions & 9 deletions src/device/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{Error, Result};
use alloc::{vec, vec::Vec};
use bitflags::bitflags;
use core::{convert::TryInto, mem::size_of};
use log::{debug, info, warn};
use log::{debug, warn};
use zerocopy::{AsBytes, FromBytes};

const MAX_BUFFER_LEN: usize = 65535;
Expand Down Expand Up @@ -112,12 +112,7 @@ pub struct VirtIONet<H: Hal, T: Transport, const QUEUE_SIZE: usize> {
impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE> {
/// Create a new VirtIO-Net driver.
pub fn new(mut transport: T, buf_len: usize) -> Result<Self> {
transport.begin_init(|features| {
let features = Features::from_bits_truncate(features);
info!("Device features {:?}", features);
let supported_features = Features::MAC | Features::STATUS;
(features & supported_features).bits()
});
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
// read configuration space
let config = transport.config_space::<Config>()?;
let mac;
Expand All @@ -139,8 +134,18 @@ impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE>
return Err(Error::InvalidParam);
}

let send_queue = VirtQueue::new(&mut transport, QUEUE_TRANSMIT, false)?;
let mut recv_queue = VirtQueue::new(&mut transport, QUEUE_RECEIVE, false)?;
let send_queue = VirtQueue::new(
&mut transport,
QUEUE_TRANSMIT,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;
let mut recv_queue = VirtQueue::new(
&mut transport,
QUEUE_RECEIVE,
false,
negotiated_features.contains(Features::RING_EVENT_IDX),
)?;

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

const QUEUE_RECEIVE: u16 = 0;
const QUEUE_TRANSMIT: u16 = 1;
const SUPPORTED_FEATURES: Features = Features::MAC
.union(Features::STATUS)
.union(Features::RING_EVENT_IDX);
30 changes: 20 additions & 10 deletions src/device/socket/vsock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub(crate) const TX_QUEUE_IDX: u16 = 1;
const EVENT_QUEUE_IDX: u16 = 2;

pub(crate) const QUEUE_SIZE: usize = 8;
const SUPPORTED_FEATURES: Feature = Feature::RING_EVENT_IDX;

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

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

let mut rx = VirtQueue::new(&mut transport, RX_QUEUE_IDX, false)?;
let tx = VirtQueue::new(&mut transport, TX_QUEUE_IDX, false)?;
let event = VirtQueue::new(&mut transport, EVENT_QUEUE_IDX, false)?;
let mut rx = VirtQueue::new(
&mut transport,
RX_QUEUE_IDX,
false,
negotiated_features.contains(Feature::RING_EVENT_IDX),
)?;
let tx = VirtQueue::new(
&mut transport,
TX_QUEUE_IDX,
false,
negotiated_features.contains(Feature::RING_EVENT_IDX),
)?;
let event = VirtQueue::new(
&mut transport,
EVENT_QUEUE_IDX,
false,
negotiated_features.contains(Feature::RING_EVENT_IDX),
)?;

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

0 comments on commit cfb8a80

Please sign in to comment.