Skip to content

Commit 4b421a4

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 b00d3e8 commit 4b421a4

29 files changed

+517
-300
lines changed

src/vmm/src/builder.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::devices::virtio::block::device::Block;
4444
use crate::devices::virtio::device::VirtioDevice;
4545
use crate::devices::virtio::net::Net;
4646
use crate::devices::virtio::rng::Entropy;
47-
use crate::devices::virtio::transport::mmio::MmioTransport;
47+
use crate::devices::virtio::transport::mmio::{IrqTrigger, MmioTransport};
4848
use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
4949
#[cfg(feature = "gdb")]
5050
use crate::gdb;
@@ -597,8 +597,14 @@ fn attach_virtio_device<T: 'static + VirtioDevice + MutEventSubscriber + Debug>(
597597
) -> Result<(), MmioError> {
598598
event_manager.add_subscriber(device.clone());
599599

600+
let interrupt = Arc::new(IrqTrigger::new()?);
600601
// The device mutex mustn't be locked here otherwise it will deadlock.
601-
let device = MmioTransport::new(vmm.vm.guest_memory().clone(), device, is_vhost_user);
602+
let device = MmioTransport::new(
603+
vmm.vm.guest_memory().clone(),
604+
interrupt,
605+
device,
606+
is_vhost_user,
607+
);
602608
vmm.mmio_device_manager
603609
.register_mmio_virtio_for_boot(
604610
vmm.vm.fd(),

src/vmm/src/device_manager/mmio.rs

+17-7
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().unwrap());
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().expect("cannot create eventFD"),
591+
interrupt_trigger: None,
589592
}
590593
}
591594
}
@@ -617,8 +620,11 @@ mod tests {
617620
&self.queue_evts
618621
}
619622

620-
fn interrupt_trigger(&self) -> &IrqTrigger {
621-
&self.interrupt_trigger
623+
fn interrupt_trigger(&self) -> Arc<IrqTrigger> {
624+
self.interrupt_trigger
625+
.as_ref()
626+
.expect("Device is not activated")
627+
.clone()
622628
}
623629

624630
fn ack_features_by_page(&mut self, page: u32, value: u32) {
@@ -636,7 +642,11 @@ mod tests {
636642
let _ = data;
637643
}
638644

639-
fn activate(&mut self, _: GuestMemoryMmap) -> Result<(), ActivateError> {
645+
fn activate(
646+
&mut self,
647+
_: GuestMemoryMmap,
648+
_: Arc<IrqTrigger>,
649+
) -> Result<(), ActivateError> {
640650
Ok(())
641651
}
642652

src/vmm/src/device_manager/persist.rs

+26-3
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,12 @@ impl<'a> Persist<'a> for MMIODeviceManager {
512514
};
513515

514516
if let Some(balloon_state) = &state.balloon_device {
517+
let interrupt =
518+
Arc::new(IrqTrigger::new().expect("Could not create interrupt for MMIO device"));
515519
let device = Arc::new(Mutex::new(Balloon::restore(
516520
BalloonConstructorArgs {
517521
mem: mem.clone(),
522+
interrupt: interrupt.clone(),
518523
restored_from_file: constructor_args.restored_from_file,
519524
},
520525
&balloon_state.device_state,
@@ -530,14 +535,20 @@ impl<'a> Persist<'a> for MMIODeviceManager {
530535
device,
531536
&balloon_state.device_id,
532537
&balloon_state.transport_state,
538+
interrupt,
533539
&balloon_state.device_info,
534540
constructor_args.event_manager,
535541
)?;
536542
}
537543

538544
for block_state in &state.block_devices {
545+
let interrupt =
546+
Arc::new(IrqTrigger::new().expect("Could not create interrupt for MMIO device"));
539547
let device = Arc::new(Mutex::new(Block::restore(
540-
BlockConstructorArgs { mem: mem.clone() },
548+
BlockConstructorArgs {
549+
mem: mem.clone(),
550+
interrupt: interrupt.clone(),
551+
},
541552
&block_state.device_state,
542553
)?));
543554

@@ -551,6 +562,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
551562
device,
552563
&block_state.device_id,
553564
&block_state.transport_state,
565+
interrupt,
554566
&block_state.device_info,
555567
constructor_args.event_manager,
556568
)?;
@@ -573,9 +585,12 @@ impl<'a> Persist<'a> for MMIODeviceManager {
573585
}
574586

575587
for net_state in &state.net_devices {
588+
let interrupt =
589+
Arc::new(IrqTrigger::new().expect("Could not create interrupt for MMIO device"));
576590
let device = Arc::new(Mutex::new(Net::restore(
577591
NetConstructorArgs {
578592
mem: mem.clone(),
593+
interrupt: interrupt.clone(),
579594
mmds: constructor_args
580595
.vm_resources
581596
.mmds
@@ -596,6 +611,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
596611
device,
597612
&net_state.device_id,
598613
&net_state.transport_state,
614+
interrupt,
599615
&net_state.device_info,
600616
constructor_args.event_manager,
601617
)?;
@@ -606,9 +622,12 @@ impl<'a> Persist<'a> for MMIODeviceManager {
606622
cid: vsock_state.device_state.frontend.cid,
607623
};
608624
let backend = VsockUnixBackend::restore(ctor_args, &vsock_state.device_state.backend)?;
625+
let interrupt =
626+
Arc::new(IrqTrigger::new().expect("Could not create interrupt for MMIO device"));
609627
let device = Arc::new(Mutex::new(Vsock::restore(
610628
VsockConstructorArgs {
611629
mem: mem.clone(),
630+
interrupt: interrupt.clone(),
612631
backend,
613632
},
614633
&vsock_state.device_state.frontend,
@@ -624,13 +643,16 @@ impl<'a> Persist<'a> for MMIODeviceManager {
624643
device,
625644
&vsock_state.device_id,
626645
&vsock_state.transport_state,
646+
interrupt,
627647
&vsock_state.device_info,
628648
constructor_args.event_manager,
629649
)?;
630650
}
631651

632652
if let Some(entropy_state) = &state.entropy_device {
633-
let ctor_args = EntropyConstructorArgs::new(mem.clone());
653+
let interrupt =
654+
Arc::new(IrqTrigger::new().expect("Could not create interrupt for MMIO device"));
655+
let ctor_args = EntropyConstructorArgs::new(mem.clone(), interrupt.clone());
634656

635657
let device = Arc::new(Mutex::new(Entropy::restore(
636658
ctor_args,
@@ -647,6 +669,7 @@ impl<'a> Persist<'a> for MMIODeviceManager {
647669
device,
648670
&entropy_state.device_id,
649671
&entropy_state.transport_state,
672+
interrupt,
650673
&entropy_state.device_info,
651674
constructor_args.event_manager,
652675
)?;

0 commit comments

Comments
 (0)