Skip to content

Commit 3422265

Browse files
ilstamShadowCurse
authored andcommitted
vmm: Deassign ioeventfds on PCI device hot-unplug
Closing the eventfds registered with KVM_IOEVENTFD is not sufficient, KVM holds its own references. We need to explicitly assign them by calling KVM_IOEVENTFD again with the KVM_IOEVENTFD_FLAG_DEASSIGN flag. Do that in hot_unplug_device(). Add VirtioPciDevice::unregister_notification_ioevents() as the counterpart to register_notification_ioevent() and move the common logic into a private helper. Since we are here rename register_notification_ioevent() to register_notification_ioevents() since it's used to register multiple events. Signed-off-by: Ilias Stamatis <ilstam@amazon.com>
1 parent 6dba32d commit 3422265

3 files changed

Lines changed: 22 additions & 4 deletions

File tree

‎src/vmm/src/device_manager/mod.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,10 @@ impl DeviceManager {
599599
let pci_device_arc = self.pci_devices.virtio_devices.remove(&device_id).unwrap();
600600
let pci_device = pci_device_arc.lock().expect("Poisoned lock");
601601

602+
pci_device
603+
.unregister_notification_ioevents(&vm)
604+
.map_err(PciManagerError::Kvm)?;
605+
602606
vm.common
603607
.mmio_bus
604608
.remove(pci_device.config_bar_addr(), CAPABILITY_BAR_SIZE)

‎src/vmm/src/device_manager/pci_mngr.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl PciDevices {
130130
Self::register_bars_with_bus(vm, &virtio_device)?;
131131

132132
let mut device = virtio_device.lock().expect("Poisoned lock");
133-
device.register_notification_ioevent(vm)?;
133+
device.register_notification_ioevents(vm)?;
134134

135135
let sub_id = event_manager.add_subscriber(device.virtio_device());
136136
device.sub_id = Some(sub_id);

‎src/vmm/src/devices/virtio/transport/pci/device.rs‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,7 @@ impl VirtioPciDevice {
620620
!self.device_activated.load(Ordering::SeqCst) && self.is_driver_ready()
621621
}
622622

623-
/// Register the IoEvent notification for a VirtIO device
624-
pub fn register_notification_ioevent(&self, vm: &KvmVm) -> Result<(), errno::Error> {
623+
fn set_notification_ioevents(&self, vm: &KvmVm, assign: bool) -> Result<(), errno::Error> {
625624
let bar_addr = self.config_bar_addr();
626625
for (i, queue_evt) in self
627626
.device
@@ -634,11 +633,26 @@ impl VirtioPciDevice {
634633
let notify_base = bar_addr + u64::from(NOTIFICATION_BAR_OFFSET);
635634
let io_addr =
636635
IoEventAddress::Mmio(notify_base + i as u64 * u64::from(NOTIFY_OFF_MULTIPLIER));
637-
vm.fd().register_ioevent(queue_evt, &io_addr, NoDatamatch)?;
636+
if assign {
637+
vm.fd().register_ioevent(queue_evt, &io_addr, NoDatamatch)?;
638+
} else {
639+
vm.fd()
640+
.unregister_ioevent(queue_evt, &io_addr, NoDatamatch)?;
641+
}
638642
}
639643
Ok(())
640644
}
641645

646+
/// Register the IoEvent notifications for a VirtIO device.
647+
pub fn register_notification_ioevents(&self, vm: &KvmVm) -> Result<(), errno::Error> {
648+
self.set_notification_ioevents(vm, true)
649+
}
650+
651+
/// Unregister the IoEvent notifications for a VirtIO device.
652+
pub fn unregister_notification_ioevents(&self, vm: &KvmVm) -> Result<(), errno::Error> {
653+
self.set_notification_ioevents(vm, false)
654+
}
655+
642656
pub fn state(&self) -> VirtioPciDeviceState {
643657
VirtioPciDeviceState {
644658
sbdf: self.sbdf,

0 commit comments

Comments
 (0)