@samitouri / QOSamiQemu / commits / c0c97fbc6c

hw/arm/smmuv3-accel: Read and propagate host vIOMMU events

Install an event handler on the vEVENTQ fd to read and propagate host generated vIOMMU events to the guest. The handler runs in QEMU's main loop, using a non-blocking fd registered via qemu_set_fd_handler(). Tested-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Tested-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com> Message-id: 20260226084456.112142-6-skolothumtho@nvidia.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Shameer Kolothum committed Mar 6, 2026 at 09:01 UTC c0c97fbc6cf764f0d66d5122c4117d0770e89902
1 file changed +64
hw/arm/smmuv3-accel.c
+64
@@ -390,6 +390,50 @@ bool smmuv3_accel_issue_inv_cmd(SMMUv3State *bs, void *cmd, SMMUDevice *sdev,
390 sizeof(Cmd), &entry_num, cmd, errp);
391 }
392
393 +static void smmuv3_accel_event_read(void *opaque)
394 +{
395 + SMMUv3State *s = opaque;
396 + IOMMUFDVeventq *veventq = s->s_accel->veventq;
397 + struct {
398 + struct iommufd_vevent_header hdr;
399 + struct iommu_vevent_arm_smmuv3 vevent;
400 + } buf;
401 + enum iommu_veventq_type type = IOMMU_VEVENTQ_TYPE_ARM_SMMUV3;
402 + uint32_t id = veventq->veventq_id;
403 + uint32_t last_seq = veventq->last_event_seq;
404 + ssize_t bytes;
405 +
406 + bytes = read(veventq->veventq_fd, &buf, sizeof(buf));
407 + if (bytes <= 0) {
408 + if (errno == EAGAIN || errno == EINTR) {
409 + return;
410 + }
411 + error_report_once("vEVENTQ(type %u id %u): read failed (%m)", type, id);
412 + return;
413 + }
414 +
415 + if (bytes == sizeof(buf.hdr) &&
416 + (buf.hdr.flags & IOMMU_VEVENTQ_FLAG_LOST_EVENTS)) {
417 + error_report_once("vEVENTQ(type %u id %u): overflowed", type, id);
418 + veventq->event_start = false;
419 + return;
420 + }
421 + if (bytes < sizeof(buf)) {
422 + error_report_once("vEVENTQ(type %u id %u): short read(%zd/%zd bytes)",
423 + type, id, bytes, sizeof(buf));
424 + return;
425 + }
426 +
427 + /* Check sequence in hdr for lost events if any */
428 + if (veventq->event_start && (buf.hdr.sequence - last_seq != 1)) {
429 + error_report_once("vEVENTQ(type %u id %u): lost %u event(s)",
430 + type, id, buf.hdr.sequence - last_seq - 1);
431 + }
432 + veventq->last_event_seq = buf.hdr.sequence;
433 + veventq->event_start = true;
434 + smmuv3_propagate_event(s, (Evt *)&buf.vevent);
435 +}
436 +
437 static void smmuv3_accel_free_veventq(SMMUv3AccelState *accel)
438 {
439 IOMMUFDVeventq *veventq = accel->veventq;
@@ -397,6 +441,7 @@ static void smmuv3_accel_free_veventq(SMMUv3AccelState *accel)
441 if (!veventq) {
442 return;
443 }
444 + qemu_set_fd_handler(veventq->veventq_fd, NULL, NULL, NULL);
445 close(veventq->veventq_fd);
446 iommufd_backend_free_id(accel->viommu->iommufd, veventq->veventq_id);
447 g_free(veventq);
@@ -424,6 +469,7 @@ bool smmuv3_accel_alloc_veventq(SMMUv3State *s, Error **errp)
469 IOMMUFDVeventq *veventq;
470 uint32_t veventq_id;
471 uint32_t veventq_fd;
472 + int flags;
473
474 if (!accel || !accel->viommu) {
475 return true;
@@ -445,12 +491,30 @@ bool smmuv3_accel_alloc_veventq(SMMUv3State *s, Error **errp)
491 return false;
492 }
493
494 + flags = fcntl(veventq_fd, F_GETFL);
495 + if (flags < 0) {
496 + error_setg_errno(errp, errno, "Failed to get flags for vEVENTQ fd");
497 + goto free_veventq;
498 + }
499 + if (fcntl(veventq_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
500 + error_setg_errno(errp, errno, "Failed to set O_NONBLOCK on vEVENTQ fd");
501 + goto free_veventq;
502 + }
503 +
504 veventq = g_new0(IOMMUFDVeventq, 1);
505 veventq->veventq_id = veventq_id;
506 veventq->veventq_fd = veventq_fd;
507 veventq->viommu = accel->viommu;
508 accel->veventq = veventq;
509 +
510 + /* Set up event handler for veventq fd */
511 + qemu_set_fd_handler(veventq_fd, smmuv3_accel_event_read, NULL, s);
512 return true;
513 +
514 +free_veventq:
515 + close(veventq_fd);
516 + iommufd_backend_free_id(accel->viommu->iommufd, veventq_id);
517 + return false;
518 }
519
520 static bool