Skip to content

Commit 869ee78

Browse files
committed
virtio: add generic interrupt trait
Describing the APIs that need to implement types that are used as interrupts for VirtIO devices. Currently, we only use `IrqInterrupt` interrupts, but this will change once we have MSI-X with PCIe devices. Signed-off-by: Babis Chalios <bchalios@amazon.es>
1 parent 4b421a4 commit 869ee78

File tree

2 files changed

+97
-19
lines changed

2 files changed

+97
-19
lines changed

src/vmm/src/devices/virtio/transport/mmio.rs

+63-19
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, MutexGuard};
1111

1212
use vmm_sys_util::eventfd::EventFd;
1313

14+
use super::{VirtioInterrupt, VirtioInterruptType};
1415
use crate::devices::virtio::device::VirtioDevice;
1516
use crate::devices::virtio::device_status;
1617
use crate::devices::virtio::queue::Queue;
@@ -375,13 +376,56 @@ pub enum IrqType {
375376
Vring,
376377
}
377378

379+
impl From<VirtioInterruptType> for IrqType {
380+
fn from(interrupt_type: VirtioInterruptType) -> Self {
381+
match interrupt_type {
382+
VirtioInterruptType::Config => IrqType::Config,
383+
VirtioInterruptType::Queue(_) => IrqType::Vring,
384+
}
385+
}
386+
}
387+
378388
/// Helper struct that is responsible for triggering guest IRQs
379389
#[derive(Debug)]
380390
pub struct IrqTrigger {
381391
pub(crate) irq_status: Arc<AtomicU32>,
382392
pub(crate) irq_evt: EventFd,
383393
}
384394

395+
impl VirtioInterrupt for IrqTrigger {
396+
fn trigger(&self, interrupt_type: super::VirtioInterruptType) -> Result<(), std::io::Error> {
397+
match interrupt_type {
398+
VirtioInterruptType::Config => self.trigger_irq(IrqType::Config),
399+
VirtioInterruptType::Queue(_) => self.trigger_irq(IrqType::Vring),
400+
}
401+
}
402+
403+
fn notifier(&self, _interrupt_type: VirtioInterruptType) -> Option<EventFd> {
404+
self.irq_evt.try_clone().ok()
405+
}
406+
407+
fn status(&self) -> Arc<AtomicU32> {
408+
self.irq_status.clone()
409+
}
410+
411+
#[cfg(test)]
412+
fn has_pending_interrupt(&self, interrupt_type: VirtioInterruptType) -> bool {
413+
if let Ok(num_irqs) = self.irq_evt.read() {
414+
if num_irqs == 0 {
415+
return false;
416+
}
417+
418+
let irq_status = self.irq_status.load(Ordering::SeqCst);
419+
return matches!(
420+
(irq_status, interrupt_type.into()),
421+
(VIRTIO_MMIO_INT_CONFIG, IrqType::Config) | (VIRTIO_MMIO_INT_VRING, IrqType::Vring)
422+
);
423+
}
424+
425+
false
426+
}
427+
}
428+
385429
impl IrqTrigger {
386430
pub fn new() -> std::io::Result<Self> {
387431
Ok(Self {
@@ -993,6 +1037,25 @@ pub(crate) mod tests {
9931037
assert!(d.locked_device().is_activated());
9941038
}
9951039

1040+
impl IrqTrigger {
1041+
pub fn has_pending_irq(&self, irq_type: IrqType) -> bool {
1042+
if let Ok(num_irqs) = self.irq_evt.read() {
1043+
if num_irqs == 0 {
1044+
return false;
1045+
}
1046+
1047+
let irq_status = self.irq_status.load(Ordering::SeqCst);
1048+
return matches!(
1049+
(irq_status, irq_type),
1050+
(VIRTIO_MMIO_INT_CONFIG, IrqType::Config)
1051+
| (VIRTIO_MMIO_INT_VRING, IrqType::Vring)
1052+
);
1053+
}
1054+
1055+
false
1056+
}
1057+
}
1058+
9961059
#[test]
9971060
fn test_bus_device_reset() {
9981061
let m = single_region_mem(0x1000);
@@ -1053,25 +1116,6 @@ pub(crate) mod tests {
10531116
assert_eq!(dummy_dev.acked_features(), 24);
10541117
}
10551118

1056-
impl IrqTrigger {
1057-
pub fn has_pending_irq(&self, irq_type: IrqType) -> bool {
1058-
if let Ok(num_irqs) = self.irq_evt.read() {
1059-
if num_irqs == 0 {
1060-
return false;
1061-
}
1062-
1063-
let irq_status = self.irq_status.load(Ordering::SeqCst);
1064-
return matches!(
1065-
(irq_status, irq_type),
1066-
(VIRTIO_MMIO_INT_CONFIG, IrqType::Config)
1067-
| (VIRTIO_MMIO_INT_VRING, IrqType::Vring)
1068-
);
1069-
}
1070-
1071-
false
1072-
}
1073-
}
1074-
10751119
#[test]
10761120
fn irq_trigger() {
10771121
let irq_trigger = IrqTrigger::new().unwrap();
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
11
// Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::sync::Arc;
5+
use std::sync::atomic::AtomicU32;
6+
7+
use vmm_sys_util::eventfd::EventFd;
8+
49
/// MMIO transport for VirtIO devices
510
pub mod mmio;
11+
12+
/// Represents the types of interrupts used by VirtIO devices
13+
#[derive(Debug, Clone)]
14+
pub enum VirtioInterruptType {
15+
/// Interrupt for VirtIO configuration changes
16+
Config,
17+
/// Interrupts for new events in a queue.
18+
Queue(u16),
19+
}
20+
21+
/// API of interrupt types used by VirtIO devices
22+
pub trait VirtioInterrupt: std::fmt::Debug + Send + Sync {
23+
/// Trigger a VirtIO interrupt.
24+
fn trigger(&self, interrupt_type: VirtioInterruptType) -> Result<(), std::io::Error>;
25+
26+
/// Get the `EventFd` (if any) that backs the underlying interrupt.
27+
fn notifier(&self, _interrupt_type: VirtioInterruptType) -> Option<EventFd> {
28+
None
29+
}
30+
31+
/// Get the current device interrupt status.
32+
fn status(&self) -> Arc<AtomicU32> {
33+
Arc::new(AtomicU32::new(0))
34+
}
35+
36+
/// Returns true if there is any pending interrupt
37+
#[cfg(test)]
38+
fn has_pending_interrupt(&self, interrupt_type: VirtioInterruptType) -> bool;
39+
}

0 commit comments

Comments
 (0)