mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
pci: Enable GSI routing (MSI type) for AArch64
In this commit we saved the BDF of a PCI device and set it to "devid" in GSI routing entry, because this field is mandatory for GICv3-ITS. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
committed by
Rob Bradford
parent
82a0e29c7a
commit
cce6237536
@@ -344,6 +344,7 @@ impl Ioapic {
|
|||||||
high_addr: 0x0,
|
high_addr: 0x0,
|
||||||
low_addr,
|
low_addr,
|
||||||
data,
|
data,
|
||||||
|
devid: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub mod aarch64;
|
|||||||
pub use kvm_bindings;
|
pub use kvm_bindings;
|
||||||
pub use kvm_bindings::{
|
pub use kvm_bindings::{
|
||||||
kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, kvm_irq_routing_entry,
|
kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_irq_routing, kvm_irq_routing_entry,
|
||||||
kvm_userspace_memory_region, KVM_IRQ_ROUTING_MSI, KVM_MEM_READONLY,
|
kvm_userspace_memory_region, KVM_IRQ_ROUTING_MSI, KVM_MEM_READONLY, KVM_MSI_VALID_DEVID,
|
||||||
};
|
};
|
||||||
pub use kvm_ioctls;
|
pub use kvm_ioctls;
|
||||||
pub use kvm_ioctls::{Cap, Kvm};
|
pub use kvm_ioctls::{Cap, Kvm};
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ impl MsiConfig {
|
|||||||
high_addr: self.cap.msg_addr_hi,
|
high_addr: self.cap.msg_addr_hi,
|
||||||
low_addr: self.cap.msg_addr_lo,
|
low_addr: self.cap.msg_addr_lo,
|
||||||
data: self.cap.msg_data as u32,
|
data: self.cap.msg_data as u32,
|
||||||
|
devid: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct MsixConfigState {
|
|||||||
pub struct MsixConfig {
|
pub struct MsixConfig {
|
||||||
pub table_entries: Vec<MsixTableEntry>,
|
pub table_entries: Vec<MsixTableEntry>,
|
||||||
pub pba_entries: Vec<u64>,
|
pub pba_entries: Vec<u64>,
|
||||||
|
pub devid: u32,
|
||||||
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
masked: bool,
|
masked: bool,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
@@ -81,6 +82,7 @@ impl MsixConfig {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
msix_vectors: u16,
|
msix_vectors: u16,
|
||||||
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||||
|
devid: u32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
assert!(msix_vectors <= MAX_MSIX_VECTORS_PER_DEVICE);
|
assert!(msix_vectors <= MAX_MSIX_VECTORS_PER_DEVICE);
|
||||||
|
|
||||||
@@ -93,6 +95,7 @@ impl MsixConfig {
|
|||||||
MsixConfig {
|
MsixConfig {
|
||||||
table_entries,
|
table_entries,
|
||||||
pba_entries,
|
pba_entries,
|
||||||
|
devid,
|
||||||
interrupt_source_group,
|
interrupt_source_group,
|
||||||
masked: false,
|
masked: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@@ -124,6 +127,7 @@ impl MsixConfig {
|
|||||||
high_addr: table_entry.msg_addr_hi,
|
high_addr: table_entry.msg_addr_hi,
|
||||||
low_addr: table_entry.msg_addr_lo,
|
low_addr: table_entry.msg_addr_lo,
|
||||||
data: table_entry.msg_data,
|
data: table_entry.msg_data,
|
||||||
|
devid: self.devid,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.interrupt_source_group
|
self.interrupt_source_group
|
||||||
@@ -162,6 +166,7 @@ impl MsixConfig {
|
|||||||
high_addr: table_entry.msg_addr_hi,
|
high_addr: table_entry.msg_addr_hi,
|
||||||
low_addr: table_entry.msg_addr_lo,
|
low_addr: table_entry.msg_addr_lo,
|
||||||
data: table_entry.msg_data,
|
data: table_entry.msg_data,
|
||||||
|
devid: self.devid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
@@ -306,6 +311,7 @@ impl MsixConfig {
|
|||||||
high_addr: table_entry.msg_addr_hi,
|
high_addr: table_entry.msg_addr_hi,
|
||||||
low_addr: table_entry.msg_addr_lo,
|
low_addr: table_entry.msg_addr_lo,
|
||||||
data: table_entry.msg_data,
|
data: table_entry.msg_data,
|
||||||
|
devid: self.devid,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = self.interrupt_source_group.update(
|
if let Err(e) = self.interrupt_source_group.update(
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ impl VfioPciDevice {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let msix_config = MsixConfig::new(msix_cap.table_size(), interrupt_source_group.clone());
|
let msix_config = MsixConfig::new(msix_cap.table_size(), interrupt_source_group.clone(), 0);
|
||||||
|
|
||||||
self.interrupt.msix = Some(VfioMsix {
|
self.interrupt.msix = Some(VfioMsix {
|
||||||
bar: msix_config,
|
bar: msix_config,
|
||||||
|
|||||||
@@ -336,6 +336,7 @@ impl VirtioPciDevice {
|
|||||||
msix_num: u16,
|
msix_num: u16,
|
||||||
iommu_mapping_cb: Option<Arc<VirtioIommuRemapping>>,
|
iommu_mapping_cb: Option<Arc<VirtioIommuRemapping>>,
|
||||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
||||||
|
pci_device_bdf: u32,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let device_clone = device.clone();
|
let device_clone = device.clone();
|
||||||
let locked_device = device_clone.lock().unwrap();
|
let locked_device = device_clone.lock().unwrap();
|
||||||
@@ -364,6 +365,7 @@ impl VirtioPciDevice {
|
|||||||
let msix_config = Arc::new(Mutex::new(MsixConfig::new(
|
let msix_config = Arc::new(Mutex::new(MsixConfig::new(
|
||||||
msix_num,
|
msix_num,
|
||||||
interrupt_source_group.clone(),
|
interrupt_source_group.clone(),
|
||||||
|
pci_device_bdf,
|
||||||
)));
|
)));
|
||||||
let msix_config_clone = msix_config.clone();
|
let msix_config_clone = msix_config.clone();
|
||||||
(Some(msix_config), Some(msix_config_clone))
|
(Some(msix_config), Some(msix_config_clone))
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ pub struct MsiIrqSourceConfig {
|
|||||||
pub low_addr: u32,
|
pub low_addr: u32,
|
||||||
/// Data to write to delivery message signaled interrupt.
|
/// Data to write to delivery message signaled interrupt.
|
||||||
pub data: u32,
|
pub data: u32,
|
||||||
|
/// Unique ID of the device to delivery message signaled interrupt.
|
||||||
|
pub devid: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration data for an interrupt source.
|
/// Configuration data for an interrupt source.
|
||||||
|
|||||||
@@ -2615,6 +2615,7 @@ impl DeviceManager {
|
|||||||
msix_num,
|
msix_num,
|
||||||
iommu_mapping_cb,
|
iommu_mapping_cb,
|
||||||
interrupt_manager,
|
interrupt_manager,
|
||||||
|
pci_device_bdf,
|
||||||
)
|
)
|
||||||
.map_err(DeviceManagerError::VirtioDevice)?;
|
.map_err(DeviceManagerError::VirtioDevice)?;
|
||||||
|
|
||||||
|
|||||||
+17
-4
@@ -4,7 +4,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
use devices::interrupt_controller::InterruptController;
|
use devices::interrupt_controller::InterruptController;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
@@ -118,7 +117,11 @@ pub trait MsiInterruptGroupOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait RoutingEntryExt {
|
pub trait RoutingEntryExt {
|
||||||
fn make_entry(gsi: u32, config: &InterruptSourceConfig) -> Result<Box<Self>>;
|
fn make_entry(
|
||||||
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> Result<Box<Self>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> MsiInterruptGroup<E> {
|
impl<E> MsiInterruptGroup<E> {
|
||||||
@@ -178,7 +181,7 @@ where
|
|||||||
|
|
||||||
fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()> {
|
fn update(&self, index: InterruptIndex, config: InterruptSourceConfig) -> Result<()> {
|
||||||
if let Some(route) = self.irq_routes.get(&index) {
|
if let Some(route) = self.irq_routes.get(&index) {
|
||||||
let entry = RoutingEntry::<_>::make_entry(route.gsi, &config)?;
|
let entry = RoutingEntry::<_>::make_entry(&self.vm, route.gsi, &config)?;
|
||||||
self.gsi_msi_routes
|
self.gsi_msi_routes
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -353,6 +356,7 @@ where
|
|||||||
|
|
||||||
pub mod kvm {
|
pub mod kvm {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use hypervisor::kvm::KVM_MSI_VALID_DEVID;
|
||||||
use hypervisor::kvm::{kvm_irq_routing, kvm_irq_routing_entry, KVM_IRQ_ROUTING_MSI};
|
use hypervisor::kvm::{kvm_irq_routing, kvm_irq_routing_entry, KVM_IRQ_ROUTING_MSI};
|
||||||
|
|
||||||
type KvmMsiInterruptGroup = MsiInterruptGroup<kvm_irq_routing_entry>;
|
type KvmMsiInterruptGroup = MsiInterruptGroup<kvm_irq_routing_entry>;
|
||||||
@@ -360,7 +364,11 @@ pub mod kvm {
|
|||||||
pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>;
|
pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>;
|
||||||
|
|
||||||
impl RoutingEntryExt for KvmRoutingEntry {
|
impl RoutingEntryExt for KvmRoutingEntry {
|
||||||
fn make_entry(gsi: u32, config: &InterruptSourceConfig) -> Result<Box<Self>> {
|
fn make_entry(
|
||||||
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> Result<Box<Self>> {
|
||||||
if let InterruptSourceConfig::MsiIrq(cfg) = &config {
|
if let InterruptSourceConfig::MsiIrq(cfg) = &config {
|
||||||
let mut kvm_route = kvm_irq_routing_entry {
|
let mut kvm_route = kvm_irq_routing_entry {
|
||||||
gsi,
|
gsi,
|
||||||
@@ -372,6 +380,11 @@ pub mod kvm {
|
|||||||
kvm_route.u.msi.address_hi = cfg.high_addr;
|
kvm_route.u.msi.address_hi = cfg.high_addr;
|
||||||
kvm_route.u.msi.data = cfg.data;
|
kvm_route.u.msi.data = cfg.data;
|
||||||
|
|
||||||
|
if vm.check_extension(hypervisor::Cap::MsiDevid) {
|
||||||
|
kvm_route.flags = KVM_MSI_VALID_DEVID;
|
||||||
|
kvm_route.u.msi.__bindgen_anon_1.devid = cfg.devid;
|
||||||
|
}
|
||||||
|
|
||||||
let kvm_entry = KvmRoutingEntry {
|
let kvm_entry = KvmRoutingEntry {
|
||||||
route: kvm_route,
|
route: kvm_route,
|
||||||
masked: false,
|
masked: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user