mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
msix: Handle MSI-X vector masking
The current MSI-X implementation completely ignores the values found in the Vector Control register related to a specific vector, and never updates the Pending Bit Array. According to the PCI specification, MSI-X vectors can be masked through the Vector Control register on bit 0. If this bit is set, the device should not inject any MSI message. When the device runs into such situation, it must not inject the interrupt, but instead it must update the bit corresponding to the vector number in the Pending Bit Array. Later on, if/when the Vector Control register is updated, and if the bit 0 is flipped from 0 to 1, the device must look into the PBA to find out if there was a pending interrupt for this specific vector. If that's the case, an MSI message is injected and the bit from the PBA is cleared. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
committed by
Rob Bradford
parent
42378caa8b
commit
d810c7712d
@@ -358,15 +358,27 @@ impl PciDevice for VirtioPciDevice {
|
||||
}
|
||||
|
||||
fn assign_msix(&mut self, msi_cb: Arc<InterruptDelivery>) {
|
||||
self.msix_config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.register_interrupt_cb(msi_cb.clone());
|
||||
|
||||
let msix_config = self.msix_config.clone();
|
||||
|
||||
let cb = Arc::new(Box::new(move |queue: &Queue| {
|
||||
let param = InterruptParameters {
|
||||
msix: Some(
|
||||
msix_config.lock().unwrap().table_entries[queue.vector as usize].clone(),
|
||||
),
|
||||
};
|
||||
(msi_cb)(param)
|
||||
let entry = &msix_config.lock().unwrap().table_entries[queue.vector as usize];
|
||||
|
||||
// In case the vector control register associated with the entry
|
||||
// has its first bit set, this means the vector is masked and the
|
||||
// device should not inject the interrupt.
|
||||
// Instead, the Pending Bit Array table is updated to reflect there
|
||||
// is a pending interrupt for this specific vector.
|
||||
if entry.vector_ctl == 0x0000_0001u32 {
|
||||
msix_config.lock().unwrap().set_pba_bit(queue.vector, false);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
(msi_cb)(InterruptParameters { msix: Some(entry) })
|
||||
}) as VirtioInterrupt);
|
||||
|
||||
self.interrupt_cb = Some(cb);
|
||||
|
||||
Reference in New Issue
Block a user