Skip to content

Commit 9357139

Browse files
committed
refactor: set VirtIO interrupt during activation
The MMIO transport for VirtIO devices uses an `IrqTrigger` object as the object that models the logic for sending interrupts from the device to the guest. We create one such object for every VirtIO device when creating it. The MMIO device manager associates this object with an IRQ number and registers it with KVM. This commit changes the timing of association of an `IrqTrigger` with a VirtIO-mmio device. It only assigns such an object to the device during its activation. We do this to prepare for supporting a PCI transport for VirtIO devices. The cloud hypervisor implementation for these passes the interrupt objects used by the device during activation, so we make this change to have a uniform way to handle interrupts for both transports. Functionally, nothing changes for MMIO devices, as before activation we don't trigger any interrupts. Signed-off-by: Babis Chalios <bchalios@amazon.es>
1 parent 94ebc63 commit 9357139

29 files changed

+541
-319
lines changed

src/vmm/src/builder.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use crate::devices::virtio::block::device::Block;
4646
use crate::devices::virtio::device::VirtioDevice;
4747
use crate::devices::virtio::net::Net;
4848
use crate::devices::virtio::rng::Entropy;
49-
use crate::devices::virtio::transport::mmio::MmioTransport;
49+
use crate::devices::virtio::transport::mmio::{IrqTrigger, MmioTransport};
5050
use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
5151
#[cfg(feature = "gdb")]
5252
use crate::gdb;
@@ -657,8 +657,14 @@ fn attach_virtio_device<T: 'static + VirtioDevice + MutEventSubscriber + Debug>(
657657
) -> Result<(), MmioError> {
658658
event_manager.add_subscriber(device.clone());
659659

660+
let interrupt = Arc::new(IrqTrigger::new());
660661
// The device mutex mustn't be locked here otherwise it will deadlock.
661-
let device = MmioTransport::new(vmm.vm.guest_memory().clone(), device, is_vhost_user);
662+
let device = MmioTransport::new(
663+
vmm.vm.guest_memory().clone(),
664+
interrupt,
665+
device,
666+
is_vhost_user,
667+
);
662668
vmm.mmio_device_manager
663669
.register_mmio_virtio_for_boot(
664670
vmm.vm.fd(),

src/vmm/src/device_manager/mmio.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ pub enum MmioError {
5353
InvalidDeviceType,
5454
/// {0}
5555
InternalDeviceError(String),
56+
/// Could not create IRQ for MMIO device: {0}
57+
CreateIrq(#[from] std::io::Error),
5658
/// Invalid MMIO IRQ configuration.
5759
InvalidIrqConfig,
5860
/// Failed to register IO event: {0}
@@ -205,7 +207,7 @@ impl MMIODeviceManager {
205207
vm.register_ioevent(queue_evt, &io_addr, u32::try_from(i).unwrap())
206208
.map_err(MmioError::RegisterIoEvent)?;
207209
}
208-
vm.register_irqfd(&locked_device.interrupt_trigger().irq_evt, irq.get())
210+
vm.register_irqfd(&mmio_device.interrupt.irq_evt, irq.get())
209211
.map_err(MmioError::RegisterIrqFd)?;
210212
}
211213

@@ -549,7 +551,8 @@ mod tests {
549551
cmdline: &mut kernel_cmdline::Cmdline,
550552
dev_id: &str,
551553
) -> Result<u64, MmioError> {
552-
let mmio_device = MmioTransport::new(guest_mem, device, false);
554+
let interrupt = Arc::new(IrqTrigger::new());
555+
let mmio_device = MmioTransport::new(guest_mem, interrupt, device, false);
553556
let device_info = self.register_mmio_virtio_for_boot(
554557
vm,
555558
resource_allocator,
@@ -576,7 +579,7 @@ mod tests {
576579
dummy: u32,
577580
queues: Vec<Queue>,
578581
queue_evts: [EventFd; 1],
579-
interrupt_trigger: IrqTrigger,
582+
interrupt_trigger: Option<Arc<IrqTrigger>>,
580583
}
581584

582585
impl DummyDevice {
@@ -585,7 +588,7 @@ mod tests {
585588
dummy: 0,
586589
queues: QUEUE_SIZES.iter().map(|&s| Queue::new(s)).collect(),
587590
queue_evts: [EventFd::new(libc::EFD_NONBLOCK).expect("cannot create eventFD")],
588-
interrupt_trigger: IrqTrigger::new(),
591+
interrupt_trigger: None,
589592
}
590593
}
591594
}
@@ -618,7 +621,9 @@ mod tests {
618621
}
619622

620623
fn interrupt_trigger(&self) -> &IrqTrigger {
621-
&self.interrupt_trigger
624+
self.interrupt_trigger
625+
.as_ref()
626+
.expect("Device is not activated")
622627
}
623628

624629
fn ack_features_by_page(&mut self, page: u32, value: u32) {
@@ -636,7 +641,11 @@ mod tests {
636641
let _ = data;
637642
}
638643

639-
fn activate(&mut self, _: GuestMemoryMmap) -> Result<(), ActivateError> {
644+
fn activate(
645+
&mut self,
646+
_: GuestMemoryMmap,
647+
_: Arc<IrqTrigger>,
648+
) -> Result<(), ActivateError> {
640649
Ok(())
641650
}
642651

src/vmm/src/device_manager/persist.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::devices::virtio::rng::Entropy;
3434
use crate::devices::virtio::rng::persist::{
3535
EntropyConstructorArgs, EntropyPersistError as EntropyError, EntropyState,
3636
};
37-
use crate::devices::virtio::transport::mmio::MmioTransport;
37+
use crate::devices::virtio::transport::mmio::{IrqTrigger, MmioTransport};
3838
use crate::devices::virtio::vsock::persist::{
3939
VsockConstructorArgs, VsockState, VsockUdsConstructorArgs,
4040
};
@@ -473,11 +473,13 @@ impl<'a> Persist<'a> for MMIODeviceManager {
473473
as_subscriber: Arc<Mutex<dyn MutEventSubscriber>>,
474474
id: &String,
475475
state: &MmioTransportState,
476+
interrupt: Arc<IrqTrigger>,
476477
device_info: &MMIODeviceInfo,
477478
event_manager: &mut EventManager|
478479
-> Result<(), Self::Error> {
479480
let restore_args = MmioTransportConstructorArgs {
480481
mem: mem.clone(),
482+
interrupt,
481483
device,
482484
is_vhost_user,
483485
};
@@ -512,9 +514,11 @@ impl<'a> Persist<'a> for MMIODeviceManager {
512514
};
513515

514516
if let Some(balloon_state) = &state.balloon_device {
517+
let interrupt = Arc::new(IrqTrigger::new());
515518
let device = Arc::new(Mutex::new(Balloon::restore(
516519
BalloonConstructorArgs {
517520
mem: mem.clone(),
521+
interrupt: interrupt.clone(),
518522
restored_from_file: constructor_args.restored_from_file,
519523
},
520524
&balloon_state.device_state,
@@ -530,14 +534,19 @@ impl<'a> Persist<'a> for MMIODeviceManager {
530534
device,
531535
&balloon_state.device_id,
532536
&balloon_state.transport_state,
537+
interrupt,
533538
&balloon_state.device_info,
534539
constructor_args.event_manager,
535540
)?;
536541
}
537542

538543
for block_state in &state.block_devices {
544+
let interrupt = Arc::new(IrqTrigger::new());
539545
let device = Arc::new(Mutex::new(Block::restore(
540-
BlockConstructorArgs { mem: mem.clone() },
546+
BlockConstructorArgs {
547+
mem: mem.clone(),
548+
interrupt: interrupt.clone(),
549+
},
541550
&block_state.device_state,
542551
)?));
543552

@@ -551,6 +560,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
551560
device,
552561
&block_state.device_id,
553562
&block_state.transport_state,
563+
interrupt,
554564
&block_state.device_info,
555565
constructor_args.event_manager,
556566
)?;
@@ -573,9 +583,11 @@ impl<'a> Persist<'a> for MMIODeviceManager {
573583
}
574584

575585
for net_state in &state.net_devices {
586+
let interrupt = Arc::new(IrqTrigger::new());
576587
let device = Arc::new(Mutex::new(Net::restore(
577588
NetConstructorArgs {
578589
mem: mem.clone(),
590+
interrupt: interrupt.clone(),
579591
mmds: constructor_args
580592
.vm_resources
581593
.mmds
@@ -596,6 +608,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
596608
device,
597609
&net_state.device_id,
598610
&net_state.transport_state,
611+
interrupt,
599612
&net_state.device_info,
600613
constructor_args.event_manager,
601614
)?;
@@ -606,9 +619,11 @@ impl<'a> Persist<'a> for MMIODeviceManager {
606619
cid: vsock_state.device_state.frontend.cid,
607620
};
608621
let backend = VsockUnixBackend::restore(ctor_args, &vsock_state.device_state.backend)?;
622+
let interrupt = Arc::new(IrqTrigger::new());
609623
let device = Arc::new(Mutex::new(Vsock::restore(
610624
VsockConstructorArgs {
611625
mem: mem.clone(),
626+
interrupt: interrupt.clone(),
612627
backend,
613628
},
614629
&vsock_state.device_state.frontend,
@@ -624,13 +639,15 @@ impl<'a> Persist<'a> for MMIODeviceManager {
624639
device,
625640
&vsock_state.device_id,
626641
&vsock_state.transport_state,
642+
interrupt,
627643
&vsock_state.device_info,
628644
constructor_args.event_manager,
629645
)?;
630646
}
631647

632648
if let Some(entropy_state) = &state.entropy_device {
633-
let ctor_args = EntropyConstructorArgs::new(mem.clone());
649+
let interrupt = Arc::new(IrqTrigger::new());
650+
let ctor_args = EntropyConstructorArgs::new(mem.clone(), interrupt.clone());
634651

635652
let device = Arc::new(Mutex::new(Entropy::restore(
636653
ctor_args,
@@ -647,6 +664,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
647664
device,
648665
&entropy_state.device_id,
649666
&entropy_state.transport_state,
667+
interrupt,
650668
&entropy_state.device_info,
651669
constructor_args.event_manager,
652670
)?;

0 commit comments

Comments
 (0)