]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
accel/mshv: fix ioeventfd deassignment to forward correct datamatch value
authorAastha Rawat <aastharawat@linux.microsoft.com>
Thu, 9 Apr 2026 11:53:06 +0000 (11:53 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 23 Apr 2026 10:27:27 +0000 (12:27 +0200)
unregister_ioevent() is not forwarding the datamatch (queue index) to
the mshv driver, causing only the first VirtIO-MMIO queue to be
deassigned correctly. Subsequent queues fail with `-ENOENT`, triggering
a fatal abort().

This failure was discovered while booting arm64 EDK2 firmware with mshv
accel.

Signed-off-by: Aastha Rawat <aastharawat@linux.microsoft.com>
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
Link: https://lore.kernel.org/r/20260409-fix_ioevent-v1-1-053b810ae6fb@linux.microsoft.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
accel/mshv/mshv-all.c

index d4cc7f537158a65268252641c5d5751a5adfab0d..e1a8d62f8d289ea75b0a690e7c605b88dab980bc 100644 (file)
@@ -278,13 +278,22 @@ static int ioeventfd(int vm_fd, int event_fd, uint64_t addr, Datamatch dm,
     return ioctl(vm_fd, MSHV_IOEVENTFD, &args);
 }
 
-static int unregister_ioevent(int vm_fd, int event_fd, uint64_t mmio_addr)
+static int unregister_ioevent(int vm_fd, int event_fd, uint64_t mmio_addr,
+                              uint64_t data, uint32_t len, bool data_match)
 {
     uint32_t flags = 0;
     Datamatch dm = {0};
 
     flags |= BIT(MSHV_IOEVENTFD_BIT_DEASSIGN);
-    dm.tag = DATAMATCH_NONE;
+    if (!data_match) {
+        dm.tag = DATAMATCH_NONE;
+    } else if (len == sizeof(uint64_t)) {
+        dm.tag = DATAMATCH_U64;
+        dm.value.u64 = data;
+    } else {
+        dm.tag = DATAMATCH_U32;
+        dm.value.u32 = data;
+    }
 
     return ioeventfd(vm_fd, event_fd, mmio_addr, dm, flags);
 }
@@ -337,11 +346,12 @@ static void mem_ioeventfd_del(MemoryListener *listener,
     int fd = event_notifier_get_fd(e);
     int ret;
     uint64_t addr = section->offset_within_address_space;
+    uint64_t len = int128_get64(section->size);
 
     trace_mshv_mem_ioeventfd_del(section->offset_within_address_space,
                                  int128_get64(section->size), data);
 
-    ret = unregister_ioevent(mshv_state->vm, fd, addr);
+    ret = unregister_ioevent(mshv_state->vm, fd, addr, data, len, match_data);
     if (ret < 0) {
         error_report("Failed to unregister ioeventfd: %s (%d)", strerror(-ret),
                      -ret);