mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
irq: Fix pin based interrupt for virtio-pci
When the KVM capability KVM_CAP_SIGNAL_MSI is not present, the VMM falls back from MSI-X onto pin based interrupts. Unfortunately, this was not working as expected because the VirtioPciDevice object was always creating an MSI-X capability structure in the PCI configuration space. This was causing the guest drivers to expect MSI-X interrupts instead of the pin based generated ones. This patch takes care of avoiding the creation of a dedicated MSI-X capability structure when MSI is not supported by KVM. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
4be3dfeb37
commit
24dbe7003a
@ -171,7 +171,7 @@ pub struct VirtioPciDevice {
|
||||
common_config: VirtioPciCommonConfig,
|
||||
|
||||
// MSI-X config
|
||||
msix_config: Arc<Mutex<MsixConfig>>,
|
||||
msix_config: Option<Arc<Mutex<MsixConfig>>>,
|
||||
|
||||
// Number of MSI-X vectors
|
||||
msix_num: u16,
|
||||
@ -210,7 +210,13 @@ impl VirtioPciDevice {
|
||||
|
||||
let pci_device_id = VIRTIO_PCI_DEVICE_ID_BASE + device.device_type() as u16;
|
||||
|
||||
let (msix_config, msix_config_clone) = if msix_num > 0 {
|
||||
let msix_config = Arc::new(Mutex::new(MsixConfig::new(msix_num)));
|
||||
let msix_config_clone = msix_config.clone();
|
||||
(Some(msix_config), Some(msix_config_clone))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
let configuration = PciConfiguration::new(
|
||||
VIRTIO_PCI_VENDOR_ID,
|
||||
@ -221,7 +227,7 @@ impl VirtioPciDevice {
|
||||
PciHeaderType::Device,
|
||||
VIRTIO_PCI_VENDOR_ID,
|
||||
pci_device_id,
|
||||
Some(msix_config.clone()),
|
||||
msix_config_clone,
|
||||
);
|
||||
|
||||
Ok(VirtioPciDevice {
|
||||
@ -327,6 +333,7 @@ impl VirtioPciDevice {
|
||||
.add_capability(&configuration_cap)
|
||||
.map_err(PciDeviceError::CapabilitiesSetup)?;
|
||||
|
||||
if self.msix_config.is_some() {
|
||||
let msix_cap = MsixCap::new(
|
||||
settings_bar,
|
||||
self.msix_num,
|
||||
@ -336,6 +343,7 @@ impl VirtioPciDevice {
|
||||
self.configuration
|
||||
.add_capability(&msix_cap)
|
||||
.map_err(PciDeviceError::CapabilitiesSetup)?;
|
||||
}
|
||||
|
||||
self.settings_bar = settings_bar;
|
||||
Ok(())
|
||||
@ -360,15 +368,16 @@ impl PciDevice for VirtioPciDevice {
|
||||
}
|
||||
|
||||
fn assign_msix(&mut self, msi_cb: Arc<InterruptDelivery>) {
|
||||
self.msix_config
|
||||
if let Some(msix_config) = &self.msix_config {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.register_interrupt_cb(msi_cb.clone());
|
||||
|
||||
let msix_config = self.msix_config.clone();
|
||||
let msix_config_clone = msix_config.clone();
|
||||
|
||||
let cb = Arc::new(Box::new(move |queue: &Queue| {
|
||||
let config = &mut msix_config.lock().unwrap();
|
||||
let config = &mut msix_config_clone.lock().unwrap();
|
||||
let entry = &config.table_entries[queue.vector as usize];
|
||||
|
||||
// In case the vector control register associated with the entry
|
||||
@ -386,6 +395,7 @@ impl PciDevice for VirtioPciDevice {
|
||||
|
||||
self.interrupt_cb = Some(cb);
|
||||
}
|
||||
}
|
||||
|
||||
fn ioeventfds(&self) -> Vec<(&EventFd, u64, u64)> {
|
||||
let bar0 = self
|
||||
@ -470,17 +480,21 @@ impl PciDevice for VirtioPciDevice {
|
||||
// Handled with ioeventfds.
|
||||
}
|
||||
o if MSIX_TABLE_BAR_OFFSET <= o && o < MSIX_TABLE_BAR_OFFSET + MSIX_TABLE_SIZE => {
|
||||
self.msix_config
|
||||
if let Some(msix_config) = &self.msix_config {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_table(o - MSIX_TABLE_BAR_OFFSET, data);
|
||||
}
|
||||
}
|
||||
o if MSIX_PBA_BAR_OFFSET <= o && o < MSIX_PBA_BAR_OFFSET + MSIX_PBA_SIZE => {
|
||||
self.msix_config
|
||||
if let Some(msix_config) = &self.msix_config {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_pba(o - MSIX_PBA_BAR_OFFSET, data);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@ -510,17 +524,21 @@ impl PciDevice for VirtioPciDevice {
|
||||
// Handled with ioeventfds.
|
||||
}
|
||||
o if MSIX_TABLE_BAR_OFFSET <= o && o < MSIX_TABLE_BAR_OFFSET + MSIX_TABLE_SIZE => {
|
||||
self.msix_config
|
||||
if let Some(msix_config) = &self.msix_config {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.write_table(o - MSIX_TABLE_BAR_OFFSET, data);
|
||||
}
|
||||
}
|
||||
o if MSIX_PBA_BAR_OFFSET <= o && o < MSIX_PBA_BAR_OFFSET + MSIX_PBA_SIZE => {
|
||||
self.msix_config
|
||||
if let Some(msix_config) = &self.msix_config {
|
||||
msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.write_pba(o - MSIX_PBA_BAR_OFFSET, data);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
|
@ -429,8 +429,9 @@ impl DeviceManager {
|
||||
mmio_bus: &mut devices::Bus,
|
||||
msi_capable: bool,
|
||||
) -> DeviceManagerResult<()> {
|
||||
let mut virtio_pci_device =
|
||||
VirtioPciDevice::new(memory, virtio_device, DEFAULT_MSIX_VEC_NUM)
|
||||
let msix_num = if msi_capable { DEFAULT_MSIX_VEC_NUM } else { 0 };
|
||||
|
||||
let mut virtio_pci_device = VirtioPciDevice::new(memory, virtio_device, msix_num)
|
||||
.map_err(DeviceManagerError::VirtioDevice)?;
|
||||
|
||||
let bars = virtio_pci_device
|
||||
|
Loading…
Reference in New Issue
Block a user