mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
As per the VIRTIO specification, every virtio device configuration can be updated while the guest is running. The guest needs to be notified when this happens, and it can be done in two different ways, depending on the type of interrupt being used for those devices. In case the device uses INTx, the allocated IRQ pin is shared between queues and configuration updates. The way for the guest to differentiate between an interrupt meant for a virtqueue or meant for a configuration update is tied to the value of the ISR status field. This field is a simple 32 bits bitmask where only bit 0 and 1 can be changed, the rest is reserved. In case the device uses MSI/MSI-X, the driver should allocate a dedicated vector for configuration updates. This case is much simpler as it only requires the device to send the appropriate MSI vector. The cloud-hypervisor codebase was not supporting the update of a virtio device configuration. This patch extends the existing VirtioInterrupt closure to accept a type that can be Config or Queue, so that based on this type, the closure implementation can make the right choice about which interrupt pin or vector to trigger. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
80 lines
2.6 KiB
Rust
80 lines
2.6 KiB
Rust
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE-BSD-3-Clause file.
|
|
//
|
|
// Copyright © 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
|
|
|
use super::*;
|
|
use pci::{PciBarConfiguration, PciCapability};
|
|
use std::sync::Arc;
|
|
use vm_memory::GuestMemoryMmap;
|
|
use vmm_sys_util::EventFd;
|
|
|
|
pub enum VirtioInterruptType {
|
|
Config,
|
|
Queue,
|
|
}
|
|
|
|
pub type VirtioInterrupt = Box<
|
|
Fn(&VirtioInterruptType, Option<&Queue>) -> std::result::Result<(), std::io::Error>
|
|
+ Send
|
|
+ Sync,
|
|
>;
|
|
|
|
/// Trait for virtio devices to be driven by a virtio transport.
|
|
///
|
|
/// The lifecycle of a virtio device is to be moved to a virtio transport, which will then query the
|
|
/// device. Once the guest driver has configured the device, `VirtioDevice::activate` will be called
|
|
/// and all the events, memory, and queues for device operation will be moved into the device.
|
|
/// Optionally, a virtio device can implement device reset in which it returns said resources and
|
|
/// resets its internal.
|
|
pub trait VirtioDevice: Send {
|
|
/// The virtio device type.
|
|
fn device_type(&self) -> u32;
|
|
|
|
/// The maximum size of each queue that this device supports.
|
|
fn queue_max_sizes(&self) -> &[u16];
|
|
|
|
/// The set of feature bits shifted by `page * 32`.
|
|
fn features(&self, page: u32) -> u32 {
|
|
let _ = page;
|
|
0
|
|
}
|
|
|
|
/// Acknowledges that this set of features should be enabled.
|
|
fn ack_features(&mut self, page: u32, value: u32);
|
|
|
|
/// Reads this device configuration space at `offset`.
|
|
fn read_config(&self, offset: u64, data: &mut [u8]);
|
|
|
|
/// Writes to this device configuration space at `offset`.
|
|
fn write_config(&mut self, offset: u64, data: &[u8]);
|
|
|
|
/// Activates this device for real usage.
|
|
fn activate(
|
|
&mut self,
|
|
mem: GuestMemoryMmap,
|
|
interrupt_evt: Arc<VirtioInterrupt>,
|
|
queues: Vec<Queue>,
|
|
queue_evts: Vec<EventFd>,
|
|
) -> ActivateResult;
|
|
|
|
/// Optionally deactivates this device and returns ownership of the guest memory map, interrupt
|
|
/// event, and queue events.
|
|
fn reset(&mut self) -> Option<(Arc<VirtioInterrupt>, Vec<EventFd>)> {
|
|
None
|
|
}
|
|
|
|
/// Returns any additional BAR configuration required by the device.
|
|
fn get_device_bars(&self) -> Vec<PciBarConfiguration> {
|
|
Vec::new()
|
|
}
|
|
|
|
/// Returns any additional capabilities required by the device.
|
|
fn get_device_caps(&self) -> Vec<Box<dyn PciCapability>> {
|
|
Vec::new()
|
|
}
|
|
}
|