mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 17:35:19 +00:00
pci: Add error propagation to PCI BAR reprogramming
Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
3e819ac797
commit
d6c68e4738
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
||||||
use std::collections::btree_map::BTreeMap;
|
use std::collections::btree_map::BTreeMap;
|
||||||
use std::result;
|
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
use std::{convert, error, fmt, io, result};
|
||||||
|
|
||||||
/// Trait for devices that respond to reads or writes in an arbitrary address space.
|
/// Trait for devices that respond to reads or writes in an arbitrary address space.
|
||||||
///
|
///
|
||||||
@ -38,6 +38,20 @@ pub enum Error {
|
|||||||
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "bus_error: {:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {}
|
||||||
|
|
||||||
|
impl convert::From<Error> for io::Error {
|
||||||
|
fn from(e: Error) -> Self {
|
||||||
|
io::Error::new(io::ErrorKind::Other, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Holds a base and length representing the address space occupied by a `BusDevice`.
|
/// Holds a base and length representing the address space occupied by a `BusDevice`.
|
||||||
///
|
///
|
||||||
/// * base - The address at which the range start.
|
/// * base - The address at which the range start.
|
||||||
|
@ -197,13 +197,15 @@ impl PciConfigIo {
|
|||||||
|
|
||||||
// Reprogram the BAR if needed
|
// Reprogram the BAR if needed
|
||||||
if let Some(params) = bar_reprog_params {
|
if let Some(params) = bar_reprog_params {
|
||||||
pci_bus.device_reloc.upgrade().unwrap().move_bar(
|
if let Err(e) = pci_bus.device_reloc.upgrade().unwrap().move_bar(
|
||||||
params.old_base,
|
params.old_base,
|
||||||
params.new_base,
|
params.new_base,
|
||||||
params.len,
|
params.len,
|
||||||
device.deref_mut(),
|
device.deref_mut(),
|
||||||
params.region_type,
|
params.region_type,
|
||||||
);
|
) {
|
||||||
|
error!("Failed moving device BAR: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,13 +315,15 @@ impl PciConfigMmio {
|
|||||||
|
|
||||||
// Reprogram the BAR if needed
|
// Reprogram the BAR if needed
|
||||||
if let Some(params) = bar_reprog_params {
|
if let Some(params) = bar_reprog_params {
|
||||||
pci_bus.device_reloc.upgrade().unwrap().move_bar(
|
if let Err(e) = pci_bus.device_reloc.upgrade().unwrap().move_bar(
|
||||||
params.old_base,
|
params.old_base,
|
||||||
params.new_base,
|
params.new_base,
|
||||||
params.len,
|
params.len,
|
||||||
device.deref_mut(),
|
device.deref_mut(),
|
||||||
params.region_type,
|
params.region_type,
|
||||||
);
|
) {
|
||||||
|
error!("Failed moving device BAR: {}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ use crate::configuration::{self, PciBarRegionType};
|
|||||||
use crate::msix::MsixTableEntry;
|
use crate::msix::MsixTableEntry;
|
||||||
use crate::PciInterruptPin;
|
use crate::PciInterruptPin;
|
||||||
use devices::BusDevice;
|
use devices::BusDevice;
|
||||||
use std;
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::{self, io, result};
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::SystemAllocator;
|
||||||
use vm_memory::{GuestAddress, GuestUsize};
|
use vm_memory::{GuestAddress, GuestUsize};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
@ -18,7 +18,7 @@ pub struct InterruptParameters<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type InterruptDelivery =
|
pub type InterruptDelivery =
|
||||||
Box<dyn Fn(InterruptParameters) -> std::result::Result<(), std::io::Error> + Send + Sync>;
|
Box<dyn Fn(InterruptParameters) -> result::Result<(), io::Error> + Send + Sync>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -107,7 +107,9 @@ pub trait PciDevice: BusDevice {
|
|||||||
/// * `data` - The data to write.
|
/// * `data` - The data to write.
|
||||||
fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) {}
|
fn write_bar(&mut self, _base: u64, _offset: u64, _data: &[u8]) {}
|
||||||
/// Relocates the BAR to a different address in guest address space.
|
/// Relocates the BAR to a different address in guest address space.
|
||||||
fn move_bar(&mut self, _old_base: u64, _new_base: u64) {}
|
fn move_bar(&mut self, _old_base: u64, _new_base: u64) -> result::Result<(), io::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait defines a set of functions which can be triggered whenever a
|
/// This trait defines a set of functions which can be triggered whenever a
|
||||||
@ -122,5 +124,5 @@ pub trait DeviceRelocation: Send + Sync {
|
|||||||
len: u64,
|
len: u64,
|
||||||
pci_dev: &mut dyn PciDevice,
|
pci_dev: &mut dyn PciDevice,
|
||||||
region_type: PciBarRegionType,
|
region_type: PciBarRegionType,
|
||||||
);
|
) -> result::Result<(), io::Error>;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use pci::{
|
|||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io, result};
|
||||||
use vfio_bindings::bindings::vfio::*;
|
use vfio_bindings::bindings::vfio::*;
|
||||||
use vm_allocator::SystemAllocator;
|
use vm_allocator::SystemAllocator;
|
||||||
use vm_memory::{Address, GuestAddress, GuestUsize};
|
use vm_memory::{Address, GuestAddress, GuestUsize};
|
||||||
@ -1004,7 +1004,7 @@ impl PciDevice for VfioPciDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_bar(&mut self, old_base: u64, new_base: u64) {
|
fn move_bar(&mut self, old_base: u64, new_base: u64) -> result::Result<(), io::Error> {
|
||||||
for region in self.mmio_regions.iter_mut() {
|
for region in self.mmio_regions.iter_mut() {
|
||||||
if region.start.raw_value() == old_base {
|
if region.start.raw_value() == old_base {
|
||||||
region.start = GuestAddress(new_base);
|
region.start = GuestAddress(new_base);
|
||||||
@ -1023,7 +1023,7 @@ impl PciDevice for VfioPciDevice {
|
|||||||
};
|
};
|
||||||
// Safe because the guest regions are guaranteed not to overlap.
|
// Safe because the guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.vm_fd.set_user_memory_region(old_mem_region).unwrap();
|
self.vm_fd.set_user_memory_region(old_mem_region)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert new region to KVM
|
// Insert new region to KVM
|
||||||
@ -1036,11 +1036,13 @@ impl PciDevice for VfioPciDevice {
|
|||||||
};
|
};
|
||||||
// Safe because the guest regions are guaranteed not to overlap.
|
// Safe because the guest regions are guaranteed not to overlap.
|
||||||
unsafe {
|
unsafe {
|
||||||
self.vm_fd.set_user_memory_region(new_mem_region).unwrap();
|
self.vm_fd.set_user_memory_region(new_mem_region)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ impl DeviceRelocation for AddressManager {
|
|||||||
len: u64,
|
len: u64,
|
||||||
pci_dev: &mut dyn PciDevice,
|
pci_dev: &mut dyn PciDevice,
|
||||||
region_type: PciBarRegionType,
|
region_type: PciBarRegionType,
|
||||||
) {
|
) -> std::result::Result<(), std::io::Error> {
|
||||||
match region_type {
|
match region_type {
|
||||||
PciBarRegionType::IORegion => {
|
PciBarRegionType::IORegion => {
|
||||||
// Update system allocator
|
// Update system allocator
|
||||||
@ -296,16 +296,19 @@ impl DeviceRelocation for AddressManager {
|
|||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.free_io_addresses(GuestAddress(old_base), len as GuestUsize);
|
.free_io_addresses(GuestAddress(old_base), len as GuestUsize);
|
||||||
|
|
||||||
self.allocator
|
self.allocator
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None)
|
.allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None)
|
||||||
.unwrap();
|
.ok_or_else(|| {
|
||||||
|
io::Error::new(io::ErrorKind::Other, "failed allocating new IO range")
|
||||||
|
})?;
|
||||||
|
|
||||||
// Update PIO bus
|
// Update PIO bus
|
||||||
self.io_bus
|
self.io_bus
|
||||||
.update_range(old_base, len, new_base, len)
|
.update_range(old_base, len, new_base, len)
|
||||||
.unwrap();
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
}
|
}
|
||||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
|
PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => {
|
||||||
// Update system allocator
|
// Update system allocator
|
||||||
@ -323,7 +326,12 @@ impl DeviceRelocation for AddressManager {
|
|||||||
len as GuestUsize,
|
len as GuestUsize,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.ok_or_else(|| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"failed allocating new 32 bits MMIO range",
|
||||||
|
)
|
||||||
|
})?;
|
||||||
} else {
|
} else {
|
||||||
self.allocator
|
self.allocator
|
||||||
.lock()
|
.lock()
|
||||||
@ -333,24 +341,28 @@ impl DeviceRelocation for AddressManager {
|
|||||||
len as GuestUsize,
|
len as GuestUsize,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.ok_or_else(|| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"failed allocating new 64 bits MMIO range",
|
||||||
|
)
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update MMIO bus
|
// Update MMIO bus
|
||||||
self.mmio_bus
|
self.mmio_bus
|
||||||
.update_range(old_base, len, new_base, len)
|
.update_range(old_base, len, new_base, len)
|
||||||
.unwrap();
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (event, addr, _) in pci_dev.ioeventfds() {
|
for (event, addr, _) in pci_dev.ioeventfds() {
|
||||||
let io_addr = IoEventAddress::Mmio(addr);
|
let io_addr = IoEventAddress::Mmio(addr);
|
||||||
self.vm_fd
|
self.vm_fd
|
||||||
.register_ioevent(event.as_raw_fd(), &io_addr, NoDatamatch)
|
.register_ioevent(event.as_raw_fd(), &io_addr, NoDatamatch)?;
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_dev.move_bar(old_base, new_base);
|
pci_dev.move_bar(old_base, new_base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user