[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251202230303.1017519-2-skhawaja@google.com>
Date: Tue, 2 Dec 2025 23:02:31 +0000
From: Samiullah Khawaja <skhawaja@...gle.com>
To: David Woodhouse <dwmw2@...radead.org>, Lu Baolu <baolu.lu@...ux.intel.com>,
Joerg Roedel <joro@...tes.org>, Will Deacon <will@...nel.org>,
Pasha Tatashin <pasha.tatashin@...een.com>, Jason Gunthorpe <jgg@...pe.ca>, iommu@...ts.linux.dev
Cc: YiFei Zhu <zhuyifei@...gle.com>, Robin Murphy <robin.murphy@....com>,
Pratyush Yadav <pratyush@...nel.org>, Samiullah Khawaja <skhawaja@...gle.com>,
Kevin Tian <kevin.tian@...el.com>, Alex Williamson <alex@...zbot.org>, linux-kernel@...r.kernel.org,
Saeed Mahameed <saeedm@...dia.com>, Adithya Jayachandran <ajayachandra@...dia.com>,
Parav Pandit <parav@...dia.com>, Leon Romanovsky <leonro@...dia.com>, William Tu <witu@...dia.com>,
Vipin Sharma <vipinsh@...gle.com>, dmatlack@...gle.com, Chris Li <chrisl@...nel.org>,
praan@...gle.com
Subject: [RFC PATCH v2 01/32] iommufd: Allow HWPTs to have a NULL IOAS
From: YiFei Zhu <zhuyifei@...gle.com>
Normally HWPTs are created with a parent IOAS to allow the mappings
to be modified. For liveupdate we want an immutable HWPT upon restore,
so no IOAS is needed. This patch prepares iommufd so it would not
crash on a NULL hwpt_paging->ioas.
Signed-off-by: YiFei Zhu <zhuyifei@...gle.com>
---
drivers/iommu/iommufd/device.c | 11 ++++++++---
drivers/iommu/iommufd/hw_pagetable.c | 15 +++++++++++++--
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 4c842368289f..ba4d9c3cfa8b 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -418,6 +418,7 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
lockdep_assert_held(&igroup->lock);
+ /* unreachable if !hwpt_paging->ioas */
rc = iopt_table_enforce_dev_resv_regions(&hwpt_paging->ioas->iopt,
idev->dev,
&igroup->sw_msi_start);
@@ -603,7 +604,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev, ioasid_t pasid)
{
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
- bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID;
+ bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID && hwpt_paging->ioas;
struct iommufd_group *igroup = idev->igroup;
struct iommufd_hw_pagetable *old_hwpt;
struct iommufd_attach *attach;
@@ -707,7 +708,7 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid)
xa_erase(&igroup->pasid_attach, pasid);
kfree(attach);
}
- if (hwpt_paging && pasid == IOMMU_NO_PASID)
+ if (hwpt_paging && pasid == IOMMU_NO_PASID && hwpt_paging->ioas)
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
mutex_unlock(&igroup->lock);
@@ -739,6 +740,9 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
lockdep_assert_held(&igroup->lock);
+ if (!hwpt_paging->ioas)
+ return;
+
attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID);
xa_for_each(&attach->device_array, index, cur)
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, cur->dev);
@@ -756,6 +760,7 @@ iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
lockdep_assert_held(&igroup->lock);
+ /* unreachable if !hwpt_paging->ioas */
attach = xa_load(&igroup->pasid_attach, IOMMU_NO_PASID);
old_hwpt_paging = find_hwpt_paging(attach->hwpt);
if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas) {
@@ -782,7 +787,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
struct iommufd_hw_pagetable *hwpt)
{
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
- bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID;
+ bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID && hwpt_paging->ioas;
struct iommufd_hwpt_paging *old_hwpt_paging;
struct iommufd_group *igroup = idev->igroup;
struct iommufd_hw_pagetable *old_hwpt;
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index fe789c2dc0c9..78d2130e0061 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -23,6 +23,7 @@ void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)
container_of(obj, struct iommufd_hwpt_paging, common.obj);
if (!list_empty(&hwpt_paging->hwpt_item)) {
+ /* unreachable if !hwpt_paging->ioas */
mutex_lock(&hwpt_paging->ioas->mutex);
list_del(&hwpt_paging->hwpt_item);
mutex_unlock(&hwpt_paging->ioas->mutex);
@@ -32,7 +33,9 @@ void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)
}
__iommufd_hwpt_destroy(&hwpt_paging->common);
- refcount_dec(&hwpt_paging->ioas->obj.users);
+
+ if (hwpt_paging->ioas)
+ refcount_dec(&hwpt_paging->ioas->obj.users);
}
void iommufd_hwpt_paging_abort(struct iommufd_object *obj)
@@ -41,9 +44,11 @@ void iommufd_hwpt_paging_abort(struct iommufd_object *obj)
container_of(obj, struct iommufd_hwpt_paging, common.obj);
/* The ioas->mutex must be held until finalize is called. */
- lockdep_assert_held(&hwpt_paging->ioas->mutex);
+ if (hwpt_paging->ioas)
+ lockdep_assert_held(&hwpt_paging->ioas->mutex);
if (!list_empty(&hwpt_paging->hwpt_item)) {
+ /* unreachable if !hwpt_paging->ioas */
list_del_init(&hwpt_paging->hwpt_item);
iopt_table_remove_domain(&hwpt_paging->ioas->iopt,
hwpt_paging->common.domain);
@@ -457,6 +462,9 @@ int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd)
return PTR_ERR(hwpt_paging);
ioas = hwpt_paging->ioas;
+ if (!ioas)
+ return -EINVAL;
+
enable = cmd->flags & IOMMU_HWPT_DIRTY_TRACKING_ENABLE;
rc = iopt_set_dirty_tracking(&ioas->iopt, hwpt_paging->common.domain,
@@ -482,6 +490,9 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd)
return PTR_ERR(hwpt_paging);
ioas = hwpt_paging->ioas;
+ if (!ioas)
+ return -EINVAL;
+
rc = iopt_read_and_clear_dirty_data(
&ioas->iopt, hwpt_paging->common.domain, cmd->flags, cmd);
--
2.52.0.158.g65b55ccf14-goog
Powered by blists - more mailing lists