From: Lu Baolu <baolu.lu@linux.intel.com>
To: Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jean-Philippe Brucker <jean-philippe@linaro.org>,
Nicolin Chen <nicolinc@nvidia.com>, Yi Liu <yi.l.liu@intel.com>,
Jacob Pan <jacob.jun.pan@linux.intel.com>,
Joel Granados <j.granados@samsung.com>
Cc: iommu@lists.linux.dev, virtualization@lists.linux-foundation.org,
linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH v3 2/8] iommu/sva: Use iopf domain attach/detach interface
Date: Mon, 22 Jan 2024 15:38:57 +0800 [thread overview]
Message-ID: <20240122073903.24406-3-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20240122073903.24406-1-baolu.lu@linux.intel.com>
The iommu sva implementation relies on iopf handling. Allocate an
attachment cookie and use the iopf domain attach/detach interface.
The SVA domain is guaranteed to be released after all outstanding
page faults are handled.
In the fault delivering path, the attachment cookie is retrieved,
instead of the domain. This ensures that the page fault is forwarded
only if an iopf-capable domain is attached, and the domain will only
be released after all outstanding faults are handled.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
include/linux/iommu.h | 2 +-
drivers/iommu/io-pgfault.c | 59 +++++++++++++++++++-------------------
drivers/iommu/iommu-sva.c | 48 ++++++++++++++++++++++++-------
3 files changed, 68 insertions(+), 41 deletions(-)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 6d85be23952a..511dc7b4bdb2 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -142,9 +142,9 @@ struct iopf_group {
/* list node for iommu_fault_param::faults */
struct list_head pending_node;
struct work_struct work;
- struct iommu_domain *domain;
/* The device's fault data parameter. */
struct iommu_fault_param *fault_param;
+ struct iopf_attach_cookie *cookie;
};
/**
diff --git a/drivers/iommu/io-pgfault.c b/drivers/iommu/io-pgfault.c
index f7ce41573799..2567d8c04e46 100644
--- a/drivers/iommu/io-pgfault.c
+++ b/drivers/iommu/io-pgfault.c
@@ -40,7 +40,7 @@ static void iopf_put_dev_fault_param(struct iommu_fault_param *fault_param)
}
/* Get the domain attachment cookie for pasid of a device. */
-static struct iopf_attach_cookie __maybe_unused *
+static struct iopf_attach_cookie *
iopf_pasid_cookie_get(struct device *dev, ioasid_t pasid)
{
struct iommu_fault_param *iopf_param = iopf_get_dev_fault_param(dev);
@@ -147,6 +147,7 @@ static void __iopf_free_group(struct iopf_group *group)
/* Pair with iommu_report_device_fault(). */
iopf_put_dev_fault_param(group->fault_param);
+ iopf_pasid_cookie_put(group->cookie);
}
void iopf_free_group(struct iopf_group *group)
@@ -156,30 +157,6 @@ void iopf_free_group(struct iopf_group *group)
}
EXPORT_SYMBOL_GPL(iopf_free_group);
-static struct iommu_domain *get_domain_for_iopf(struct device *dev,
- struct iommu_fault *fault)
-{
- struct iommu_domain *domain;
-
- if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID) {
- domain = iommu_get_domain_for_dev_pasid(dev, fault->prm.pasid, 0);
- if (IS_ERR(domain))
- domain = NULL;
- } else {
- domain = iommu_get_domain_for_dev(dev);
- }
-
- if (!domain || !domain->iopf_handler) {
- dev_warn_ratelimited(dev,
- "iopf (pasid %d) without domain attached or handler installed\n",
- fault->prm.pasid);
-
- return NULL;
- }
-
- return domain;
-}
-
/* Non-last request of a group. Postpone until the last one. */
static int report_partial_fault(struct iommu_fault_param *fault_param,
struct iommu_fault *fault)
@@ -199,10 +176,20 @@ static int report_partial_fault(struct iommu_fault_param *fault_param,
return 0;
}
+static ioasid_t fault_to_pasid(struct iommu_fault *fault)
+{
+ if (fault->prm.flags & IOMMU_FAULT_PAGE_REQUEST_PASID_VALID)
+ return fault->prm.pasid;
+
+ return IOMMU_NO_PASID;
+}
+
static struct iopf_group *iopf_group_alloc(struct iommu_fault_param *iopf_param,
struct iopf_fault *evt,
struct iopf_group *abort_group)
{
+ ioasid_t pasid = fault_to_pasid(&evt->fault);
+ struct iopf_attach_cookie *cookie;
struct iopf_fault *iopf, *next;
struct iopf_group *group;
@@ -215,7 +202,23 @@ static struct iopf_group *iopf_group_alloc(struct iommu_fault_param *iopf_param,
group = abort_group;
}
+ cookie = iopf_pasid_cookie_get(iopf_param->dev, pasid);
+ if (!cookie && pasid != IOMMU_NO_PASID)
+ cookie = iopf_pasid_cookie_get(iopf_param->dev, IOMMU_NO_PASID);
+ if (IS_ERR(cookie) || !cookie) {
+ /*
+ * The PASID of this device was not attached by an I/O-capable
+ * domain. Ask the caller to abort handling of this fault.
+ * Otherwise, the reference count will be switched to the new
+ * iopf group and will be released in iopf_free_group().
+ */
+ kfree(group);
+ group = abort_group;
+ cookie = NULL;
+ }
+
group->fault_param = iopf_param;
+ group->cookie = cookie;
group->last_fault.fault = evt->fault;
INIT_LIST_HEAD(&group->faults);
INIT_LIST_HEAD(&group->pending_node);
@@ -305,15 +308,11 @@ void iommu_report_device_fault(struct device *dev, struct iopf_fault *evt)
if (group == &abort_group)
goto err_abort;
- group->domain = get_domain_for_iopf(dev, fault);
- if (!group->domain)
- goto err_abort;
-
/*
* On success iopf_handler must call iopf_group_response() and
* iopf_free_group()
*/
- if (group->domain->iopf_handler(group))
+ if (group->cookie->domain->iopf_handler(group))
goto err_abort;
return;
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
index b51995b4fe90..fff3ee1ee9ce 100644
--- a/drivers/iommu/iommu-sva.c
+++ b/drivers/iommu/iommu-sva.c
@@ -50,6 +50,39 @@ static struct iommu_mm_data *iommu_alloc_mm_data(struct mm_struct *mm, struct de
return iommu_mm;
}
+static void release_attach_cookie(struct iopf_attach_cookie *cookie)
+{
+ struct iommu_domain *domain = cookie->domain;
+
+ mutex_lock(&iommu_sva_lock);
+ if (--domain->users == 0) {
+ list_del(&domain->next);
+ iommu_domain_free(domain);
+ }
+ mutex_unlock(&iommu_sva_lock);
+
+ kfree(cookie);
+}
+
+static int sva_attach_device_pasid(struct iommu_domain *domain,
+ struct device *dev, ioasid_t pasid)
+{
+ struct iopf_attach_cookie *cookie;
+ int ret;
+
+ cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
+ if (!cookie)
+ return -ENOMEM;
+
+ cookie->release = release_attach_cookie;
+
+ ret = iopf_domain_attach(domain, dev, pasid, cookie);
+ if (ret)
+ kfree(cookie);
+
+ return ret;
+}
+
/**
* iommu_sva_bind_device() - Bind a process address space to a device
* @dev: the device
@@ -90,7 +123,7 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
/* Search for an existing domain. */
list_for_each_entry(domain, &mm->iommu_mm->sva_domains, next) {
- ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
+ ret = sva_attach_device_pasid(domain, dev, iommu_mm->pasid);
if (!ret) {
domain->users++;
goto out;
@@ -104,7 +137,7 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
goto out_free_handle;
}
- ret = iommu_attach_device_pasid(domain, dev, iommu_mm->pasid);
+ ret = sva_attach_device_pasid(domain, dev, iommu_mm->pasid);
if (ret)
goto out_free_domain;
domain->users = 1;
@@ -140,13 +173,7 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
struct iommu_mm_data *iommu_mm = domain->mm->iommu_mm;
struct device *dev = handle->dev;
- mutex_lock(&iommu_sva_lock);
- iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
- if (--domain->users == 0) {
- list_del(&domain->next);
- iommu_domain_free(domain);
- }
- mutex_unlock(&iommu_sva_lock);
+ iopf_domain_detach(domain, dev, iommu_mm->pasid);
kfree(handle);
}
EXPORT_SYMBOL_GPL(iommu_sva_unbind_device);
@@ -242,7 +269,8 @@ static void iommu_sva_handle_iopf(struct work_struct *work)
if (status != IOMMU_PAGE_RESP_SUCCESS)
break;
- status = iommu_sva_handle_mm(&iopf->fault, group->domain->mm);
+ status = iommu_sva_handle_mm(&iopf->fault,
+ group->cookie->domain->mm);
}
iopf_group_response(group, status);
--
2.34.1
next prev parent reply other threads:[~2024-01-22 7:44 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-22 7:38 [PATCH v3 0/8] IOMMUFD: Deliver IO page faults to user space Lu Baolu
2024-01-22 7:38 ` [PATCH v3 1/8] iommu: Add iopf domain attach/detach/replace interface Lu Baolu
2024-02-07 8:11 ` Tian, Kevin
2024-02-21 5:52 ` Baolu Lu
2024-02-21 6:49 ` Tian, Kevin
2024-02-21 7:21 ` Baolu Lu
2024-02-21 7:22 ` Tian, Kevin
2024-01-22 7:38 ` Lu Baolu [this message]
2024-03-08 17:46 ` [PATCH v3 2/8] iommu/sva: Use iopf domain attach/detach interface Jason Gunthorpe
2024-03-14 7:41 ` Baolu Lu
2024-03-22 16:59 ` Jason Gunthorpe
2024-03-25 3:52 ` Baolu Lu
2024-01-22 7:38 ` [PATCH v3 3/8] iommufd: Add fault and response message definitions Lu Baolu
2024-03-08 17:50 ` Jason Gunthorpe
2024-03-14 13:41 ` Baolu Lu
2024-03-22 17:04 ` Jason Gunthorpe
2024-03-25 3:57 ` Baolu Lu
2024-01-22 7:38 ` [PATCH v3 4/8] iommufd: Add iommufd fault object Lu Baolu
2024-03-08 18:03 ` Jason Gunthorpe
2024-03-15 1:46 ` Baolu Lu
2024-03-22 17:09 ` Jason Gunthorpe
2024-03-25 5:01 ` Baolu Lu
2024-03-20 16:18 ` Shameerali Kolothum Thodi
2024-03-22 17:22 ` Jason Gunthorpe
2024-03-25 3:26 ` Baolu Lu
2024-03-25 4:02 ` Baolu Lu
2024-01-22 7:39 ` [PATCH v3 5/8] iommufd: Associate fault object with iommufd_hw_pgtable Lu Baolu
2024-02-07 8:14 ` Tian, Kevin
2024-02-21 6:06 ` Baolu Lu
2024-03-02 2:36 ` Zhangfei Gao
2024-03-06 15:15 ` Zhangfei Gao
2024-03-06 16:01 ` Jason Gunthorpe
2024-03-07 1:54 ` Baolu Lu
2024-03-08 17:19 ` Jason Gunthorpe
2024-03-08 19:05 ` Jason Gunthorpe
2024-03-15 1:16 ` Baolu Lu
2024-03-22 17:06 ` Jason Gunthorpe
2024-03-25 4:59 ` Baolu Lu
2024-01-22 7:39 ` [PATCH v3 6/8] iommufd: IOPF-capable hw page table attach/detach/replace Lu Baolu
2024-02-20 13:57 ` Joel Granados
2024-02-21 6:15 ` Baolu Lu
2024-01-22 7:39 ` [PATCH v3 7/8] iommufd/selftest: Add IOPF support for mock device Lu Baolu
2024-01-22 7:39 ` [PATCH v3 8/8] iommufd/selftest: Add coverage for IOPF test Lu Baolu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240122073903.24406-3-baolu.lu@linux.intel.com \
--to=baolu.lu@linux.intel.com \
--cc=iommu@lists.linux.dev \
--cc=j.granados@samsung.com \
--cc=jacob.jun.pan@linux.intel.com \
--cc=jean-philippe@linaro.org \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nicolinc@nvidia.com \
--cc=robin.murphy@arm.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=will@kernel.org \
--cc=yi.l.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox