devices: pci: add ioeventfds to PciDevice trait

VirtioDevices and potentially others need to register ioeventfds that
will be triggered when guests write to certain addresses. Allow
PciDevices to return an array of ioeventfds that the VM can install.

Change-Id: I2524c4e8c04f75a8d7868cac998304aecbb29c40
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1237360
Commit-Ready: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Dylan Reid 2018-07-09 13:35:40 -07:00 committed by chrome-bot
parent c5a6762081
commit aa12c74bff
4 changed files with 26 additions and 5 deletions

View file

@ -209,7 +209,8 @@ impl arch::LinuxArch for AArch64 {
let (pci, pci_irqs) = arch::generate_pci_root(components.pci_devices,
&mut mmio_bus,
&mut resources)
&mut resources,
&mut vm)
.map_err(Error::CreatePciRoot)?;
let exit_evt = EventFd::new().map_err(Error::CreateEventFd)?;

View file

@ -20,7 +20,7 @@ use devices::{Bus, BusError, PciDevice, PciDeviceError, PciInterruptPin,
PciRoot, ProxyDevice, Serial};
use devices::virtio::VirtioDevice;
use io_jail::Minijail;
use kvm::{IoeventAddress, Kvm, Vm, Vcpu};
use kvm::{IoeventAddress, Kvm, NoDatamatch, Vm, Vcpu};
use sys_util::{EventFd, GuestMemory, syslog};
use resources::SystemAllocator;
@ -136,7 +136,8 @@ impl fmt::Display for DeviceRegistrationError {
/// Creates a root PCI device for use by this Vm.
pub fn generate_pci_root(devices: Vec<(Box<PciDevice + 'static>, Minijail)>,
mmio_bus: &mut Bus,
resources: &mut SystemAllocator)
resources: &mut SystemAllocator,
vm: &mut Vm)
-> std::result::Result<(PciRoot, Vec<(u32, PciInterruptPin)>), DeviceRegistrationError>
{
let mut root = PciRoot::new();
@ -146,7 +147,9 @@ pub fn generate_pci_root(devices: Vec<(Box<PciDevice + 'static>, Minijail)>,
syslog::push_fds(&mut keep_fds);
let irqfd = EventFd::new().map_err(DeviceRegistrationError::EventFdCreate)?;
let irq_num = resources.allocate_irq().ok_or(DeviceRegistrationError::AllocateIrq)? as u32;
let irq_num = resources
.allocate_irq()
.ok_or(DeviceRegistrationError::AllocateIrq)? as u32;
let pci_irq_pin = match dev_idx % 4 {
0 => PciInterruptPin::IntA,
1 => PciInterruptPin::IntB,
@ -160,6 +163,12 @@ pub fn generate_pci_root(devices: Vec<(Box<PciDevice + 'static>, Minijail)>,
let ranges = device
.allocate_io_bars(resources)
.map_err(DeviceRegistrationError::AllocateIoAddrs)?;
for (event, addr) in device.ioeventfds() {
let io_addr = IoeventAddress::Mmio(addr);
vm.register_ioevent(&event, io_addr, NoDatamatch)
.map_err(DeviceRegistrationError::RegisterIoevent)?;
keep_fds.push(event.as_raw_fd());
}
let proxy = ProxyDevice::new(device, &jail, keep_fds)
.map_err(DeviceRegistrationError::ProxyDeviceCreation)?;
let arced_dev = Arc::new(Mutex::new(proxy));

View file

@ -37,6 +37,11 @@ pub trait PciDevice: Send {
) -> Result<Vec<(u64, u64)>> {
Ok(Vec::new())
}
/// Gets a list of ioeventfds that should be registered with the running VM. The list is
/// returned as a Vec of (eventfd, addr) tuples.
fn ioeventfds(&self) -> Vec<(&EventFd, u64)> {
Vec::new()
}
/// Gets the configuration registers of the Pci Device.
fn config_registers(&self) -> &PciConfiguration; // TODO - remove these
/// Gets the configuration registers of the Pci Device for modification.
@ -98,6 +103,11 @@ impl<T: PciDevice + ?Sized> PciDevice for Box<T> {
) -> Result<Vec<(u64, u64)>> {
(**self).allocate_io_bars(resources)
}
/// Gets a list of ioeventfds that should be registered with the running VM. The list is
/// returned as a Vec of (eventfd, addr) tuples.
fn ioeventfds(&self) -> Vec<(&EventFd, u64)> {
(**self).ioeventfds()
}
/// Gets the configuration registers of the Pci Device.
fn config_registers(&self) -> &PciConfiguration {
(**self).config_registers()

View file

@ -277,7 +277,8 @@ impl arch::LinuxArch for X8664arch {
let (pci, pci_irqs) = arch::generate_pci_root(components.pci_devices,
&mut mmio_bus,
&mut resources)
&mut resources,
&mut vm)
.map_err(Error::CreatePciRoot)?;
let pci_bus = Arc::new(Mutex::new(pci));