All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iommu/virtio: Report faults via report_iommu_fault()
@ 2026-07-13  1:04 weimin xiong
  2026-07-13  2:07 ` Baolu Lu
  2026-07-14  2:02 ` [PATCH v2] " weimin xiong
  0 siblings, 2 replies; 7+ messages in thread
From: weimin xiong @ 2026-07-13  1:04 UTC (permalink / raw)
  To: iommu; +Cc: jean-philippe, jgg, xiongweimin

From: xiongweimin <xiongweimin@kylinos.cn>

Fault events currently only print a ratelimited error with the endpoint
ID. Upper layers (VFIO, drivers with domain fault handlers) cannot react.

Track endpoints in an xarray keyed by endpoint ID at probe/release time,
and call report_iommu_fault() when a fault carries an address and the
endpoint is attached to a domain. Keep the existing log as a fallback
when the endpoint is unknown or detached.

Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
Cc: iommu@lists.linux.dev
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Cc: Jason Gunthorpe <jgg@nvidia.com>
---

--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -19,6 +19,7 @@
 #include <linux/virtio_config.h>
 #include <linux/virtio_ids.h>
 #include <linux/wait.h>
+#include <linux/xarray.h>
 
 #include <uapi/linux/virtio_iommu.h>
 
@@ -42,6 +43,8 @@
 	spinlock_t			request_lock;
 	struct list_head		requests;
 	void				*evts;
+	/* endpoint ID -> viommu_endpoint, for fault reporting */
+	struct xarray			endpoints;
 
 	/* Device configuration */
 	struct iommu_domain_geometry	geometry;
@@ -593,7 +596,10 @@
 static int viommu_fault_handler(struct viommu_dev *viommu,
 				struct virtio_iommu_fault *fault)
 {
+	struct viommu_endpoint *vdev;
+	struct iommu_domain *domain;
 	char *reason_str;
+	int fault_flags = IOMMU_FAULT_READ;
 
 	u8 reason	= fault->reason;
 	u32 flags	= le32_to_cpu(fault->flags);
@@ -613,16 +619,28 @@
 		break;
 	}
 
-	/* TODO: find EP by ID and report_iommu_fault */
-	if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
-		dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx [%s%s%s]\n",
+	if (flags & VIRTIO_IOMMU_FAULT_F_WRITE)
+		fault_flags = IOMMU_FAULT_WRITE;
+
+	rcu_read_lock();
+	vdev = xa_load(&viommu->endpoints, endpoint);
+	if (vdev && vdev->vdomain && (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)) {
+		domain = &vdev->vdomain->domain;
+		report_iommu_fault(domain, vdev->dev, address, fault_flags);
+		rcu_read_unlock();
+	} else if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS) {
+		rcu_read_unlock();
+		dev_err_ratelimited(viommu->dev,
+				    "%s fault from EP %u at %#llx [%s%s%s]\n",
 				    reason_str, endpoint, address,
 				    flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : "",
 				    flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : "",
 				    flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : "");
-	else
+	} else {
+		rcu_read_unlock();
 		dev_err_ratelimited(viommu->dev, "%s fault from EP %u\n",
 				    reason_str, endpoint);
+	}
 	return 0;
 }
 
@@ -1037,15 +1055,33 @@
 	INIT_LIST_HEAD(&vdev->resv_regions);
 	dev_iommu_priv_set(dev, vdev);
 
+	for (ret = 0; ret < fwspec->num_ids; ret++) {
+		int err = xa_insert(&viommu->endpoints, fwspec->ids[ret], vdev,
+				   GFP_KERNEL);
+		if (err) {
+			while (ret--)
+				xa_erase(&viommu->endpoints, fwspec->ids[ret]);
+			ret = err;
+			goto err_free_dev;
+		}
+	}
+
 	if (viommu->probe_size) {
 		/* Get additional information for this endpoint */
 		ret = viommu_probe_endpoint(viommu, dev);
 		if (ret)
-			goto err_free_dev;
+			goto err_unreg;
 	}
 
 	return &viommu->iommu;
 
+err_unreg:
+	{
+		int i;
+
+		for (i = 0; i < fwspec->num_ids; i++)
+			xa_erase(&viommu->endpoints, fwspec->ids[i]);
+	}
 err_free_dev:
 	iommu_put_resv_regions(dev, &vdev->resv_regions);
 	kfree(vdev);
@@ -1056,8 +1092,12 @@
 static void viommu_release_device(struct device *dev)
 {
 	struct viommu_endpoint *vdev = dev_iommu_priv_get(dev);
+	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+	int i;
 
 	viommu_detach_dev(vdev);
+	for (i = 0; i < fwspec->num_ids; i++)
+		xa_erase(&vdev->viommu->endpoints, fwspec->ids[i]);
 	iommu_put_resv_regions(dev, &vdev->resv_regions);
 	kfree(vdev);
 }
@@ -1167,6 +1207,7 @@
 
 	spin_lock_init(&viommu->request_lock);
 	ida_init(&viommu->domain_ids);
+	xa_init(&viommu->endpoints);
 	viommu->dev = dev;
 	viommu->vdev = vdev;
 	INIT_LIST_HEAD(&viommu->requests);
@@ -1261,6 +1302,7 @@
 	virtio_reset_device(vdev);
 	vdev->config->del_vqs(vdev);
 
+	xa_destroy(&viommu->endpoints);
 	dev_info(&vdev->dev, "device removed\n");
 }
 


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-14 11:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13  1:04 [PATCH] iommu/virtio: Report faults via report_iommu_fault() weimin xiong
2026-07-13  2:07 ` Baolu Lu
2026-07-13  8:02   ` Xiong Weimin
2026-07-13 11:45     ` Jason Gunthorpe
2026-07-14  1:52       ` Xiong Weimin
2026-07-14  2:02 ` [PATCH v2] " weimin xiong
2026-07-14 11:36   ` Jason Gunthorpe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.