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