[PATCH v3 6/6] intel_iommu_accel: teardown FAULTQ resources in bottom half
Zhenzhong Duan <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
When a pasid entry becomes invalid, we need to release all resources allocated for that entry including FAULTQ object and fault_fd. We call qemu_set_fd_handler() to detach fault_fd's io_read handler and wakes up main thread from poll(), but there could still be a small window we call iommufd_backend_free_id(fault_id) before poll() exit and release fault_id file reference. In this rare case, FAULTQ object free return -EBUSY because opened fault_id file keeps reference of FAULTQ object. Teardown FAULTQ resources in bottom half to ensure poll() has released fault_id file reference. Suggested-by: Shameer Kolothum <[email protected]> Signed-off-by: Zhenzhong Duan <[email protected]> Tested-by: Xudong Hao <[email protected]> --- hw/i386/intel_iommu_accel.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c index 6ec03c1b05..f757ef6b09 100644 --- a/hw/i386/intel_iommu_accel.c +++ b/hw/i386/intel_iommu_accel.c @@ -246,15 +246,40 @@ free_faultq: return false; } +typedef struct IOMMUFaultQueue { + IOMMUFDBackend *iommufd; + uint32_t id; + int fd; +} IOMMUFaultQueue; + +static void faultq_teardown_bh(void *opaque) +{ + IOMMUFaultQueue *fq = opaque; + + qemu_set_fd_handler(fq->fd, NULL, NULL, NULL); + close(fq->fd); + iommufd_backend_free_id(fq->iommufd, fq->id); + + g_free(fq); +} + static void vtd_destroy_old_fs_faultq(VTDAccelPASIDCacheEntry *vtd_pce) { + HostIOMMUDeviceIOMMUFD *idev = + HOST_IOMMU_DEVICE_IOMMUFD(vtd_pce->vtd_hiod->hiod); + if (vtd_pce->fault_fd < 0) { return; } - qemu_set_fd_handler(vtd_pce->fault_fd, NULL, NULL, NULL); - vtd_destroy_fs_faultq(vtd_pce->vtd_hiod, vtd_pce->fault_id, - vtd_pce->fault_fd); + IOMMUFaultQueue *fq = g_malloc(sizeof(IOMMUFaultQueue)); + fq->iommufd = idev->iommufd; + fq->fd = vtd_pce->fault_fd; + fq->id = vtd_pce->fault_id; + + aio_bh_schedule_oneshot(iohandler_get_aio_context(), + faultq_teardown_bh, fq); + vtd_pce->fault_id = 0; vtd_pce->fault_fd = -1; } -- 2.52.0