From: Jason Gunthorpe <jgg@nvidia.com>
To: Michael Shavit <mshavit@google.com>
Cc: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, baolu.lu@linux.intel.com,
will@kernel.org, jean-philippe@linaro.org, robin.murphy@arm.com,
nicolinc@nvidia.com
Subject: Re: [PATCH v5 4/6] iommu/arm-smmu-v3: Implement set_dev_pasid
Date: Thu, 3 Aug 2023 14:52:26 -0300 [thread overview]
Message-ID: <ZMvpWoslIZNiLNQp@nvidia.com> (raw)
In-Reply-To: <20230803181225.v5.4.I4ba46c0f7d599f43094d6ba1113c0b4fe49bd908@changeid>
On Thu, Aug 03, 2023 at 06:12:24PM +0800, Michael Shavit wrote:
> @@ -2448,21 +2476,17 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> return -EBUSY;
> }
>
> - arm_smmu_detach_dev(master);
> -
> - mutex_lock(&smmu_domain->init_mutex);
> -
> - if (!smmu_domain->smmu) {
> - smmu_domain->smmu = smmu;
> - ret = arm_smmu_domain_finalise(domain, master);
> - if (ret)
> - smmu_domain->smmu = NULL;
> - } else if (smmu_domain->smmu != smmu)
> - ret = -EINVAL;
> + /*
> + * Attaching a bypass or stage 2 domain would break any domains attached
> + * with pasid. Attaching an S1 domain should be feasible but requires
> + * more complicated logic to handle.
> + */
> + if (arm_smmu_master_has_pasid_domains(master)) {
> + dev_err(dev, "cannot attach - domain attached with pasid\n");
> + return -EBUSY;
> + }
Basically don't you just call set_dev_pased(pasid = 0) and it will do
that logic?
> +static int arm_smmu_set_dev_pasid(struct iommu_domain *domain,
> + struct device *dev, ioasid_t pasid)
> +{
> + int ret = 0;
> + unsigned long flags;
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> + struct arm_smmu_device *smmu;
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> + struct arm_smmu_attached_domain *attached_domain;
> + struct arm_smmu_master *master;
> +
> + if (!fwspec)
> + return -ENOENT;
fwspec drivers always have fwspecs, they don't need to check this.
> +
> + master = dev_iommu_priv_get(dev);
> + smmu = master->smmu;
> +
> + ret = arm_smmu_prepare_domain_for_smmu(smmu, smmu_domain, master);
> + if (ret)
> + return ret;
> +
> + if (pasid == 0) {
> + dev_err(dev, "pasid 0 is reserved for the device's primary domain\n");
> + return -ENODEV;
> + }
> +
> + if (smmu_domain->stage != ARM_SMMU_DOMAIN_S1) {
> + dev_err(dev, "set_dev_pasid only supports stage 1 domains\n");
don't print messages, iommufd can trigger these paths from userspace.
> @@ -2738,6 +2828,15 @@ static void arm_smmu_release_device(struct device *dev)
>
> if (WARN_ON(arm_smmu_master_sva_enabled(master)))
> iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
> + if (WARN_ON(master->nr_attached_pasid_domains != 0)) {
> + /*
> + * TODO: Do we need to handle this case?
> + * This requires a mechanism to obtain all the pasid domains
> + * that this master is attached to so that we can clean up the
> + * domain's attached_domain list.
> + */
> + }
Unnecessary, the core code should handle this, add a patch that does this:
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 5b5cf74edc7e53..57cac1ffba1cfe 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -438,9 +438,16 @@ static void iommu_deinit_device(struct device *dev)
{
struct iommu_group *group = dev->iommu_group;
const struct iommu_ops *ops = dev_iommu_ops(dev);
+ struct iommu_domain *{pasid_domain;
+ unsigned long pasid;
lockdep_assert_held(&group->mutex);
+ xa_for_each(&group->pasid_array, pasid, pasid_domain) {
+ __iommu_remove_group_pasid(pasid);
+ xa_erase(&group->pasid_array, pasid);
+ }
+
iommu_device_unlink(dev->iommu->iommu_dev, dev);
/*
> @@ -2874,12 +2973,36 @@ static int arm_smmu_def_domain_type(struct device *dev)
> static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
> {
> struct iommu_domain *domain;
> + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> + struct arm_smmu_domain *smmu_domain;
> + struct arm_smmu_attached_domain *attached_domain;
> + unsigned long flags;
>
> - domain = iommu_get_domain_for_dev_pasid(dev, pasid, IOMMU_DOMAIN_SVA);
> + if (!master || pasid == 0)
> + return;
> +
> + domain = iommu_get_domain_for_dev_pasid(dev, pasid, 0);
> if (WARN_ON(IS_ERR(domain)) || !domain)
> return;
I feel like we have made a mistake here to not pass in the current
domain from the core code, it already knows what the domain was..
> + if (domain->type == IOMMU_DOMAIN_SVA)
> + return arm_smmu_sva_remove_dev_pasid(domain, dev, pasid);
Yuk.
Jason
WARNING: multiple messages have this Message-ID (diff)
From: Jason Gunthorpe <jgg@nvidia.com>
To: Michael Shavit <mshavit@google.com>
Cc: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, baolu.lu@linux.intel.com,
will@kernel.org, jean-philippe@linaro.org, robin.murphy@arm.com,
nicolinc@nvidia.com
Subject: Re: [PATCH v5 4/6] iommu/arm-smmu-v3: Implement set_dev_pasid
Date: Thu, 3 Aug 2023 14:52:26 -0300 [thread overview]
Message-ID: <ZMvpWoslIZNiLNQp@nvidia.com> (raw)
In-Reply-To: <20230803181225.v5.4.I4ba46c0f7d599f43094d6ba1113c0b4fe49bd908@changeid>
On Thu, Aug 03, 2023 at 06:12:24PM +0800, Michael Shavit wrote:
> @@ -2448,21 +2476,17 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> return -EBUSY;
> }
>
> - arm_smmu_detach_dev(master);
> -
> - mutex_lock(&smmu_domain->init_mutex);
> -
> - if (!smmu_domain->smmu) {
> - smmu_domain->smmu = smmu;
> - ret = arm_smmu_domain_finalise(domain, master);
> - if (ret)
> - smmu_domain->smmu = NULL;
> - } else if (smmu_domain->smmu != smmu)
> - ret = -EINVAL;
> + /*
> + * Attaching a bypass or stage 2 domain would break any domains attached
> + * with pasid. Attaching an S1 domain should be feasible but requires
> + * more complicated logic to handle.
> + */
> + if (arm_smmu_master_has_pasid_domains(master)) {
> + dev_err(dev, "cannot attach - domain attached with pasid\n");
> + return -EBUSY;
> + }
Basically don't you just call set_dev_pased(pasid = 0) and it will do
that logic?
> +static int arm_smmu_set_dev_pasid(struct iommu_domain *domain,
> + struct device *dev, ioasid_t pasid)
> +{
> + int ret = 0;
> + unsigned long flags;
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> + struct arm_smmu_device *smmu;
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> + struct arm_smmu_attached_domain *attached_domain;
> + struct arm_smmu_master *master;
> +
> + if (!fwspec)
> + return -ENOENT;
fwspec drivers always have fwspecs, they don't need to check this.
> +
> + master = dev_iommu_priv_get(dev);
> + smmu = master->smmu;
> +
> + ret = arm_smmu_prepare_domain_for_smmu(smmu, smmu_domain, master);
> + if (ret)
> + return ret;
> +
> + if (pasid == 0) {
> + dev_err(dev, "pasid 0 is reserved for the device's primary domain\n");
> + return -ENODEV;
> + }
> +
> + if (smmu_domain->stage != ARM_SMMU_DOMAIN_S1) {
> + dev_err(dev, "set_dev_pasid only supports stage 1 domains\n");
don't print messages, iommufd can trigger these paths from userspace.
> @@ -2738,6 +2828,15 @@ static void arm_smmu_release_device(struct device *dev)
>
> if (WARN_ON(arm_smmu_master_sva_enabled(master)))
> iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
> + if (WARN_ON(master->nr_attached_pasid_domains != 0)) {
> + /*
> + * TODO: Do we need to handle this case?
> + * This requires a mechanism to obtain all the pasid domains
> + * that this master is attached to so that we can clean up the
> + * domain's attached_domain list.
> + */
> + }
Unnecessary, the core code should handle this, add a patch that does this:
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 5b5cf74edc7e53..57cac1ffba1cfe 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -438,9 +438,16 @@ static void iommu_deinit_device(struct device *dev)
{
struct iommu_group *group = dev->iommu_group;
const struct iommu_ops *ops = dev_iommu_ops(dev);
+ struct iommu_domain *{pasid_domain;
+ unsigned long pasid;
lockdep_assert_held(&group->mutex);
+ xa_for_each(&group->pasid_array, pasid, pasid_domain) {
+ __iommu_remove_group_pasid(pasid);
+ xa_erase(&group->pasid_array, pasid);
+ }
+
iommu_device_unlink(dev->iommu->iommu_dev, dev);
/*
> @@ -2874,12 +2973,36 @@ static int arm_smmu_def_domain_type(struct device *dev)
> static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
> {
> struct iommu_domain *domain;
> + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> + struct arm_smmu_domain *smmu_domain;
> + struct arm_smmu_attached_domain *attached_domain;
> + unsigned long flags;
>
> - domain = iommu_get_domain_for_dev_pasid(dev, pasid, IOMMU_DOMAIN_SVA);
> + if (!master || pasid == 0)
> + return;
> +
> + domain = iommu_get_domain_for_dev_pasid(dev, pasid, 0);
> if (WARN_ON(IS_ERR(domain)) || !domain)
> return;
I feel like we have made a mistake here to not pass in the current
domain from the core code, it already knows what the domain was..
> + if (domain->type == IOMMU_DOMAIN_SVA)
> + return arm_smmu_sva_remove_dev_pasid(domain, dev, pasid);
Yuk.
Jason
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-08-03 17:52 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-03 10:12 [PATCH v5 0/6] Add PASID support to SMMUv3 unmanaged domains Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 10:12 ` [PATCH v5 1/6] iommu/arm-smmu-v3: Simplify arm_smmu_enable_ats Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 10:12 ` [PATCH v5 2/6] iommu/arm-smmu-v3: Keep track of attached ssids Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 15:42 ` Jason Gunthorpe
2023-08-03 15:42 ` Jason Gunthorpe
2023-08-03 16:32 ` Michael Shavit
2023-08-03 16:32 ` Michael Shavit
2023-08-03 17:44 ` Jason Gunthorpe
2023-08-03 17:44 ` Jason Gunthorpe
2023-08-03 10:12 ` [PATCH v5 3/6] iommu/arm-smmu-v3: Add helper for atc invalidation Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 10:12 ` [PATCH v5 4/6] iommu/arm-smmu-v3: Implement set_dev_pasid Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 17:52 ` Jason Gunthorpe [this message]
2023-08-03 17:52 ` Jason Gunthorpe
2023-08-03 10:12 ` [PATCH v5 5/6] iommu/arm-smmu-v3: Free pasid domains on iommu release Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 10:17 ` Michael Shavit
2023-08-03 10:17 ` Michael Shavit
2023-08-03 15:20 ` Jason Gunthorpe
2023-08-03 15:20 ` Jason Gunthorpe
2023-08-03 10:12 ` [PATCH v5 6/6] iommu/arm-smmu-v3: Cleanup arm_smmu_domain_finalise Michael Shavit
2023-08-03 10:12 ` Michael Shavit
2023-08-03 10:15 ` Michael Shavit
2023-08-03 10:15 ` Michael Shavit
2023-08-03 15:19 ` Jason Gunthorpe
2023-08-03 15:19 ` Jason Gunthorpe
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=ZMvpWoslIZNiLNQp@nvidia.com \
--to=jgg@nvidia.com \
--cc=baolu.lu@linux.intel.com \
--cc=iommu@lists.linux.dev \
--cc=jean-philippe@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mshavit@google.com \
--cc=nicolinc@nvidia.com \
--cc=robin.murphy@arm.com \
--cc=will@kernel.org \
/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 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.