* [PATCH v4 01/12] iommu: Refactor __iommu_domain_alloc()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
@ 2024-10-23 10:41 ` Vasant Hegde
2024-10-23 10:41 ` [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags() Vasant Hegde
` (10 subsequent siblings)
11 siblings, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:41 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
From: Jason Gunthorpe <jgg@ziepe.ca>
Following patch will introduce iommu_paging_domain_alloc_flags() API.
Hence move domain init code to separate function so that it can be
reused.
Also move iommu_get_dma_cookie() setup iommu_setup_default_domain() as
it is required in DMA API mode only.
Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
[Split the patch and added description - Vasant]
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/iommu.c | 46 +++++++++++++++++++++++--------------------
1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 83c8e617a2c5..811748bec4b0 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1934,6 +1934,22 @@ void iommu_set_fault_handler(struct iommu_domain *domain,
}
EXPORT_SYMBOL_GPL(iommu_set_fault_handler);
+static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
+ const struct iommu_ops *ops)
+{
+ domain->type = type;
+ domain->owner = ops;
+ if (!domain->ops)
+ domain->ops = ops->default_domain_ops;
+
+ /*
+ * If not already set, assume all sizes by default; the driver
+ * may override this later
+ */
+ if (!domain->pgsize_bitmap)
+ domain->pgsize_bitmap = ops->pgsize_bitmap;
+}
+
static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
struct device *dev,
unsigned int type)
@@ -1962,27 +1978,7 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
if (!domain)
return ERR_PTR(-ENOMEM);
- domain->type = type;
- domain->owner = ops;
- /*
- * If not already set, assume all sizes by default; the driver
- * may override this later
- */
- if (!domain->pgsize_bitmap)
- domain->pgsize_bitmap = ops->pgsize_bitmap;
-
- if (!domain->ops)
- domain->ops = ops->default_domain_ops;
-
- if (iommu_is_dma_domain(domain)) {
- int rc;
-
- rc = iommu_get_dma_cookie(domain);
- if (rc) {
- iommu_domain_free(domain);
- return ERR_PTR(rc);
- }
- }
+ iommu_domain_init(domain, type, ops);
return domain;
}
@@ -2965,6 +2961,14 @@ static int iommu_setup_default_domain(struct iommu_group *group,
if (group->default_domain == dom)
return 0;
+ if (iommu_is_dma_domain(dom)) {
+ ret = iommu_get_dma_cookie(dom);
+ if (ret) {
+ iommu_domain_free(dom);
+ return ret;
+ }
+ }
+
/*
* IOMMU_RESV_DIRECT and IOMMU_RESV_DIRECT_RELAXABLE regions must be
* mapped before their device is attached, in order to guarantee
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
2024-10-23 10:41 ` [PATCH v4 01/12] iommu: Refactor __iommu_domain_alloc() Vasant Hegde
@ 2024-10-23 10:41 ` Vasant Hegde
2024-10-23 14:26 ` Robin Murphy
2024-10-25 8:22 ` Tian, Kevin
2024-10-23 10:41 ` [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain Vasant Hegde
` (9 subsequent siblings)
11 siblings, 2 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:41 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
From: Jason Gunthorpe <jgg@ziepe.ca>
Currently drivers calls iommu_paging_domain_alloc(dev) to get an
UNMANAGED domain. This is not sufficient to support PASID with
UNMANAGED domain as some HW like AMD requires certain page table type
to support PASIDs.
Also the domain_alloc_paging op only passes device as param for domain
allocation. This is not sufficient for AMD driver to decide the right
page table.
Instead of extending ops->domain_alloc_paging() it was decided to
enhance ops->domain_alloc_user() so that caller can pass various
additional flags.
Hence add iommu_paging_domain_alloc_flags() API which takes flags as
parameter. Caller can pass additional parameter to indicate type of
domain required, etc. iommu_paging_domain_alloc_flags() internally calls
appropriate callback function to allocate a domain.
Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
[Added description - Vasant]
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Yi Liu <yi.l.liu@intel.com>
---
drivers/iommu/iommu.c | 32 +++++++++++++++++++++++++++-----
include/linux/iommu.h | 14 +++++++++++---
2 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 811748bec4b0..69fc0b9ba31a 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2027,20 +2027,42 @@ struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus)
EXPORT_SYMBOL_GPL(iommu_domain_alloc);
/**
- * iommu_paging_domain_alloc() - Allocate a paging domain
+ * iommu_paging_domain_alloc_flags() - Allocate a paging domain
* @dev: device for which the domain is allocated
+ * @flags: Enum of iommufd_hwpt_alloc_flags
*
* Allocate a paging domain which will be managed by a kernel driver. Return
- * allocated domain if successful, or a ERR pointer for failure.
+ * allocated domain if successful, or an ERR pointer for failure.
*/
-struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
+struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int flags)
{
+ const struct iommu_ops *ops;
+ struct iommu_domain *domain;
+
if (!dev_has_iommu(dev))
return ERR_PTR(-ENODEV);
- return __iommu_domain_alloc(dev_iommu_ops(dev), dev, IOMMU_DOMAIN_UNMANAGED);
+ ops = dev_iommu_ops(dev);
+
+ if (ops->domain_alloc_paging && !flags)
+ domain = ops->domain_alloc_paging(dev);
+ else if (ops->domain_alloc_user)
+ domain = ops->domain_alloc_user(dev, flags, NULL, NULL);
+ else if (ops->domain_alloc && !flags)
+ domain = ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
+ else
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (IS_ERR(domain))
+ return domain;
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_domain_init(domain, IOMMU_DOMAIN_UNMANAGED, ops);
+ return domain;
}
-EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc);
+EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);
void iommu_domain_free(struct iommu_domain *domain)
{
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index bd722f473635..42243183e81d 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -511,8 +511,6 @@ static inline int __iommu_copy_struct_from_user_array(
* the caller iommu_domain_alloc() returns.
* @domain_alloc_user: Allocate an iommu domain corresponding to the input
* parameters as defined in include/uapi/linux/iommufd.h.
- * Unlike @domain_alloc, it is called only by IOMMUFD and
- * must fully initialize the new domain before return.
* Upon success, if the @user_data is valid and the @parent
* points to a kernel-managed domain, the new domain must be
* IOMMU_DOMAIN_NESTED type; otherwise, the @parent must be
@@ -789,7 +787,11 @@ extern bool iommu_present(const struct bus_type *bus);
extern bool device_iommu_capable(struct device *dev, enum iommu_cap cap);
extern bool iommu_group_has_isolated_msi(struct iommu_group *group);
extern struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus);
-struct iommu_domain *iommu_paging_domain_alloc(struct device *dev);
+struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev, unsigned int flags);
+static inline struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
+{
+ return iommu_paging_domain_alloc_flags(dev, 0);
+}
extern void iommu_domain_free(struct iommu_domain *domain);
extern int iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
@@ -1096,6 +1098,12 @@ static inline struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus
return NULL;
}
+struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int flags)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
{
return ERR_PTR(-ENODEV);
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags()
2024-10-23 10:41 ` [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags() Vasant Hegde
@ 2024-10-23 14:26 ` Robin Murphy
2024-10-23 14:44 ` Jason Gunthorpe
2024-10-25 8:22 ` Tian, Kevin
1 sibling, 1 reply; 26+ messages in thread
From: Robin Murphy @ 2024-10-23 14:26 UTC (permalink / raw)
To: Vasant Hegde, iommu, joro
Cc: will, suravee.suthikulpanit, jgg, yi.l.liu, baolu.lu, kevin.tian,
jacob.pan, Jason Gunthorpe
On 2024-10-23 11:41 am, Vasant Hegde wrote:
> From: Jason Gunthorpe <jgg@ziepe.ca>
>
> Currently drivers calls iommu_paging_domain_alloc(dev) to get an
> UNMANAGED domain. This is not sufficient to support PASID with
> UNMANAGED domain as some HW like AMD requires certain page table type
> to support PASIDs.
>
> Also the domain_alloc_paging op only passes device as param for domain
> allocation. This is not sufficient for AMD driver to decide the right
> page table.
>
> Instead of extending ops->domain_alloc_paging() it was decided to
> enhance ops->domain_alloc_user() so that caller can pass various
> additional flags.
Wait, what? So iommu_paging_domain_alloc_flags() opaquely may or may not
actually allocate a regular paging domain or a user domain depending on
the flags? But then per patch #3 we allocate default domains - the most
kernel-owned of all - as *user* domains, by virtue of passing the PASID
flag?? Except then per patch #4 it's actually a big double-bluff,
because asking a driver's .domain_alloc_user op for PASIDs is in fact
expected to return an unfinished non-user domain, in spite of the
explicitly documented behaviour:
| Unlike @domain_alloc, it is called only by IOMMUFD and
| must fully initialize the new domain before return.
???
This is insane. Please implement it in manner which is not insane.
Thanks,
Robin.
> Hence add iommu_paging_domain_alloc_flags() API which takes flags as
> parameter. Caller can pass additional parameter to indicate type of
> domain required, etc. iommu_paging_domain_alloc_flags() internally calls
> appropriate callback function to allocate a domain.
>
> Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
> [Added description - Vasant]
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
> Reviewed-by: Yi Liu <yi.l.liu@intel.com>
> ---
> drivers/iommu/iommu.c | 32 +++++++++++++++++++++++++++-----
> include/linux/iommu.h | 14 +++++++++++---
> 2 files changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 811748bec4b0..69fc0b9ba31a 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -2027,20 +2027,42 @@ struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus)
> EXPORT_SYMBOL_GPL(iommu_domain_alloc);
>
> /**
> - * iommu_paging_domain_alloc() - Allocate a paging domain
> + * iommu_paging_domain_alloc_flags() - Allocate a paging domain
> * @dev: device for which the domain is allocated
> + * @flags: Enum of iommufd_hwpt_alloc_flags
> *
> * Allocate a paging domain which will be managed by a kernel driver. Return
> - * allocated domain if successful, or a ERR pointer for failure.
> + * allocated domain if successful, or an ERR pointer for failure.
> */
> -struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
> +struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
> + unsigned int flags)
> {
> + const struct iommu_ops *ops;
> + struct iommu_domain *domain;
> +
> if (!dev_has_iommu(dev))
> return ERR_PTR(-ENODEV);
>
> - return __iommu_domain_alloc(dev_iommu_ops(dev), dev, IOMMU_DOMAIN_UNMANAGED);
> + ops = dev_iommu_ops(dev);
> +
> + if (ops->domain_alloc_paging && !flags)
> + domain = ops->domain_alloc_paging(dev);
> + else if (ops->domain_alloc_user)
> + domain = ops->domain_alloc_user(dev, flags, NULL, NULL);
> + else if (ops->domain_alloc && !flags)
> + domain = ops->domain_alloc(IOMMU_DOMAIN_UNMANAGED);
> + else
> + return ERR_PTR(-EOPNOTSUPP);
> +
> + if (IS_ERR(domain))
> + return domain;
> + if (!domain)
> + return ERR_PTR(-ENOMEM);
> +
> + iommu_domain_init(domain, IOMMU_DOMAIN_UNMANAGED, ops);
> + return domain;
> }
> -EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc);
> +EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);
>
> void iommu_domain_free(struct iommu_domain *domain)
> {
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index bd722f473635..42243183e81d 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -511,8 +511,6 @@ static inline int __iommu_copy_struct_from_user_array(
> * the caller iommu_domain_alloc() returns.
> * @domain_alloc_user: Allocate an iommu domain corresponding to the input
> * parameters as defined in include/uapi/linux/iommufd.h.
> - * Unlike @domain_alloc, it is called only by IOMMUFD and
> - * must fully initialize the new domain before return.
> * Upon success, if the @user_data is valid and the @parent
> * points to a kernel-managed domain, the new domain must be
> * IOMMU_DOMAIN_NESTED type; otherwise, the @parent must be
> @@ -789,7 +787,11 @@ extern bool iommu_present(const struct bus_type *bus);
> extern bool device_iommu_capable(struct device *dev, enum iommu_cap cap);
> extern bool iommu_group_has_isolated_msi(struct iommu_group *group);
> extern struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus);
> -struct iommu_domain *iommu_paging_domain_alloc(struct device *dev);
> +struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev, unsigned int flags);
> +static inline struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
> +{
> + return iommu_paging_domain_alloc_flags(dev, 0);
> +}
> extern void iommu_domain_free(struct iommu_domain *domain);
> extern int iommu_attach_device(struct iommu_domain *domain,
> struct device *dev);
> @@ -1096,6 +1098,12 @@ static inline struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus
> return NULL;
> }
>
> +struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
> + unsigned int flags)
> +{
> + return ERR_PTR(-ENODEV);
> +}
> +
> static inline struct iommu_domain *iommu_paging_domain_alloc(struct device *dev)
> {
> return ERR_PTR(-ENODEV);
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags()
2024-10-23 14:26 ` Robin Murphy
@ 2024-10-23 14:44 ` Jason Gunthorpe
0 siblings, 0 replies; 26+ messages in thread
From: Jason Gunthorpe @ 2024-10-23 14:44 UTC (permalink / raw)
To: Robin Murphy
Cc: Vasant Hegde, iommu, joro, will, suravee.suthikulpanit, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan
On Wed, Oct 23, 2024 at 03:26:48PM +0100, Robin Murphy wrote:
> On 2024-10-23 11:41 am, Vasant Hegde wrote:
> > From: Jason Gunthorpe <jgg@ziepe.ca>
> >
> > Currently drivers calls iommu_paging_domain_alloc(dev) to get an
> > UNMANAGED domain. This is not sufficient to support PASID with
> > UNMANAGED domain as some HW like AMD requires certain page table type
> > to support PASIDs.
> >
> > Also the domain_alloc_paging op only passes device as param for domain
> > allocation. This is not sufficient for AMD driver to decide the right
> > page table.
> >
> > Instead of extending ops->domain_alloc_paging() it was decided to
> > enhance ops->domain_alloc_user() so that caller can pass various
> > additional flags.
>
> Wait, what? So iommu_paging_domain_alloc_flags() opaquely may or may not
> actually allocate a regular paging domain or a user domain
There is no such thing as a "user domain".
> depending on the flags? But then per patch #3 we allocate default
> domains - the most kernel-owned of all - as *user* domains,
We are going to rename domain_alloc_user() once this lands and the
dust settled, it's purpose has now expanded. I'm going to try to do it
for rc7 when all the branches are together.
> return an unfinished non-user domain, in spite of the explicitly documented
> behaviour:
> | Unlike @domain_alloc, it is called only by IOMMUFD and
> | must fully initialize the new domain before return.
>
> ???
That remark about "called only by iommufd" should be removed in this
series.
> This is insane. Please implement it in manner which is not insane.
There are more steps, calm down.
Jason
^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags()
2024-10-23 10:41 ` [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags() Vasant Hegde
2024-10-23 14:26 ` Robin Murphy
@ 2024-10-25 8:22 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:22 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com,
Jason Gunthorpe
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> From: Jason Gunthorpe <jgg@ziepe.ca>
>
> Currently drivers calls iommu_paging_domain_alloc(dev) to get an
> UNMANAGED domain. This is not sufficient to support PASID with
> UNMANAGED domain as some HW like AMD requires certain page table type
> to support PASIDs.
>
> Also the domain_alloc_paging op only passes device as param for domain
> allocation. This is not sufficient for AMD driver to decide the right
> page table.
>
> Instead of extending ops->domain_alloc_paging() it was decided to
> enhance ops->domain_alloc_user() so that caller can pass various
> additional flags.
>
> Hence add iommu_paging_domain_alloc_flags() API which takes flags as
> parameter. Caller can pass additional parameter to indicate type of
> domain required, etc. iommu_paging_domain_alloc_flags() internally calls
> appropriate callback function to allocate a domain.
>
> Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
> [Added description - Vasant]
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
> Reviewed-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
2024-10-23 10:41 ` [PATCH v4 01/12] iommu: Refactor __iommu_domain_alloc() Vasant Hegde
2024-10-23 10:41 ` [PATCH v4 02/12] iommu: Introduce iommu_paging_domain_alloc_flags() Vasant Hegde
@ 2024-10-23 10:41 ` Vasant Hegde
2024-10-23 11:11 ` Baolu Lu
2024-10-25 8:23 ` Tian, Kevin
2024-10-23 10:41 ` [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate " Vasant Hegde
` (8 subsequent siblings)
11 siblings, 2 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:41 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde
From: Jason Gunthorpe <jgg@ziepe.ca>
Introduce new flag (IOMMU_HWPT_ALLOC_PASID) to domain_alloc_users() ops.
If IOMMU supports PASID it will allocate domain. Otherwise return error.
In error path check for -EOPNOTSUPP and try to allocate non-PASID
domain so that DMA-API mode work fine for drivers which does not support
PASID as well.
Also modify __iommu_group_alloc_default_domain() to call
iommu_paging_domain_alloc_flags() with appropriate flag when allocating
paging domain.
Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
Co-developed-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/iommu.c | 56 +++++++++++++++++++++++++++++-------
include/uapi/linux/iommufd.h | 8 ++++++
2 files changed, 53 insertions(+), 11 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 69fc0b9ba31a..a7286c406170 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -32,6 +32,7 @@
#include <trace/events/iommu.h>
#include <linux/sched/mm.h>
#include <linux/msi.h>
+#include <uapi/linux/iommufd.h>
#include "dma-iommu.h"
#include "iommu-priv.h"
@@ -99,6 +100,9 @@ static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain,
struct iommu_group *group);
+static struct iommu_domain *__iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int type,
+ unsigned int flags);
enum {
IOMMU_SET_DOMAIN_MUST_SUCCEED = 1 << 0,
@@ -1589,8 +1593,30 @@ EXPORT_SYMBOL_GPL(fsl_mc_device_group);
static struct iommu_domain *
__iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{
+ struct device *dev = iommu_group_first_dev(group);
+ struct iommu_domain *dom;
+
if (group->default_domain && group->default_domain->type == req_type)
return group->default_domain;
+
+ /*
+ * When allocating the DMA API domain assume that the driver is going to
+ * use PASID and make sure the RID's domain is PASID compatible.
+ */
+ if (req_type & __IOMMU_DOMAIN_PAGING) {
+ dom = __iommu_paging_domain_alloc_flags(dev, req_type,
+ dev->iommu->max_pasids ? IOMMU_HWPT_ALLOC_PASID : 0);
+
+ /*
+ * If driver does not support PASID feature then
+ * try to allocate non-PASID domain
+ */
+ if (PTR_ERR(dom) == -EOPNOTSUPP)
+ dom = __iommu_paging_domain_alloc_flags(dev, req_type, 0);
+
+ return dom;
+ }
+
return __iommu_group_domain_alloc(group, req_type);
}
@@ -2026,16 +2052,9 @@ struct iommu_domain *iommu_domain_alloc(const struct bus_type *bus)
}
EXPORT_SYMBOL_GPL(iommu_domain_alloc);
-/**
- * iommu_paging_domain_alloc_flags() - Allocate a paging domain
- * @dev: device for which the domain is allocated
- * @flags: Enum of iommufd_hwpt_alloc_flags
- *
- * Allocate a paging domain which will be managed by a kernel driver. Return
- * allocated domain if successful, or an ERR pointer for failure.
- */
-struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
- unsigned int flags)
+static struct iommu_domain *
+__iommu_paging_domain_alloc_flags(struct device *dev, unsigned int type,
+ unsigned int flags)
{
const struct iommu_ops *ops;
struct iommu_domain *domain;
@@ -2059,9 +2078,24 @@ struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
if (!domain)
return ERR_PTR(-ENOMEM);
- iommu_domain_init(domain, IOMMU_DOMAIN_UNMANAGED, ops);
+ iommu_domain_init(domain, type, ops);
return domain;
}
+
+/**
+ * iommu_paging_domain_alloc_flags() - Allocate a paging domain
+ * @dev: device for which the domain is allocated
+ * @flags: Bitmap of iommufd_hwpt_alloc_flags
+ *
+ * Allocate a paging domain which will be managed by a kernel driver. Return
+ * allocated domain if successful, or an ERR pointer for failure.
+ */
+struct iommu_domain *iommu_paging_domain_alloc_flags(struct device *dev,
+ unsigned int flags)
+{
+ return __iommu_paging_domain_alloc_flags(dev,
+ IOMMU_DOMAIN_UNMANAGED, flags);
+}
EXPORT_SYMBOL_GPL(iommu_paging_domain_alloc_flags);
void iommu_domain_free(struct iommu_domain *domain)
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 72010f71c5e4..0c0ed28ee113 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -359,11 +359,19 @@ struct iommu_vfio_ioas {
* enforced on device attachment
* @IOMMU_HWPT_FAULT_ID_VALID: The fault_id field of hwpt allocation data is
* valid.
+ * @IOMMU_HWPT_ALLOC_PASID: Requests a domain that can be used with PASID. The
+ * domain can be attached to any PASID on the device.
+ * Any domain attached to the non-PASID part of the
+ * device must also be flaged, otherwise attaching a
+ * PASID will blocked.
+ * If IOMMU does not support PASID it will return
+ * error (-EOPNOTSUPP).
*/
enum iommufd_hwpt_alloc_flags {
IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
IOMMU_HWPT_FAULT_ID_VALID = 1 << 2,
+ IOMMU_HWPT_ALLOC_PASID = 1 << 3,
};
/**
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain
2024-10-23 10:41 ` [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain Vasant Hegde
@ 2024-10-23 11:11 ` Baolu Lu
2024-10-25 8:23 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Baolu Lu @ 2024-10-23 11:11 UTC (permalink / raw)
To: Vasant Hegde, iommu, joro
Cc: baolu.lu, will, robin.murphy, suravee.suthikulpanit, jgg,
yi.l.liu, kevin.tian, jacob.pan
On 2024/10/23 18:41, Vasant Hegde wrote:
> From: Jason Gunthorpe<jgg@ziepe.ca>
>
> Introduce new flag (IOMMU_HWPT_ALLOC_PASID) to domain_alloc_users() ops.
> If IOMMU supports PASID it will allocate domain. Otherwise return error.
> In error path check for -EOPNOTSUPP and try to allocate non-PASID
> domain so that DMA-API mode work fine for drivers which does not support
> PASID as well.
>
> Also modify __iommu_group_alloc_default_domain() to call
> iommu_paging_domain_alloc_flags() with appropriate flag when allocating
> paging domain.
>
> Signed-off-by: Jason Gunthorpe<jgg@ziepe.ca>
> Co-developed-by: Vasant Hegde<vasant.hegde@amd.com>
> Signed-off-by: Vasant Hegde<vasant.hegde@amd.com>
> ---
> drivers/iommu/iommu.c | 56 +++++++++++++++++++++++++++++-------
> include/uapi/linux/iommufd.h | 8 ++++++
> 2 files changed, 53 insertions(+), 11 deletions(-)
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Thanks,
baolu
^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain
2024-10-23 10:41 ` [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain Vasant Hegde
2024-10-23 11:11 ` Baolu Lu
@ 2024-10-25 8:23 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:23 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> From: Jason Gunthorpe <jgg@ziepe.ca>
>
> Introduce new flag (IOMMU_HWPT_ALLOC_PASID) to domain_alloc_users()
> ops.
> If IOMMU supports PASID it will allocate domain. Otherwise return error.
> In error path check for -EOPNOTSUPP and try to allocate non-PASID
> domain so that DMA-API mode work fine for drivers which does not support
> PASID as well.
>
> Also modify __iommu_group_alloc_default_domain() to call
> iommu_paging_domain_alloc_flags() with appropriate flag when allocating
> paging domain.
>
> Signed-off-by: Jason Gunthorpe <jgg@ziepe.ca>
> Co-developed-by: Vasant Hegde <vasant.hegde@amd.com>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate PASID capable domain
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (2 preceding siblings ...)
2024-10-23 10:41 ` [PATCH v4 03/12] iommu: Add new flag to explictly request PASID capable domain Vasant Hegde
@ 2024-10-23 10:41 ` Vasant Hegde
2024-10-23 12:23 ` Jason Gunthorpe
2024-10-25 8:23 ` Tian, Kevin
2024-10-23 10:42 ` [PATCH v4 05/12] iommu/amd: Add helper function to check GIOSUP/GTSUP Vasant Hegde
` (7 subsequent siblings)
11 siblings, 2 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:41 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde
Core layer is modified to call domain_alloc_user() to allocate PASID
capable domain. Enhance arm_smmu_domain_alloc_user() to allocate
PASID capable domain based on the 'flags' parameter.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 737c5b882355..8a193141f003 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3084,7 +3084,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
const struct iommu_user_data *user_data)
{
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
- const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+ const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_ALLOC_PASID;
struct arm_smmu_domain *smmu_domain;
int ret;
@@ -3093,6 +3094,9 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
if (parent || user_data)
return ERR_PTR(-EOPNOTSUPP);
+ if (flags & IOMMU_HWPT_ALLOC_PASID)
+ return arm_smmu_domain_alloc_paging(dev);
+
smmu_domain = arm_smmu_domain_alloc();
if (IS_ERR(smmu_domain))
return ERR_CAST(smmu_domain);
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate PASID capable domain
2024-10-23 10:41 ` [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate " Vasant Hegde
@ 2024-10-23 12:23 ` Jason Gunthorpe
2024-10-25 8:23 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Jason Gunthorpe @ 2024-10-23 12:23 UTC (permalink / raw)
To: Vasant Hegde
Cc: iommu, joro, will, robin.murphy, suravee.suthikulpanit, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan
On Wed, Oct 23, 2024 at 10:41:59AM +0000, Vasant Hegde wrote:
> Core layer is modified to call domain_alloc_user() to allocate PASID
> capable domain. Enhance arm_smmu_domain_alloc_user() to allocate
> PASID capable domain based on the 'flags' parameter.
>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Jason
^ permalink raw reply [flat|nested] 26+ messages in thread
* RE: [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate PASID capable domain
2024-10-23 10:41 ` [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate " Vasant Hegde
2024-10-23 12:23 ` Jason Gunthorpe
@ 2024-10-25 8:23 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:23 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> Core layer is modified to call domain_alloc_user() to allocate PASID
> capable domain. Enhance arm_smmu_domain_alloc_user() to allocate
> PASID capable domain based on the 'flags' parameter.
>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 05/12] iommu/amd: Add helper function to check GIOSUP/GTSUP
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (3 preceding siblings ...)
2024-10-23 10:41 ` [PATCH v4 04/12] iommu/arm-smmu-v3: Enhance domain_alloc_user() to allocate " Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-23 10:42 ` [PATCH v4 06/12] iommu/amd: Move V2 page table support check to early_amd_iommu_init() Vasant Hegde
` (6 subsequent siblings)
11 siblings, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
amd_iommu_gt_ppr_supported() only checks for GTSUP. To support PASID
with V2 page table we need GIOSUP as well. Hence add new helper function
to check GIOSUP/GTSUP.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/amd/amd_iommu.h | 7 ++++++-
drivers/iommu/amd/init.c | 3 +--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 6386fa4556d9..3b6c6332b09f 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -118,9 +118,14 @@ static inline bool check_feature2(u64 mask)
return (amd_iommu_efr2 & mask);
}
+static inline bool amd_iommu_v2_pgtbl_supported(void)
+{
+ return (check_feature(FEATURE_GIOSUP) && check_feature(FEATURE_GT));
+}
+
static inline bool amd_iommu_gt_ppr_supported(void)
{
- return (check_feature(FEATURE_GT) &&
+ return (amd_iommu_v2_pgtbl_supported() &&
check_feature(FEATURE_PPR) &&
check_feature(FEATURE_EPHSUP));
}
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 43131c3a2172..7ae478d95e2b 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2071,8 +2071,7 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
init_iommu_perf_ctr(iommu);
if (amd_iommu_pgtable == AMD_IOMMU_V2) {
- if (!check_feature(FEATURE_GIOSUP) ||
- !check_feature(FEATURE_GT)) {
+ if (!amd_iommu_v2_pgtbl_supported()) {
pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
amd_iommu_pgtable = AMD_IOMMU_V1;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v4 06/12] iommu/amd: Move V2 page table support check to early_amd_iommu_init()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (4 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 05/12] iommu/amd: Add helper function to check GIOSUP/GTSUP Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-23 10:42 ` [PATCH v4 07/12] iommu/amd: Separate page table setup from domain allocation Vasant Hegde
` (5 subsequent siblings)
11 siblings, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
amd_iommu_pgtable validation has to be done before calling
iommu_snp_enable(). It can be done immediately after reading IOMMU
features. Hence move this check to early_amd_iommu_init().
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/amd/init.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 7ae478d95e2b..7c883be22559 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2070,13 +2070,6 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
init_iommu_perf_ctr(iommu);
- if (amd_iommu_pgtable == AMD_IOMMU_V2) {
- if (!amd_iommu_v2_pgtbl_supported()) {
- pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
- amd_iommu_pgtable = AMD_IOMMU_V1;
- }
- }
-
if (is_rd890_iommu(iommu->dev)) {
int i, j;
@@ -3090,6 +3083,13 @@ static int __init early_amd_iommu_init(void)
FIELD_GET(FEATURE_GATS, amd_iommu_efr) == GUEST_PGTABLE_5_LEVEL)
amd_iommu_gpt_level = PAGE_MODE_5_LEVEL;
+ if (amd_iommu_pgtable == AMD_IOMMU_V2) {
+ if (!amd_iommu_v2_pgtbl_supported()) {
+ pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n");
+ amd_iommu_pgtable = AMD_IOMMU_V1;
+ }
+ }
+
/* Disable any previously enabled IOMMUs */
if (!is_kdump_kernel() || amd_iommu_disabled)
disable_iommus();
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v4 07/12] iommu/amd: Separate page table setup from domain allocation
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (5 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 06/12] iommu/amd: Move V2 page table support check to early_amd_iommu_init() Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-23 10:42 ` [PATCH v4 08/12] iommu/amd: Pass page table type as param to pdom_setup_pgtable() Vasant Hegde
` (4 subsequent siblings)
11 siblings, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
Currently protection_domain_alloc() allocates domain and also sets up
page table. Page table setup is required for PAGING domain only. Domain
type like SVA doesn't need page table. Hence move page table setup code
to separate function.
Also SVA domain allocation path does not call pdom_setup_pgtable().
Hence remove IOMMU_DOMAIN_SVA type check.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jacob Pan <jacob.pan@linux.microsoft.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/amd/iommu.c | 42 ++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 8364cd6fa47d..6285fd1afd50 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2265,28 +2265,36 @@ void protection_domain_free(struct protection_domain *domain)
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
{
- struct io_pgtable_ops *pgtbl_ops;
struct protection_domain *domain;
- int pgtable;
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
domain->id = domain_id_alloc();
- if (!domain->id)
- goto err_free;
+ if (!domain->id) {
+ kfree(domain);
+ return NULL;
+ }
spin_lock_init(&domain->lock);
INIT_LIST_HEAD(&domain->dev_list);
INIT_LIST_HEAD(&domain->dev_data_list);
domain->iop.pgtbl.cfg.amd.nid = nid;
+ return domain;
+}
+
+static int pdom_setup_pgtable(struct protection_domain *domain,
+ unsigned int type)
+{
+ struct io_pgtable_ops *pgtbl_ops;
+ int pgtable;
+
switch (type) {
/* No need to allocate io pgtable ops in passthrough mode */
case IOMMU_DOMAIN_IDENTITY:
- case IOMMU_DOMAIN_SVA:
- return domain;
+ return 0;
case IOMMU_DOMAIN_DMA:
pgtable = amd_iommu_pgtable;
break;
@@ -2298,7 +2306,7 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
pgtable = AMD_IOMMU_V1;
break;
default:
- goto err_id;
+ return -EINVAL;
}
switch (pgtable) {
@@ -2309,20 +2317,14 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
domain->pd_mode = PD_MODE_V2;
break;
default:
- goto err_id;
+ return -EINVAL;
}
-
pgtbl_ops =
alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain);
if (!pgtbl_ops)
- goto err_id;
+ return -ENOMEM;
- return domain;
-err_id:
- domain_id_free(domain->id);
-err_free:
- kfree(domain);
- return NULL;
+ return 0;
}
static inline u64 dma_max_address(void)
@@ -2345,6 +2347,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
struct protection_domain *domain;
struct amd_iommu *iommu = NULL;
+ int ret;
if (dev)
iommu = get_amd_iommu_from_dev(dev);
@@ -2364,6 +2367,13 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
if (!domain)
return ERR_PTR(-ENOMEM);
+ ret = pdom_setup_pgtable(domain, type);
+ if (ret) {
+ domain_id_free(domain->id);
+ kfree(domain);
+ return ERR_PTR(ret);
+ }
+
domain->domain.geometry.aperture_start = 0;
domain->domain.geometry.aperture_end = dma_max_address();
domain->domain.geometry.force_aperture = true;
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v4 08/12] iommu/amd: Pass page table type as param to pdom_setup_pgtable()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (6 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 07/12] iommu/amd: Separate page table setup from domain allocation Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-23 10:42 ` [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user() Vasant Hegde
` (3 subsequent siblings)
11 siblings, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
Current code forces v1 page table for UNMANAGED domain and global page
table type (amd_iommu_pgtable) for rest of paging domain.
Following patch series adds support for domain_alloc_paging() ops. Also
enhances domain_alloc_user() to allocate page table based on 'flags.
Hence pass page table type as parameter to pdomain_setup_pgtable(). So
that caller can decide right page table type. Also update
dma_max_address() to take pgtable as parameter.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jacob Pan <jacob.pan@linux.microsoft.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/amd/iommu.c | 43 +++++++++++++++++----------------------
1 file changed, 19 insertions(+), 24 deletions(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 6285fd1afd50..cb6a72564c23 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2286,28 +2286,13 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
}
static int pdom_setup_pgtable(struct protection_domain *domain,
- unsigned int type)
+ unsigned int type, int pgtable)
{
struct io_pgtable_ops *pgtbl_ops;
- int pgtable;
- switch (type) {
/* No need to allocate io pgtable ops in passthrough mode */
- case IOMMU_DOMAIN_IDENTITY:
+ if (!(type & __IOMMU_DOMAIN_PAGING))
return 0;
- case IOMMU_DOMAIN_DMA:
- pgtable = amd_iommu_pgtable;
- break;
- /*
- * Force IOMMU v1 page table when allocating
- * domain for pass-through devices.
- */
- case IOMMU_DOMAIN_UNMANAGED:
- pgtable = AMD_IOMMU_V1;
- break;
- default:
- return -EINVAL;
- }
switch (pgtable) {
case AMD_IOMMU_V1:
@@ -2319,6 +2304,7 @@ static int pdom_setup_pgtable(struct protection_domain *domain,
default:
return -EINVAL;
}
+
pgtbl_ops =
alloc_io_pgtable_ops(pgtable, &domain->iop.pgtbl.cfg, domain);
if (!pgtbl_ops)
@@ -2327,9 +2313,9 @@ static int pdom_setup_pgtable(struct protection_domain *domain,
return 0;
}
-static inline u64 dma_max_address(void)
+static inline u64 dma_max_address(int pgtable)
{
- if (amd_iommu_pgtable == AMD_IOMMU_V1)
+ if (pgtable == AMD_IOMMU_V1)
return ~0ULL;
/* V2 with 4/5 level page table */
@@ -2342,7 +2328,8 @@ static bool amd_iommu_hd_support(struct amd_iommu *iommu)
}
static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
- struct device *dev, u32 flags)
+ struct device *dev,
+ u32 flags, int pgtable)
{
bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
struct protection_domain *domain;
@@ -2367,7 +2354,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
if (!domain)
return ERR_PTR(-ENOMEM);
- ret = pdom_setup_pgtable(domain, type);
+ ret = pdom_setup_pgtable(domain, type, pgtable);
if (ret) {
domain_id_free(domain->id);
kfree(domain);
@@ -2375,7 +2362,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
}
domain->domain.geometry.aperture_start = 0;
- domain->domain.geometry.aperture_end = dma_max_address();
+ domain->domain.geometry.aperture_end = dma_max_address(pgtable);
domain->domain.geometry.force_aperture = true;
domain->domain.pgsize_bitmap = domain->iop.pgtbl.cfg.pgsize_bitmap;
@@ -2393,8 +2380,16 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
static struct iommu_domain *amd_iommu_domain_alloc(unsigned int type)
{
struct iommu_domain *domain;
+ int pgtable = amd_iommu_pgtable;
+
+ /*
+ * Force IOMMU v1 page table when allocating
+ * domain for pass-through devices.
+ */
+ if (type == IOMMU_DOMAIN_UNMANAGED)
+ pgtable = AMD_IOMMU_V1;
- domain = do_iommu_domain_alloc(type, NULL, 0);
+ domain = do_iommu_domain_alloc(type, NULL, 0, pgtable);
if (IS_ERR(domain))
return NULL;
@@ -2412,7 +2407,7 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
return ERR_PTR(-EOPNOTSUPP);
- return do_iommu_domain_alloc(type, dev, flags);
+ return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
}
void amd_iommu_domain_free(struct iommu_domain *dom)
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (7 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 08/12] iommu/amd: Pass page table type as param to pdom_setup_pgtable() Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-23 12:46 ` Jason Gunthorpe
2024-10-23 10:42 ` [PATCH v4 10/12] iommu/amd: Implement global identity domain Vasant Hegde
` (2 subsequent siblings)
11 siblings, 1 reply; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde
Previous patch enhanced core layer to check device PASID capability and
pass right flags to ops->domain_alloc_user().
Enhance amd_iommu_domain_alloc_user() to allocate domain with
appropriate page table based on flags parameter.
- If flags is empty then allocate domain with default page table type.
This will eventually replace ops->domain_alloc().
For UNMANAGED domain, core will call this interface with flags=0. So
AMD driver will continue to allocate V1 page table.
- If IOMMU_HWPT_ALLOC_PASID flags is passed then allocate domain with v2
page table.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/amd/iommu.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index cb6a72564c23..cdc93c794eff 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2403,10 +2403,26 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
{
unsigned int type = IOMMU_DOMAIN_UNMANAGED;
+ const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+ IOMMU_HWPT_ALLOC_PASID;
- if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
+ if ((flags & ~supported_flags) || parent || user_data)
return ERR_PTR(-EOPNOTSUPP);
+ /* Allocate domain with default page table */
+ if (!flags) {
+ return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA,
+ dev, 0, amd_iommu_pgtable);
+ }
+
+ /* Allocate domain with v2 page table if IOMMU supports PASID. */
+ if (flags & IOMMU_HWPT_ALLOC_PASID) {
+ if (!amd_iommu_pasid_supported())
+ return ERR_PTR(-EOPNOTSUPP);
+
+ return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
+ }
+
return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user()
2024-10-23 10:42 ` [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user() Vasant Hegde
@ 2024-10-23 12:46 ` Jason Gunthorpe
2024-10-24 6:38 ` Vasant Hegde
2024-10-25 8:24 ` Tian, Kevin
0 siblings, 2 replies; 26+ messages in thread
From: Jason Gunthorpe @ 2024-10-23 12:46 UTC (permalink / raw)
To: Vasant Hegde
Cc: iommu, joro, will, robin.murphy, suravee.suthikulpanit, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan
On Wed, Oct 23, 2024 at 10:42:04AM +0000, Vasant Hegde wrote:
> Previous patch enhanced core layer to check device PASID capability and
> pass right flags to ops->domain_alloc_user().
>
> Enhance amd_iommu_domain_alloc_user() to allocate domain with
> appropriate page table based on flags parameter.
> - If flags is empty then allocate domain with default page table type.
> This will eventually replace ops->domain_alloc().
> For UNMANAGED domain, core will call this interface with flags=0. So
> AMD driver will continue to allocate V1 page table.
>
> - If IOMMU_HWPT_ALLOC_PASID flags is passed then allocate domain with v2
> page table.
>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> ---
> drivers/iommu/amd/iommu.c | 18 +++++++++++++++++-
> 1 file changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index cb6a72564c23..cdc93c794eff 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -2403,10 +2403,26 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
>
> {
> unsigned int type = IOMMU_DOMAIN_UNMANAGED;
> + const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
> + IOMMU_HWPT_ALLOC_PASID;
>
> - if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
> + if ((flags & ~supported_flags) || parent || user_data)
> return ERR_PTR(-EOPNOTSUPP);
>
> + /* Allocate domain with default page table */
> + if (!flags) {
> + return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA,
> + dev, 0, amd_iommu_pgtable);
> + }
> +
> + /* Allocate domain with v2 page table if IOMMU supports PASID. */
> + if (flags & IOMMU_HWPT_ALLOC_PASID) {
> + if (!amd_iommu_pasid_supported())
> + return ERR_PTR(-EOPNOTSUPP);
> +
> + return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
> + }
> +
> return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
This should be more specific about what the dirty_tracking
configuration needs:
if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) {
if (!amd_iommu_hd_support(iommu) ||
(flags & IOMMU_HWPT_ALLOC_PASID))
return ERR_PTR(-EOPNOTSUPP);
return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
}
if (flags & IOMMU_HWPT_ALLOC_PASID) {
if (!amd_iommu_pasid_supported())
return ERR_PTR(-EOPNOTSUPP);
return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
}
/* If nothing specific is required use the kernel commandline default */
return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA, dev, 0,
amd_iommu_pgtable);
Jason
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user()
2024-10-23 12:46 ` Jason Gunthorpe
@ 2024-10-24 6:38 ` Vasant Hegde
2024-10-25 8:24 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Vasant Hegde @ 2024-10-24 6:38 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: iommu, joro, will, robin.murphy, suravee.suthikulpanit, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan
Jason,
On 10/23/2024 6:16 PM, Jason Gunthorpe wrote:
> On Wed, Oct 23, 2024 at 10:42:04AM +0000, Vasant Hegde wrote:
>> Previous patch enhanced core layer to check device PASID capability and
>> pass right flags to ops->domain_alloc_user().
>>
>> Enhance amd_iommu_domain_alloc_user() to allocate domain with
>> appropriate page table based on flags parameter.
>> - If flags is empty then allocate domain with default page table type.
>> This will eventually replace ops->domain_alloc().
>> For UNMANAGED domain, core will call this interface with flags=0. So
>> AMD driver will continue to allocate V1 page table.
>>
>> - If IOMMU_HWPT_ALLOC_PASID flags is passed then allocate domain with v2
>> page table.
>>
>> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
>> ---
>> drivers/iommu/amd/iommu.c | 18 +++++++++++++++++-
>> 1 file changed, 17 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
>> index cb6a72564c23..cdc93c794eff 100644
>> --- a/drivers/iommu/amd/iommu.c
>> +++ b/drivers/iommu/amd/iommu.c
>> @@ -2403,10 +2403,26 @@ amd_iommu_domain_alloc_user(struct device *dev, u32 flags,
>>
>> {
>> unsigned int type = IOMMU_DOMAIN_UNMANAGED;
>> + const u32 supported_flags = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
>> + IOMMU_HWPT_ALLOC_PASID;
>>
>> - if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent || user_data)
>> + if ((flags & ~supported_flags) || parent || user_data)
>> return ERR_PTR(-EOPNOTSUPP);
>>
>> + /* Allocate domain with default page table */
>> + if (!flags) {
>> + return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA,
>> + dev, 0, amd_iommu_pgtable);
>> + }
>> +
>> + /* Allocate domain with v2 page table if IOMMU supports PASID. */
>> + if (flags & IOMMU_HWPT_ALLOC_PASID) {
>> + if (!amd_iommu_pasid_supported())
>> + return ERR_PTR(-EOPNOTSUPP);
>> +
>> + return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
>> + }
>> +
>> return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
>
> This should be more specific about what the dirty_tracking
> configuration needs:
Sure. Fixed it.
-Vasant
>
> if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) {
> if (!amd_iommu_hd_support(iommu) ||
> (flags & IOMMU_HWPT_ALLOC_PASID))
> return ERR_PTR(-EOPNOTSUPP);
> return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
> }
>
> if (flags & IOMMU_HWPT_ALLOC_PASID) {
> if (!amd_iommu_pasid_supported())
> return ERR_PTR(-EOPNOTSUPP);
> return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V2);
> }
>
> /* If nothing specific is required use the kernel commandline default */
> return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA, dev, 0,
> amd_iommu_pgtable);
>
> Jason
^ permalink raw reply [flat|nested] 26+ messages in thread* RE: [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user()
2024-10-23 12:46 ` Jason Gunthorpe
2024-10-24 6:38 ` Vasant Hegde
@ 2024-10-25 8:24 ` Tian, Kevin
1 sibling, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:24 UTC (permalink / raw)
To: Jason Gunthorpe, Vasant Hegde
Cc: iommu@lists.linux.dev, joro@8bytes.org, will@kernel.org,
robin.murphy@arm.com, suravee.suthikulpanit@amd.com, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com
> From: Jason Gunthorpe <jgg@ziepe.ca>
> Sent: Wednesday, October 23, 2024 8:46 PM
>
> On Wed, Oct 23, 2024 at 10:42:04AM +0000, Vasant Hegde wrote:
> > Previous patch enhanced core layer to check device PASID capability and
> > pass right flags to ops->domain_alloc_user().
> >
> > Enhance amd_iommu_domain_alloc_user() to allocate domain with
> > appropriate page table based on flags parameter.
> > - If flags is empty then allocate domain with default page table type.
> > This will eventually replace ops->domain_alloc().
> > For UNMANAGED domain, core will call this interface with flags=0. So
> > AMD driver will continue to allocate V1 page table.
> >
> > - If IOMMU_HWPT_ALLOC_PASID flags is passed then allocate domain
> with v2
> > page table.
> >
> > Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> > ---
> > drivers/iommu/amd/iommu.c | 18 +++++++++++++++++-
> > 1 file changed, 17 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> > index cb6a72564c23..cdc93c794eff 100644
> > --- a/drivers/iommu/amd/iommu.c
> > +++ b/drivers/iommu/amd/iommu.c
> > @@ -2403,10 +2403,26 @@ amd_iommu_domain_alloc_user(struct device
> *dev, u32 flags,
> >
> > {
> > unsigned int type = IOMMU_DOMAIN_UNMANAGED;
> > + const u32 supported_flags =
> IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
> > +
> IOMMU_HWPT_ALLOC_PASID;
> >
> > - if ((flags & ~IOMMU_HWPT_ALLOC_DIRTY_TRACKING) || parent ||
> user_data)
> > + if ((flags & ~supported_flags) || parent || user_data)
> > return ERR_PTR(-EOPNOTSUPP);
> >
> > + /* Allocate domain with default page table */
> > + if (!flags) {
> > + return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA,
> > + dev, 0, amd_iommu_pgtable);
> > + }
> > +
> > + /* Allocate domain with v2 page table if IOMMU supports PASID. */
> > + if (flags & IOMMU_HWPT_ALLOC_PASID) {
> > + if (!amd_iommu_pasid_supported())
> > + return ERR_PTR(-EOPNOTSUPP);
> > +
> > + return do_iommu_domain_alloc(type, dev, flags,
> AMD_IOMMU_V2);
> > + }
> > +
> > return do_iommu_domain_alloc(type, dev, flags, AMD_IOMMU_V1);
>
> This should be more specific about what the dirty_tracking
> configuration needs:
>
> if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) {
> if (!amd_iommu_hd_support(iommu) ||
> (flags & IOMMU_HWPT_ALLOC_PASID))
> return ERR_PTR(-EOPNOTSUPP);
> return do_iommu_domain_alloc(type, dev, flags,
> AMD_IOMMU_V1);
> }
>
> if (flags & IOMMU_HWPT_ALLOC_PASID) {
> if (!amd_iommu_pasid_supported())
> return ERR_PTR(-EOPNOTSUPP);
> return do_iommu_domain_alloc(type, dev, flags,
> AMD_IOMMU_V2);
> }
>
> /* If nothing specific is required use the kernel commandline default
> */
> return do_iommu_domain_alloc(IOMMU_DOMAIN_DMA, dev, 0,
> amd_iommu_pgtable);
>
with that fix,
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 10/12] iommu/amd: Implement global identity domain
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (8 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 09/12] iommu/amd: Enhance amd_iommu_domain_alloc_user() Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-25 8:24 ` Tian, Kevin
2024-10-23 10:42 ` [PATCH v4 11/12] iommu: Put domain allocation in __iommu_group_alloc_blocking_domain() Vasant Hegde
2024-10-23 10:42 ` [PATCH v4 12/12] iommu: Create __iommu_alloc_identity_domain() Vasant Hegde
11 siblings, 1 reply; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Vasant Hegde, Jason Gunthorpe
Implement global identity domain. All device groups in identity domain
will share this domain.
In attach device path, based on device capability it will allocate per
device domain ID and GCR3 table. So that it can support SVA.
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/amd/amd_iommu.h | 1 +
drivers/iommu/amd/init.c | 3 +++
drivers/iommu/amd/iommu.c | 36 +++++++++++++++++++++++++++++++----
3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index 3b6c6332b09f..38509e1019e9 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -46,6 +46,7 @@ extern int amd_iommu_gpt_level;
extern unsigned long amd_iommu_pgsize_bitmap;
/* Protection domain ops */
+void amd_iommu_init_identity_domain(void);
struct protection_domain *protection_domain_alloc(unsigned int type, int nid);
void protection_domain_free(struct protection_domain *domain);
struct iommu_domain *amd_iommu_domain_alloc_sva(struct device *dev,
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 7c883be22559..45fdba48d54d 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -2164,6 +2164,9 @@ static int __init amd_iommu_init_pci(void)
struct amd_iommu_pci_seg *pci_seg;
int ret;
+ /* Init global identity domain before registering IOMMU */
+ amd_iommu_init_identity_domain();
+
for_each_iommu(iommu) {
ret = iommu_init_pci(iommu);
if (ret) {
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index cdc93c794eff..73c7ffa2ee02 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -74,6 +74,9 @@ struct kmem_cache *amd_iommu_irq_cache;
static void detach_device(struct device *dev);
+static int amd_iommu_attach_device(struct iommu_domain *dom,
+ struct device *dev);
+
static void set_dte_entry(struct amd_iommu *iommu,
struct iommu_dev_data *dev_data);
@@ -2263,6 +2266,14 @@ void protection_domain_free(struct protection_domain *domain)
kfree(domain);
}
+static void protection_domain_init(struct protection_domain *domain, int nid)
+{
+ spin_lock_init(&domain->lock);
+ INIT_LIST_HEAD(&domain->dev_list);
+ INIT_LIST_HEAD(&domain->dev_data_list);
+ domain->iop.pgtbl.cfg.amd.nid = nid;
+}
+
struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
{
struct protection_domain *domain;
@@ -2277,10 +2288,7 @@ struct protection_domain *protection_domain_alloc(unsigned int type, int nid)
return NULL;
}
- spin_lock_init(&domain->lock);
- INIT_LIST_HEAD(&domain->dev_list);
- INIT_LIST_HEAD(&domain->dev_data_list);
- domain->iop.pgtbl.cfg.amd.nid = nid;
+ protection_domain_init(domain, nid);
return domain;
}
@@ -2465,6 +2473,25 @@ static struct iommu_domain blocked_domain = {
}
};
+static struct protection_domain identity_domain;
+
+static const struct iommu_domain_ops identity_domain_ops = {
+ .attach_dev = amd_iommu_attach_device,
+};
+
+void amd_iommu_init_identity_domain(void)
+{
+ struct iommu_domain *domain = &identity_domain.domain;
+
+ domain->type = IOMMU_DOMAIN_IDENTITY;
+ domain->ops = &identity_domain_ops;
+ domain->owner = &amd_iommu_ops;
+
+ identity_domain.id = domain_id_alloc();
+
+ protection_domain_init(&identity_domain, NUMA_NO_NODE);
+}
+
static int amd_iommu_attach_device(struct iommu_domain *dom,
struct device *dev)
{
@@ -2863,6 +2890,7 @@ static int amd_iommu_dev_disable_feature(struct device *dev,
const struct iommu_ops amd_iommu_ops = {
.capable = amd_iommu_capable,
.blocked_domain = &blocked_domain,
+ .identity_domain = &identity_domain.domain,
.domain_alloc = amd_iommu_domain_alloc,
.domain_alloc_user = amd_iommu_domain_alloc_user,
.domain_alloc_sva = amd_iommu_domain_alloc_sva,
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* RE: [PATCH v4 10/12] iommu/amd: Implement global identity domain
2024-10-23 10:42 ` [PATCH v4 10/12] iommu/amd: Implement global identity domain Vasant Hegde
@ 2024-10-25 8:24 ` Tian, Kevin
0 siblings, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:24 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com,
Jason Gunthorpe
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> Implement global identity domain. All device groups in identity domain
> will share this domain.
>
> In attach device path, based on device capability it will allocate per
> device domain ID and GCR3 table. So that it can support SVA.
>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 11/12] iommu: Put domain allocation in __iommu_group_alloc_blocking_domain()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (9 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 10/12] iommu/amd: Implement global identity domain Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-25 8:25 ` Tian, Kevin
2024-10-23 10:42 ` [PATCH v4 12/12] iommu: Create __iommu_alloc_identity_domain() Vasant Hegde
11 siblings, 1 reply; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Jason Gunthorpe, Vasant Hegde
From: Jason Gunthorpe <jgg@nvidia.com>
There is no longer a reason to call __iommu_domain_alloc() to allocate
the blocking domain. All drivers that support a native blocking domain
provide it via the ops, for other drivers we should call
iommu_paging_domain_alloc().
__iommu_group_alloc_blocking_domain() is the only place that allocates
an BLOCKED domain, so move the ops->blocked_domain logic there.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/iommu.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index a7286c406170..4677b676bd0b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1985,8 +1985,6 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
if (alloc_type == IOMMU_DOMAIN_IDENTITY && ops->identity_domain)
return ops->identity_domain;
- else if (alloc_type == IOMMU_DOMAIN_BLOCKED && ops->blocked_domain)
- return ops->blocked_domain;
else if (type & __IOMMU_DOMAIN_PAGING && ops->domain_alloc_paging)
domain = ops->domain_alloc_paging(dev);
else if (ops->domain_alloc)
@@ -3212,22 +3210,25 @@ void iommu_device_unuse_default_domain(struct device *dev)
static int __iommu_group_alloc_blocking_domain(struct iommu_group *group)
{
+ struct device *dev = iommu_group_first_dev(group);
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
struct iommu_domain *domain;
if (group->blocking_domain)
return 0;
- domain = __iommu_group_domain_alloc(group, IOMMU_DOMAIN_BLOCKED);
- if (IS_ERR(domain)) {
- /*
- * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED
- * create an empty domain instead.
- */
- domain = __iommu_group_domain_alloc(group,
- IOMMU_DOMAIN_UNMANAGED);
- if (IS_ERR(domain))
- return PTR_ERR(domain);
+ if (ops->blocked_domain) {
+ group->blocking_domain = ops->blocked_domain;
+ return 0;
}
+
+ /*
+ * For drivers that do not yet understand IOMMU_DOMAIN_BLOCKED create an
+ * empty PAGING domain instead.
+ */
+ domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(domain))
+ return PTR_ERR(domain);
group->blocking_domain = domain;
return 0;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* RE: [PATCH v4 11/12] iommu: Put domain allocation in __iommu_group_alloc_blocking_domain()
2024-10-23 10:42 ` [PATCH v4 11/12] iommu: Put domain allocation in __iommu_group_alloc_blocking_domain() Vasant Hegde
@ 2024-10-25 8:25 ` Tian, Kevin
0 siblings, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:25 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com,
Jason Gunthorpe
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> From: Jason Gunthorpe <jgg@nvidia.com>
>
> There is no longer a reason to call __iommu_domain_alloc() to allocate
> the blocking domain. All drivers that support a native blocking domain
> provide it via the ops, for other drivers we should call
> iommu_paging_domain_alloc().
>
> __iommu_group_alloc_blocking_domain() is the only place that allocates
> an BLOCKED domain, so move the ops->blocked_domain logic there.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread
* [PATCH v4 12/12] iommu: Create __iommu_alloc_identity_domain()
2024-10-23 10:41 [PATCH v4 00/12] iommu: Domain allocation enhancements Vasant Hegde
` (10 preceding siblings ...)
2024-10-23 10:42 ` [PATCH v4 11/12] iommu: Put domain allocation in __iommu_group_alloc_blocking_domain() Vasant Hegde
@ 2024-10-23 10:42 ` Vasant Hegde
2024-10-25 8:25 ` Tian, Kevin
11 siblings, 1 reply; 26+ messages in thread
From: Vasant Hegde @ 2024-10-23 10:42 UTC (permalink / raw)
To: iommu, joro
Cc: will, robin.murphy, suravee.suthikulpanit, jgg, yi.l.liu,
baolu.lu, kevin.tian, jacob.pan, Jason Gunthorpe, Vasant Hegde
From: Jason Gunthorpe <jgg@nvidia.com>
Consolidate all the code to create an IDENTITY domain into one
function. This removes the legacy __iommu_domain_alloc() path from all
paths, and preps it for final removal.
BLOCKED/IDENTITY/PAGING are now always allocated via a type specific
function.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/iommu.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 4677b676bd0b..dfc2f9816086 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -94,8 +94,6 @@ static const char * const iommu_group_resv_type_string[] = {
static int iommu_bus_notifier(struct notifier_block *nb,
unsigned long action, void *data);
static void iommu_release_device(struct device *dev);
-static struct iommu_domain *
-__iommu_group_domain_alloc(struct iommu_group *group, unsigned int type);
static int __iommu_attach_device(struct iommu_domain *domain,
struct device *dev);
static int __iommu_attach_group(struct iommu_domain *domain,
@@ -137,6 +135,8 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
struct device *dev);
static void __iommu_group_free_device(struct iommu_group *group,
struct group_device *grp_dev);
+static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
+ const struct iommu_ops *ops);
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
struct iommu_group_attribute iommu_group_attr_##_name = \
@@ -1590,6 +1590,28 @@ struct iommu_group *fsl_mc_device_group(struct device *dev)
}
EXPORT_SYMBOL_GPL(fsl_mc_device_group);
+static struct iommu_domain *__iommu_alloc_identity_domain(struct device *dev)
+{
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
+ struct iommu_domain *domain;
+
+ if (ops->identity_domain)
+ return ops->identity_domain;
+
+ /* Older drivers create the identity domain via ops->domain_alloc() */
+ if (!ops->domain_alloc)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ domain = ops->domain_alloc(IOMMU_DOMAIN_IDENTITY);
+ if (IS_ERR(domain))
+ return domain;
+ if (!domain)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_domain_init(domain, IOMMU_DOMAIN_IDENTITY, ops);
+ return domain;
+}
+
static struct iommu_domain *
__iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
{
@@ -1617,7 +1639,10 @@ __iommu_group_alloc_default_domain(struct iommu_group *group, int req_type)
return dom;
}
- return __iommu_group_domain_alloc(group, req_type);
+ if (req_type == IOMMU_DOMAIN_IDENTITY)
+ return __iommu_alloc_identity_domain(dev);
+
+ return ERR_PTR(-EINVAL);
}
/*
@@ -1983,9 +2008,7 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
struct iommu_domain *domain;
unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS;
- if (alloc_type == IOMMU_DOMAIN_IDENTITY && ops->identity_domain)
- return ops->identity_domain;
- else if (type & __IOMMU_DOMAIN_PAGING && ops->domain_alloc_paging)
+ if (type & __IOMMU_DOMAIN_PAGING && ops->domain_alloc_paging)
domain = ops->domain_alloc_paging(dev);
else if (ops->domain_alloc)
domain = ops->domain_alloc(alloc_type);
@@ -2006,14 +2029,6 @@ static struct iommu_domain *__iommu_domain_alloc(const struct iommu_ops *ops,
return domain;
}
-static struct iommu_domain *
-__iommu_group_domain_alloc(struct iommu_group *group, unsigned int type)
-{
- struct device *dev = iommu_group_first_dev(group);
-
- return __iommu_domain_alloc(dev_iommu_ops(dev), dev, type);
-}
-
static int __iommu_domain_alloc_dev(struct device *dev, void *data)
{
const struct iommu_ops **ops = data;
--
2.31.1
^ permalink raw reply related [flat|nested] 26+ messages in thread* RE: [PATCH v4 12/12] iommu: Create __iommu_alloc_identity_domain()
2024-10-23 10:42 ` [PATCH v4 12/12] iommu: Create __iommu_alloc_identity_domain() Vasant Hegde
@ 2024-10-25 8:25 ` Tian, Kevin
0 siblings, 0 replies; 26+ messages in thread
From: Tian, Kevin @ 2024-10-25 8:25 UTC (permalink / raw)
To: Vasant Hegde, iommu@lists.linux.dev, joro@8bytes.org
Cc: will@kernel.org, robin.murphy@arm.com,
suravee.suthikulpanit@amd.com, jgg@ziepe.ca, Liu, Yi L,
baolu.lu@linux.intel.com, jacob.pan@linux.microsoft.com,
Jason Gunthorpe
> From: Vasant Hegde <vasant.hegde@amd.com>
> Sent: Wednesday, October 23, 2024 6:42 PM
>
> From: Jason Gunthorpe <jgg@nvidia.com>
>
> Consolidate all the code to create an IDENTITY domain into one
> function. This removes the legacy __iommu_domain_alloc() path from all
> paths, and preps it for final removal.
>
> BLOCKED/IDENTITY/PAGING are now always allocated via a type specific
> function.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
^ permalink raw reply [flat|nested] 26+ messages in thread