From 8e02dc18e0e1fd09b05b5d1cdd1feb7f4531dc74 Mon Sep 17 00:00:00 2001 From: Adam Jensen Date: Tue, 30 Jan 2024 21:17:20 -0500 Subject: [PATCH 1/3] vmm: Add ResetError type Signed-off-by: Adam Jensen --- src/vmm/src/devices/virtio/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/vmm/src/devices/virtio/mod.rs b/src/vmm/src/devices/virtio/mod.rs index e79787223c4..28f3d4b679d 100644 --- a/src/vmm/src/devices/virtio/mod.rs +++ b/src/vmm/src/devices/virtio/mod.rs @@ -70,6 +70,13 @@ pub enum ActivateError { VhostUser(vhost_user::VhostUserError), } +// Errors triggered when resetting a VirtioDevice. +#[derive(Debug, thiserror::Error, displaydoc::Display)] +pub enum ResetError { + /// Reset is not implemented for the device. + NotImplemented, +} + /// Trait that helps in upcasting an object to Any pub trait AsAny { /// Return the immutable any encapsulated object. From 8f182ad37238e6f0dd8dcbd243b54da9d3d6b390 Mon Sep 17 00:00:00 2001 From: Adam Jensen Date: Tue, 30 Jan 2024 21:18:13 -0500 Subject: [PATCH 2/3] vmm: Refactor reset func to use ResetError Signed-off-by: Adam Jensen --- src/vmm/src/devices/virtio/device.rs | 9 ++++----- src/vmm/src/devices/virtio/mmio.rs | 10 +++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs index 80135576e13..f2774071ca1 100644 --- a/src/vmm/src/devices/virtio/device.rs +++ b/src/vmm/src/devices/virtio/device.rs @@ -13,7 +13,7 @@ use utils::eventfd::EventFd; use super::mmio::{VIRTIO_MMIO_INT_CONFIG, VIRTIO_MMIO_INT_VRING}; use super::queue::Queue; -use super::ActivateError; +use super::{ActivateError, ResetError}; use crate::devices::virtio::AsAny; use crate::logger::{error, warn}; use crate::vstate::memory::GuestMemoryMmap; @@ -174,10 +174,9 @@ pub trait VirtioDevice: AsAny + Send { /// Checks if the resources of this device are activated. fn is_activated(&self) -> bool; - /// Optionally deactivates this device and returns ownership of the guest memory map, interrupt - /// event, and queue events. - fn reset(&mut self) -> Option<(EventFd, Vec)> { - None + /// Optionally deactivates this device. + fn reset(&mut self) -> Result<(), ResetError> { + Err(ResetError::NotImplemented) } } diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs index 96bd914d984..fcb7458a904 100644 --- a/src/vmm/src/devices/virtio/mmio.rs +++ b/src/vmm/src/devices/virtio/mmio.rs @@ -201,8 +201,12 @@ impl MmioTransport { let mut device_status = self.device_status; let reset_result = self.locked_device().reset(); match reset_result { - Some((_interrupt_evt, mut _queue_evts)) => {} - None => { + Ok(_) => { + // The device MUST initialize device status to 0 upon reset. + device_status = INIT; + } + Err(e) => { + warn!("failed to reset virtio device: {:?}", e); device_status |= FAILED; } } @@ -469,7 +473,7 @@ pub(crate) mod tests { let m = single_region_mem(0x1000); let mut dummy = DummyDevice::new(); // Validate reset is no-op. - assert!(dummy.reset().is_none()); + assert!(dummy.reset().is_err()); let mut d = MmioTransport::new(m, Arc::new(Mutex::new(dummy)), false); // We just make sure here that the implementation of a mmio device behaves as we expect, From a3f3ad96f2c99fb2987bb9ce4c0365a7a03095b6 Mon Sep 17 00:00:00 2001 From: Adam Jensen Date: Tue, 30 Jan 2024 21:18:27 -0500 Subject: [PATCH 3/3] vmm: Implement basic reset capability for net device Signed-off-by: Adam Jensen --- src/vmm/src/devices/virtio/net/device.rs | 41 ++++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/vmm/src/devices/virtio/net/device.rs b/src/vmm/src/devices/virtio/net/device.rs index 9d8cdfd7372..5ac24ef0e65 100755 --- a/src/vmm/src/devices/virtio/net/device.rs +++ b/src/vmm/src/devices/virtio/net/device.rs @@ -34,7 +34,7 @@ use crate::devices::virtio::net::{ gen, NetError, NetQueue, MAX_BUFFER_SIZE, NET_QUEUE_SIZES, RX_INDEX, TX_INDEX, }; use crate::devices::virtio::queue::{DescriptorChain, Queue}; -use crate::devices::virtio::{ActivateError, TYPE_NET}; +use crate::devices::virtio::{ActivateError, ResetError, TYPE_NET}; use crate::devices::{report_net_event_fail, DeviceError}; use crate::dumbo::pdu::arp::ETH_IPV4_FRAME_LEN; use crate::dumbo::pdu::ethernet::{EthernetFrame, PAYLOAD_OFFSET}; @@ -870,6 +870,15 @@ impl VirtioDevice for Net { fn is_activated(&self) -> bool { self.device_state.is_activated() } + + fn reset(&mut self) -> Result<(), ResetError> { + self.device_state = DeviceState::Inactive; + self.rx_bytes_read = 0; + self.rx_deferred_frame = false; + self.rx_frame_buf = [0u8; MAX_BUFFER_SIZE]; + self.metrics = NetMetricsPerDevice::alloc(self.id.clone()); + Ok(()) + } } #[cfg(test)] @@ -2015,17 +2024,29 @@ pub mod tests { th.activate_net(); let net = th.net.lock().unwrap(); - // Test queues count (TX and RX). - let queues = net.queues(); - assert_eq!(queues.len(), NET_QUEUE_SIZES.len()); - assert_eq!(queues[RX_INDEX].size, th.rxq.size()); - assert_eq!(queues[TX_INDEX].size, th.txq.size()); + let validate = |net: &Net| { + // Test queues count (TX and RX). + let queues = net.queues(); + assert_eq!(queues.len(), NET_QUEUE_SIZES.len()); + assert_eq!(queues[RX_INDEX].size, th.rxq.size()); + assert_eq!(queues[TX_INDEX].size, th.txq.size()); + + // Test corresponding queues events. + assert_eq!(net.queue_events().len(), NET_QUEUE_SIZES.len()); + + // Test interrupts. + assert!(!&net.irq_trigger.has_pending_irq(IrqType::Vring)); + }; + + validate(&net); - // Test corresponding queues events. - assert_eq!(net.queue_events().len(), NET_QUEUE_SIZES.len()); + // Test reset. + let mut net = net; + assert!(net.device_state.is_activated()); + net.reset().unwrap(); + assert!(!net.device_state.is_activated()); - // Test interrupts. - assert!(!&net.irq_trigger.has_pending_irq(IrqType::Vring)); + validate(&net); } #[test]