mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
pci, vmm: Extend PciDevice trait to support BAR relocation
By adding a new method id() to the PciDevice trait, we allow the caller to retrieve a unique identifier. This is used in the context of BAR relocation to identify the device being relocated, so that we can update the DeviceTree resources for all PCI devices (and not only VirtioPciDevice). Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
6175cc0977
commit
5264d545dd
@ -88,6 +88,10 @@ impl PciDevice for PciRoot {
|
|||||||
fn as_any(&mut self) -> &mut dyn Any {
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PciBus {
|
pub struct PciBus {
|
||||||
|
@ -110,6 +110,9 @@ pub trait PciDevice: BusDevice {
|
|||||||
/// Provides a mutable reference to the Any trait. This is useful to let
|
/// Provides a mutable reference to the Any trait. This is useful to let
|
||||||
/// the caller have access to the underlying type behind the trait.
|
/// the caller have access to the underlying type behind the trait.
|
||||||
fn as_any(&mut self) -> &mut dyn Any;
|
fn as_any(&mut self) -> &mut dyn Any;
|
||||||
|
|
||||||
|
/// Optionally returns a unique identifier.
|
||||||
|
fn id(&self) -> Option<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
|
@ -976,6 +976,7 @@ impl VfioCommon {
|
|||||||
/// The VMM creates a VfioDevice, then assigns it to a VfioPciDevice,
|
/// The VMM creates a VfioDevice, then assigns it to a VfioPciDevice,
|
||||||
/// which then gets added to the PCI bus.
|
/// which then gets added to the PCI bus.
|
||||||
pub struct VfioPciDevice {
|
pub struct VfioPciDevice {
|
||||||
|
id: String,
|
||||||
vm: Arc<dyn hypervisor::Vm>,
|
vm: Arc<dyn hypervisor::Vm>,
|
||||||
device: Arc<VfioDevice>,
|
device: Arc<VfioDevice>,
|
||||||
container: Arc<VfioContainer>,
|
container: Arc<VfioContainer>,
|
||||||
@ -986,7 +987,9 @@ pub struct VfioPciDevice {
|
|||||||
|
|
||||||
impl VfioPciDevice {
|
impl VfioPciDevice {
|
||||||
/// Constructs a new Vfio Pci device for the given Vfio device
|
/// Constructs a new Vfio Pci device for the given Vfio device
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String,
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
device: VfioDevice,
|
device: VfioDevice,
|
||||||
container: Arc<VfioContainer>,
|
container: Arc<VfioContainer>,
|
||||||
@ -1027,6 +1030,7 @@ impl VfioPciDevice {
|
|||||||
common.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)?;
|
common.initialize_legacy_interrupt(legacy_interrupt_group, &vfio_wrapper)?;
|
||||||
|
|
||||||
let vfio_pci_device = VfioPciDevice {
|
let vfio_pci_device = VfioPciDevice {
|
||||||
|
id,
|
||||||
vm: vm.clone(),
|
vm: vm.clone(),
|
||||||
device,
|
device,
|
||||||
container,
|
container,
|
||||||
@ -1438,4 +1442,8 @@ impl PciDevice for VfioPciDevice {
|
|||||||
fn as_any(&mut self) -> &mut dyn Any {
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ use vm_memory::{
|
|||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
pub struct VfioUserPciDevice {
|
pub struct VfioUserPciDevice {
|
||||||
|
id: String,
|
||||||
vm: Arc<dyn hypervisor::Vm>,
|
vm: Arc<dyn hypervisor::Vm>,
|
||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
vfio_wrapper: VfioUserClientWrapper,
|
vfio_wrapper: VfioUserClientWrapper,
|
||||||
@ -63,6 +64,7 @@ impl PciSubclass for PciVfioUserSubclass {
|
|||||||
|
|
||||||
impl VfioUserPciDevice {
|
impl VfioUserPciDevice {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: String,
|
||||||
vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
msi_interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
@ -111,6 +113,7 @@ impl VfioUserPciDevice {
|
|||||||
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
.map_err(VfioUserPciDeviceError::InitializeLegacyInterrupts)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
id,
|
||||||
vm: vm.clone(),
|
vm: vm.clone(),
|
||||||
client,
|
client,
|
||||||
vfio_wrapper,
|
vfio_wrapper,
|
||||||
@ -486,6 +489,10 @@ impl PciDevice for VfioUserPciDevice {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VfioUserPciDevice {
|
impl Drop for VfioUserPciDevice {
|
||||||
|
@ -1089,6 +1089,10 @@ impl PciDevice for VirtioPciDevice {
|
|||||||
fn as_any(&mut self) -> &mut dyn Any {
|
fn as_any(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> Option<String> {
|
||||||
|
Some(self.id.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BusDevice for VirtioPciDevice {
|
impl BusDevice for VirtioPciDevice {
|
||||||
|
@ -660,22 +660,30 @@ impl DeviceRelocation for AddressManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let any_dev = pci_dev.as_any();
|
// Update the device_tree resources associated with the device
|
||||||
if let Some(virtio_pci_dev) = any_dev.downcast_ref::<VirtioPciDevice>() {
|
if let Some(id) = pci_dev.id() {
|
||||||
// Update the device_tree resources associated with the device
|
if let Some(node) = self.device_tree.lock().unwrap().get_mut(&id) {
|
||||||
if let Some(node) = self
|
|
||||||
.device_tree
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&virtio_pci_dev.id())
|
|
||||||
{
|
|
||||||
let mut resource_updated = false;
|
let mut resource_updated = false;
|
||||||
for resource in node.resources.iter_mut() {
|
for resource in node.resources.iter_mut() {
|
||||||
if let Resource::MmioAddressRange { base, .. } = resource {
|
match region_type {
|
||||||
if *base == old_base {
|
PciBarRegionType::IoRegion => {
|
||||||
*base = new_base;
|
if let Resource::PioAddressRange { base, .. } = resource {
|
||||||
resource_updated = true;
|
if *base as u64 == old_base {
|
||||||
break;
|
*base = new_base as u16;
|
||||||
|
resource_updated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PciBarRegionType::Memory32BitRegion
|
||||||
|
| PciBarRegionType::Memory64BitRegion => {
|
||||||
|
if let Resource::MmioAddressRange { base, .. } = resource {
|
||||||
|
if *base == old_base {
|
||||||
|
*base = new_base;
|
||||||
|
resource_updated = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -685,21 +693,20 @@ impl DeviceRelocation for AddressManager {
|
|||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!(
|
format!(
|
||||||
"Couldn't find a resource with base 0x{:x} for device {}",
|
"Couldn't find a resource with base 0x{:x} for device {}",
|
||||||
old_base,
|
old_base, id
|
||||||
virtio_pci_dev.id()
|
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!(
|
format!("Couldn't find device {} from device tree", id),
|
||||||
"Couldn't find device {} from device tree",
|
|
||||||
virtio_pci_dev.id()
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let any_dev = pci_dev.as_any();
|
||||||
|
if let Some(virtio_pci_dev) = any_dev.downcast_ref::<VirtioPciDevice>() {
|
||||||
let bar_addr = virtio_pci_dev.config_bar_addr();
|
let bar_addr = virtio_pci_dev.config_bar_addr();
|
||||||
if bar_addr == new_base {
|
if bar_addr == new_base {
|
||||||
for (event, addr) in virtio_pci_dev.ioeventfds(old_base) {
|
for (event, addr) in virtio_pci_dev.ioeventfds(old_base) {
|
||||||
@ -3184,6 +3191,7 @@ impl DeviceManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let vfio_pci_device = VfioPciDevice::new(
|
let vfio_pci_device = VfioPciDevice::new(
|
||||||
|
vfio_name.clone(),
|
||||||
&self.address_manager.vm,
|
&self.address_manager.vm,
|
||||||
vfio_device,
|
vfio_device,
|
||||||
vfio_container,
|
vfio_container,
|
||||||
@ -3354,6 +3362,7 @@ impl DeviceManager {
|
|||||||
));
|
));
|
||||||
|
|
||||||
let mut vfio_user_pci_device = VfioUserPciDevice::new(
|
let mut vfio_user_pci_device = VfioUserPciDevice::new(
|
||||||
|
vfio_user_name.clone(),
|
||||||
&self.address_manager.vm,
|
&self.address_manager.vm,
|
||||||
client.clone(),
|
client.clone(),
|
||||||
&self.msi_interrupt_manager,
|
&self.msi_interrupt_manager,
|
||||||
|
Loading…
Reference in New Issue
Block a user