mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
The PciDevice trait is supposed to describe only functions related to PCI. The specific method ioeventfds() has nothing to do with PCI, but instead would be more specific to virtio transport devices. This commit removes the ioeventfds() method from the PciDevice trait, adding some convenient helper as_any() to retrieve the Any trait from the structure behing the PciDevice trait. This is the only way to keep calling into ioeventfds() function from VirtioPciDevice, so that we can still properly reprogram the PCI BAR. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
127 lines
4.4 KiB
Rust
Executable File
127 lines
4.4 KiB
Rust
Executable File
// 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.
|
|
|
|
use crate::configuration::{self, PciBarRegionType};
|
|
use crate::msix::MsixTableEntry;
|
|
use crate::PciInterruptPin;
|
|
use devices::BusDevice;
|
|
use std::any::Any;
|
|
use std::fmt::{self, Display};
|
|
use std::sync::Arc;
|
|
use std::{self, io, result};
|
|
use vm_allocator::SystemAllocator;
|
|
use vm_memory::{GuestAddress, GuestUsize};
|
|
|
|
pub struct InterruptParameters<'a> {
|
|
pub msix: Option<&'a MsixTableEntry>,
|
|
}
|
|
|
|
pub type InterruptDelivery =
|
|
Box<dyn Fn(InterruptParameters) -> result::Result<(), io::Error> + Send + Sync>;
|
|
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
/// Setup of the device capabilities failed.
|
|
CapabilitiesSetup(configuration::Error),
|
|
/// Allocating space for an IO BAR failed.
|
|
IoAllocationFailed(u64),
|
|
/// Registering an IO BAR failed.
|
|
IoRegistrationFailed(u64, configuration::Error),
|
|
}
|
|
pub type Result<T> = std::result::Result<T, Error>;
|
|
|
|
impl Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
use self::Error::*;
|
|
|
|
match self {
|
|
CapabilitiesSetup(e) => write!(f, "failed to add capability {}", e),
|
|
IoAllocationFailed(size) => {
|
|
write!(f, "failed to allocate space for an IO BAR, size={}", size)
|
|
}
|
|
IoRegistrationFailed(addr, e) => {
|
|
write!(f, "failed to register an IO BAR, addr={} err={}", addr, e)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct BarReprogrammingParams {
|
|
pub old_base: u64,
|
|
pub new_base: u64,
|
|
pub len: u64,
|
|
pub region_type: PciBarRegionType,
|
|
}
|
|
|
|
pub trait PciDevice: BusDevice {
|
|
/// Assign a legacy PCI IRQ to this device.
|
|
/// The device may write to `irq_evt` to trigger an interrupt.
|
|
fn assign_pin_irq(
|
|
&mut self,
|
|
_irq_cb: Arc<InterruptDelivery>,
|
|
_irq_num: u32,
|
|
_irq_pin: PciInterruptPin,
|
|
) {
|
|
}
|
|
|
|
/// Assign MSI-X to this device.
|
|
fn assign_msix(&mut self, _msi_cb: Arc<InterruptDelivery>) {}
|
|
|
|
/// Allocates the needed PCI BARs space using the `allocate` function which takes a size and
|
|
/// returns an address. Returns a Vec of (GuestAddress, GuestUsize) tuples.
|
|
fn allocate_bars(
|
|
&mut self,
|
|
_allocator: &mut SystemAllocator,
|
|
) -> Result<Vec<(GuestAddress, GuestUsize, PciBarRegionType)>> {
|
|
Ok(Vec::new())
|
|
}
|
|
|
|
/// Sets a register in the configuration space.
|
|
/// * `reg_idx` - The index of the config register to modify.
|
|
/// * `offset` - Offset in to the register.
|
|
fn write_config_register(&mut self, reg_idx: usize, offset: u64, data: &[u8]);
|
|
/// Gets a register from the configuration space.
|
|
/// * `reg_idx` - The index of the config register to read.
|
|
fn read_config_register(&self, reg_idx: usize) -> u32;
|
|
/// Detects if a BAR is being reprogrammed.
|
|
fn detect_bar_reprogramming(
|
|
&mut self,
|
|
_reg_idx: usize,
|
|
_data: &[u8],
|
|
) -> Option<BarReprogrammingParams> {
|
|
None
|
|
}
|
|
/// Reads from a BAR region mapped in to the device.
|
|
/// * `addr` - The guest address inside the BAR.
|
|
/// * `data` - Filled with the data from `addr`.
|
|
fn read_bar(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {}
|
|
/// Writes to a BAR region mapped in to the device.
|
|
/// * `addr` - The guest address inside the BAR.
|
|
/// * `data` - The data to write.
|
|
fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) {}
|
|
/// Relocates the BAR to a different address in guest address space.
|
|
fn move_bar(&mut self, _old_base: u64, _new_base: u64) -> result::Result<(), io::Error> {
|
|
Ok(())
|
|
}
|
|
/// Provides a mutable reference to the Any trait. This is useful to let
|
|
/// the caller have access to the underlying type behind the trait.
|
|
fn as_any(&mut self) -> &mut dyn Any;
|
|
}
|
|
|
|
/// This trait defines a set of functions which can be triggered whenever a
|
|
/// PCI device is modified in any way.
|
|
pub trait DeviceRelocation: Send + Sync {
|
|
/// The BAR needs to be moved to a different location in the guest address
|
|
/// space. This follows a decision from the software running in the guest.
|
|
fn move_bar(
|
|
&self,
|
|
old_base: u64,
|
|
new_base: u64,
|
|
len: u64,
|
|
pci_dev: &mut dyn PciDevice,
|
|
region_type: PciBarRegionType,
|
|
) -> result::Result<(), io::Error>;
|
|
}
|