mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-07-05 01:12:36 +00:00
Revert "virtio-devices, vmm: Optimised async virtio device activation"
This reverts commit f160572f9d
.
There has been increased flakiness around the live migration tests since
this was merged. Speculatively reverting to see if there is increased
stability.
Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
80f6dda932
commit
fa07d83565
@ -6,7 +6,7 @@ use vmm_sys_util::eventfd::EventFd;
|
|||||||
mod pci_common_config;
|
mod pci_common_config;
|
||||||
mod pci_device;
|
mod pci_device;
|
||||||
pub use pci_common_config::VirtioPciCommonConfig;
|
pub use pci_common_config::VirtioPciCommonConfig;
|
||||||
pub use pci_device::{VirtioPciDevice, VirtioPciDeviceActivator};
|
pub use pci_device::VirtioPciDevice;
|
||||||
|
|
||||||
pub trait VirtioTransport {
|
pub trait VirtioTransport {
|
||||||
fn ioeventfds(&self, base_addr: u64) -> Vec<(&EventFd, u64)>;
|
fn ioeventfds(&self, base_addr: u64) -> Vec<(&EventFd, u64)>;
|
||||||
|
@ -287,37 +287,6 @@ struct VirtioPciDeviceState {
|
|||||||
|
|
||||||
impl VersionMapped for VirtioPciDeviceState {}
|
impl VersionMapped for VirtioPciDeviceState {}
|
||||||
|
|
||||||
pub struct VirtioPciDeviceActivator {
|
|
||||||
interrupt: Option<Arc<dyn VirtioInterrupt>>,
|
|
||||||
memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
|
|
||||||
device: Arc<Mutex<dyn VirtioDevice>>,
|
|
||||||
device_activated: Arc<AtomicBool>,
|
|
||||||
queues: Option<Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>>>,
|
|
||||||
queue_evts: Option<Vec<EventFd>>,
|
|
||||||
barrier: Option<Arc<Barrier>>,
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VirtioPciDeviceActivator {
|
|
||||||
pub fn activate(&mut self) -> ActivateResult {
|
|
||||||
self.device.lock().unwrap().activate(
|
|
||||||
self.memory.take().unwrap(),
|
|
||||||
self.interrupt.take().unwrap(),
|
|
||||||
self.queues.take().unwrap(),
|
|
||||||
self.queue_evts.take().unwrap(),
|
|
||||||
)?;
|
|
||||||
self.device_activated.store(true, Ordering::SeqCst);
|
|
||||||
|
|
||||||
if let Some(barrier) = self.barrier.take() {
|
|
||||||
info!("{}: Waiting for barrier", self.id);
|
|
||||||
barrier.wait();
|
|
||||||
info!("{}: Barrier released", self.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VirtioPciDevice {
|
pub struct VirtioPciDevice {
|
||||||
id: String,
|
id: String,
|
||||||
|
|
||||||
@ -369,11 +338,11 @@ pub struct VirtioPciDevice {
|
|||||||
// EventFd to signal on to request activation
|
// EventFd to signal on to request activation
|
||||||
activate_evt: EventFd,
|
activate_evt: EventFd,
|
||||||
|
|
||||||
|
// Barrier that is used to wait on for activation
|
||||||
|
activate_barrier: Arc<Barrier>,
|
||||||
|
|
||||||
// Optional DMA handler
|
// Optional DMA handler
|
||||||
dma_handler: Option<Arc<dyn ExternalDmaMapping>>,
|
dma_handler: Option<Arc<dyn ExternalDmaMapping>>,
|
||||||
|
|
||||||
// Pending activations
|
|
||||||
pending_activations: Arc<Mutex<Vec<VirtioPciDeviceActivator>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtioPciDevice {
|
impl VirtioPciDevice {
|
||||||
@ -390,7 +359,6 @@ impl VirtioPciDevice {
|
|||||||
activate_evt: EventFd,
|
activate_evt: EventFd,
|
||||||
use_64bit_bar: bool,
|
use_64bit_bar: bool,
|
||||||
dma_handler: Option<Arc<dyn ExternalDmaMapping>>,
|
dma_handler: Option<Arc<dyn ExternalDmaMapping>>,
|
||||||
pending_activations: Arc<Mutex<Vec<VirtioPciDeviceActivator>>>,
|
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let device_clone = device.clone();
|
let device_clone = device.clone();
|
||||||
let mut locked_device = device_clone.lock().unwrap();
|
let mut locked_device = device_clone.lock().unwrap();
|
||||||
@ -490,8 +458,8 @@ impl VirtioPciDevice {
|
|||||||
cap_pci_cfg_info: VirtioPciCfgCapInfo::default(),
|
cap_pci_cfg_info: VirtioPciCfgCapInfo::default(),
|
||||||
bar_regions: vec![],
|
bar_regions: vec![],
|
||||||
activate_evt,
|
activate_evt,
|
||||||
|
activate_barrier: Arc::new(Barrier::new(2)),
|
||||||
dma_handler,
|
dma_handler,
|
||||||
pending_activations,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(msix_config) = &virtio_pci_device.msix_config {
|
if let Some(msix_config) = &virtio_pci_device.msix_config {
|
||||||
@ -698,37 +666,37 @@ impl VirtioPciDevice {
|
|||||||
self.device.clone()
|
self.device.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_activator(&mut self, barrier: Option<Arc<Barrier>>) -> VirtioPciDeviceActivator {
|
fn activate(&mut self) -> ActivateResult {
|
||||||
let mut queue_evts = Vec::new();
|
if let Some(virtio_interrupt) = self.virtio_interrupt.take() {
|
||||||
let mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>> =
|
if self.memory.is_some() {
|
||||||
self.queues.iter().map(vm_virtio::clone_queue).collect();
|
let mem = self.memory.as_ref().unwrap().clone();
|
||||||
queues.retain(|q| q.state.ready);
|
let mut device = self.device.lock().unwrap();
|
||||||
for (i, queue) in queues.iter().enumerate() {
|
let mut queue_evts = Vec::new();
|
||||||
queue_evts.push(self.queue_evts[i].try_clone().unwrap());
|
let mut queues: Vec<Queue<GuestMemoryAtomic<GuestMemoryMmap>>> =
|
||||||
if !queue.is_valid() {
|
self.queues.iter().map(vm_virtio::clone_queue).collect();
|
||||||
error!("Queue {} is not valid", i);
|
queues.retain(|q| q.state.ready);
|
||||||
|
for (i, queue) in queues.iter().enumerate() {
|
||||||
|
queue_evts.push(self.queue_evts[i].try_clone().unwrap());
|
||||||
|
if !queue.is_valid() {
|
||||||
|
error!("Queue {} is not valid", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return device.activate(mem, virtio_interrupt, queues, queue_evts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
VirtioPciDeviceActivator {
|
|
||||||
interrupt: self.virtio_interrupt.take(),
|
|
||||||
memory: self.memory.clone(),
|
|
||||||
device: self.device.clone(),
|
|
||||||
queues: Some(queues),
|
|
||||||
device_activated: self.device_activated.clone(),
|
|
||||||
queue_evts: Some(
|
|
||||||
queue_evts
|
|
||||||
.iter()
|
|
||||||
.map(|fd| fd.try_clone().unwrap())
|
|
||||||
.collect(),
|
|
||||||
),
|
|
||||||
barrier,
|
|
||||||
id: self.id.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn activate(&mut self) -> ActivateResult {
|
pub fn maybe_activate(&mut self) {
|
||||||
self.prepare_activator(None).activate()
|
if self.needs_activation() {
|
||||||
|
self.activate().expect("Failed to activate device");
|
||||||
|
self.device_activated.store(true, Ordering::SeqCst);
|
||||||
|
info!("{}: Waiting for barrier", self.id);
|
||||||
|
self.activate_barrier.wait();
|
||||||
|
info!("{}: Barrier released", self.id);
|
||||||
|
} else {
|
||||||
|
info!("{}: Device does not need activation", self.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn needs_activation(&self) -> bool {
|
fn needs_activation(&self) -> bool {
|
||||||
@ -1090,16 +1058,13 @@ impl PciDevice for VirtioPciDevice {
|
|||||||
|
|
||||||
// Try and activate the device if the driver status has changed
|
// Try and activate the device if the driver status has changed
|
||||||
if self.needs_activation() {
|
if self.needs_activation() {
|
||||||
let barrier = Arc::new(Barrier::new(2));
|
|
||||||
let activator = self.prepare_activator(Some(barrier.clone()));
|
|
||||||
self.pending_activations.lock().unwrap().push(activator);
|
|
||||||
info!(
|
info!(
|
||||||
"{}: Needs activation; writing to activate event fd",
|
"{}: Needs activation; writing to activate event fd",
|
||||||
self.id
|
self.id
|
||||||
);
|
);
|
||||||
self.activate_evt.write(1).ok();
|
self.activate_evt.write(1).ok();
|
||||||
info!("{}: Needs activation; returning barrier", self.id);
|
info!("{}: Needs activation; returning barrier", self.id);
|
||||||
return Some(barrier);
|
return Some(self.activate_barrier.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device has been reset by the driver
|
// Device has been reset by the driver
|
||||||
|
@ -79,12 +79,10 @@ use std::result;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use vfio_ioctls::{VfioContainer, VfioDevice};
|
use vfio_ioctls::{VfioContainer, VfioDevice};
|
||||||
|
use virtio_devices::transport::VirtioPciDevice;
|
||||||
use virtio_devices::transport::VirtioTransport;
|
use virtio_devices::transport::VirtioTransport;
|
||||||
use virtio_devices::transport::{VirtioPciDevice, VirtioPciDeviceActivator};
|
|
||||||
use virtio_devices::vhost_user::VhostUserConfig;
|
use virtio_devices::vhost_user::VhostUserConfig;
|
||||||
use virtio_devices::{
|
use virtio_devices::{AccessPlatformMapping, VdpaDmaMapping, VirtioMemMappingSource};
|
||||||
AccessPlatformMapping, ActivateError, VdpaDmaMapping, VirtioMemMappingSource,
|
|
||||||
};
|
|
||||||
use virtio_devices::{Endpoint, IommuMapping};
|
use virtio_devices::{Endpoint, IommuMapping};
|
||||||
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
|
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
|
||||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||||
@ -478,9 +476,6 @@ pub enum DeviceManagerError {
|
|||||||
|
|
||||||
/// Invalid identifier
|
/// Invalid identifier
|
||||||
InvalidIdentifier(String),
|
InvalidIdentifier(String),
|
||||||
|
|
||||||
/// Error activating virtio device
|
|
||||||
VirtioActivate(ActivateError),
|
|
||||||
}
|
}
|
||||||
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
||||||
|
|
||||||
@ -944,9 +939,6 @@ pub struct DeviceManager {
|
|||||||
|
|
||||||
// Start time of the VM
|
// Start time of the VM
|
||||||
timestamp: Instant,
|
timestamp: Instant,
|
||||||
|
|
||||||
// Pending activations
|
|
||||||
pending_activations: Arc<Mutex<Vec<VirtioPciDeviceActivator>>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeviceManager {
|
impl DeviceManager {
|
||||||
@ -1088,7 +1080,6 @@ impl DeviceManager {
|
|||||||
io_uring_supported: None,
|
io_uring_supported: None,
|
||||||
boot_id_list,
|
boot_id_list,
|
||||||
timestamp,
|
timestamp,
|
||||||
pending_activations: Arc::new(Mutex::new(Vec::default())),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let device_manager = Arc::new(Mutex::new(device_manager));
|
let device_manager = Arc::new(Mutex::new(device_manager));
|
||||||
@ -3529,7 +3520,6 @@ impl DeviceManager {
|
|||||||
// The exception being if not on the default PCI segment.
|
// The exception being if not on the default PCI segment.
|
||||||
pci_segment_id > 0 || device_type != VirtioDeviceType::Block as u32,
|
pci_segment_id > 0 || device_type != VirtioDeviceType::Block as u32,
|
||||||
dma_handler,
|
dma_handler,
|
||||||
self.pending_activations.clone(),
|
|
||||||
)
|
)
|
||||||
.map_err(DeviceManagerError::VirtioDevice)?,
|
.map_err(DeviceManagerError::VirtioDevice)?,
|
||||||
));
|
));
|
||||||
@ -3684,10 +3674,17 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_virtio_devices(&self) -> DeviceManagerResult<()> {
|
pub fn activate_virtio_devices(&self) -> DeviceManagerResult<()> {
|
||||||
for mut activator in self.pending_activations.lock().unwrap().drain(..) {
|
// Find virtio pci devices and activate any pending ones
|
||||||
activator
|
let device_tree = self.device_tree.lock().unwrap();
|
||||||
.activate()
|
for pci_device_node in device_tree.pci_devices() {
|
||||||
.map_err(DeviceManagerError::VirtioActivate)?;
|
#[allow(irrefutable_let_patterns)]
|
||||||
|
if let PciDeviceHandle::Virtio(virtio_pci_device) = &pci_device_node
|
||||||
|
.pci_device_handle
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(DeviceManagerError::MissingPciDevice)?
|
||||||
|
{
|
||||||
|
virtio_pci_device.lock().unwrap().maybe_activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user