virtio-devices: Handle virtio queues interrupts from transport layer

Instead of relying on the virtio-queue crate to store the information
about the MSI-X vectors for each queue, we handle this directly from the
PCI transport layer.

This is the first step in getting closer to the upstream version of
virtio-queue so that we can eventually move fully to the upstream
version.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf
2022-01-24 15:30:42 +01:00
parent d3081ff50c
commit de3e003e3e
17 changed files with 73 additions and 107 deletions
+12 -25
View File
@@ -267,7 +267,6 @@ struct QueueState {
max_size: u16,
size: u16,
ready: bool,
vector: u16,
desc_table: u64,
avail_ring: u64,
used_ring: u64,
@@ -358,6 +357,7 @@ impl VirtioPciDevice {
for _ in locked_device.queue_max_sizes().iter() {
queue_evts.push(EventFd::new(EFD_NONBLOCK)?)
}
let num_queues = locked_device.queue_max_sizes().len();
let queues = locked_device
.queue_max_sizes()
.iter()
@@ -429,6 +429,7 @@ impl VirtioPciDevice {
driver_feature_select: 0,
queue_select: 0,
msix_config: Arc::new(AtomicU16::new(VIRTQ_MSI_NO_VECTOR)),
msix_queues: Arc::new(Mutex::new(vec![VIRTQ_MSI_NO_VECTOR; num_queues])),
},
msix_config,
msix_num,
@@ -453,6 +454,7 @@ impl VirtioPciDevice {
virtio_pci_device.virtio_interrupt = Some(Arc::new(VirtioInterruptMsix::new(
msix_config.clone(),
virtio_pci_device.common_config.msix_config.clone(),
virtio_pci_device.common_config.msix_queues.clone(),
virtio_pci_device.interrupt_source_group.clone(),
)));
}
@@ -471,7 +473,6 @@ impl VirtioPciDevice {
max_size: q.max_size(),
size: q.state.size,
ready: q.state.ready,
vector: q.state.vector,
desc_table: q.state.desc_table.0,
avail_ring: q.state.avail_ring.0,
used_ring: q.state.used_ring.0,
@@ -490,7 +491,6 @@ impl VirtioPciDevice {
for (i, queue) in self.queues.iter_mut().enumerate() {
queue.state.size = state.queues[i].size;
queue.state.ready = state.queues[i].ready;
queue.state.vector = state.queues[i].vector;
queue.state.desc_table = GuestAddress(state.queues[i].desc_table);
queue.state.avail_ring = GuestAddress(state.queues[i].avail_ring);
queue.state.used_ring = GuestAddress(state.queues[i].used_ring);
@@ -716,6 +716,7 @@ impl VirtioTransport for VirtioPciDevice {
pub struct VirtioInterruptMsix {
msix_config: Arc<Mutex<MsixConfig>>,
config_vector: Arc<AtomicU16>,
queues_vectors: Arc<Mutex<Vec<u16>>>,
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
}
@@ -723,30 +724,24 @@ impl VirtioInterruptMsix {
pub fn new(
msix_config: Arc<Mutex<MsixConfig>>,
config_vector: Arc<AtomicU16>,
queues_vectors: Arc<Mutex<Vec<u16>>>,
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
) -> Self {
VirtioInterruptMsix {
msix_config,
config_vector,
queues_vectors,
interrupt_source_group,
}
}
}
impl VirtioInterrupt for VirtioInterruptMsix {
fn trigger(
&self,
int_type: &VirtioInterruptType,
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
) -> std::result::Result<(), std::io::Error> {
fn trigger(&self, int_type: VirtioInterruptType) -> std::result::Result<(), std::io::Error> {
let vector = match int_type {
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
VirtioInterruptType::Queue => {
if let Some(q) = queue {
q.state.vector
} else {
0
}
VirtioInterruptType::Queue(queue_index) => {
self.queues_vectors.lock().unwrap()[queue_index as usize]
}
};
@@ -770,19 +765,11 @@ impl VirtioInterrupt for VirtioInterruptMsix {
.trigger(vector as InterruptIndex)
}
fn notifier(
&self,
int_type: &VirtioInterruptType,
queue: Option<&Queue<GuestMemoryAtomic<GuestMemoryMmap>>>,
) -> Option<EventFd> {
fn notifier(&self, int_type: VirtioInterruptType) -> Option<EventFd> {
let vector = match int_type {
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
VirtioInterruptType::Queue => {
if let Some(q) = queue {
q.state.vector
} else {
0
}
VirtioInterruptType::Queue(queue_index) => {
self.queues_vectors.lock().unwrap()[queue_index as usize]
}
};