Re: [PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-24 Thread Jason Gunthorpe via iommu
On Tue, May 24, 2022 at 01:45:26PM -0700, Jacob Pan wrote:

> > The idea that there is only one PASID per domain per device is not
> > right.
> > 
> Got you, I was under the impression that there is no use case yet for
> multiple PASIDs per device-domain based on our early discussion.

The key word there is "in-kernel" and "DMA API" - iommufd userspace
will do whatever it likes.

I wish you guys would organize your work so adding generic PASID
support to IOMMU was its own series with its own purpose so everything
stops becoming confused with SVA and DMA API ideas that are not
general.

Jason
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-24 Thread Jacob Pan
Hi Jason,

On Tue, 24 May 2022 15:02:41 -0300, Jason Gunthorpe  wrote:

> On Tue, May 24, 2022 at 09:12:35AM -0700, Jacob Pan wrote:
> > Hi Jason,
> > 
> > On Tue, 24 May 2022 10:51:35 -0300, Jason Gunthorpe 
> > wrote: 
> > > On Wed, May 18, 2022 at 11:21:17AM -0700, Jacob Pan wrote:  
> > > > On VT-d platforms with scalable mode enabled, devices issue DMA
> > > > requests with PASID need to attach PASIDs to given IOMMU domains.
> > > > The attach operation involves the following:
> > > > - Programming the PASID into the device's PASID table
> > > > - Tracking device domain and the PASID relationship
> > > > - Managing IOTLB and device TLB invalidations
> > > > 
> > > > This patch add attach_dev_pasid functions to the default domain ops
> > > > which is used by DMA and identity domain types. It could be
> > > > extended to support other domain types whenever necessary.
> > > > 
> > > > Signed-off-by: Lu Baolu 
> > > > Signed-off-by: Jacob Pan 
> > > >  drivers/iommu/intel/iommu.c | 72
> > > > +++-- 1 file changed, 70
> > > > insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/iommu/intel/iommu.c
> > > > b/drivers/iommu/intel/iommu.c index 1c2c92b657c7..75615c105fdf
> > > > 100644 +++ b/drivers/iommu/intel/iommu.c
> > > > @@ -1556,12 +1556,18 @@ static void __iommu_flush_dev_iotlb(struct
> > > > device_domain_info *info, u64 addr, unsigned int mask)
> > > >  {
> > > > u16 sid, qdep;
> > > > +   ioasid_t pasid;
> > > >  
> > > > if (!info || !info->ats_enabled)
> > > > return;
> > > >  
> > > > sid = info->bus << 8 | info->devfn;
> > > > qdep = info->ats_qdep;
> > > > +   pasid = iommu_get_pasid_from_domain(info->dev,
> > > > >domain->domain);
> > > 
> > > No, a simgple domain can be attached to multiple pasids, all need to
> > > be flushed.
> > >   
> > Here is device TLB flush, why would I want to flush PASIDs other than my
> > own device attached?  
> 
> Again, a domain can be attached to multiple PASID's *on the same
> device*
> 
> The idea that there is only one PASID per domain per device is not
> right.
> 
Got you, I was under the impression that there is no use case yet for
multiple PASIDs per device-domain based on our early discussion.
https://lore.kernel.org/lkml/20220315142216.gv11...@nvidia.com/

Perhaps I misunderstood. I will make the API more future proof and search
through the pasid_array xa for *all* domain-device matches. Like you
suggested earlier, may need to retrieve the xa in the first place and use
xas_for_each to get a faster search.

Thanks,

Jacob
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-24 Thread Jason Gunthorpe via iommu
On Tue, May 24, 2022 at 09:12:35AM -0700, Jacob Pan wrote:
> Hi Jason,
> 
> On Tue, 24 May 2022 10:51:35 -0300, Jason Gunthorpe  wrote:
> 
> > On Wed, May 18, 2022 at 11:21:17AM -0700, Jacob Pan wrote:
> > > On VT-d platforms with scalable mode enabled, devices issue DMA requests
> > > with PASID need to attach PASIDs to given IOMMU domains. The attach
> > > operation involves the following:
> > > - Programming the PASID into the device's PASID table
> > > - Tracking device domain and the PASID relationship
> > > - Managing IOTLB and device TLB invalidations
> > > 
> > > This patch add attach_dev_pasid functions to the default domain ops
> > > which is used by DMA and identity domain types. It could be extended to
> > > support other domain types whenever necessary.
> > > 
> > > Signed-off-by: Lu Baolu 
> > > Signed-off-by: Jacob Pan 
> > >  drivers/iommu/intel/iommu.c | 72 +++--
> > >  1 file changed, 70 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> > > index 1c2c92b657c7..75615c105fdf 100644
> > > +++ b/drivers/iommu/intel/iommu.c
> > > @@ -1556,12 +1556,18 @@ static void __iommu_flush_dev_iotlb(struct
> > > device_domain_info *info, u64 addr, unsigned int mask)
> > >  {
> > >   u16 sid, qdep;
> > > + ioasid_t pasid;
> > >  
> > >   if (!info || !info->ats_enabled)
> > >   return;
> > >  
> > >   sid = info->bus << 8 | info->devfn;
> > >   qdep = info->ats_qdep;
> > > + pasid = iommu_get_pasid_from_domain(info->dev,
> > > >domain->domain);  
> > 
> > No, a simgple domain can be attached to multiple pasids, all need to
> > be flushed.
> > 
> Here is device TLB flush, why would I want to flush PASIDs other than my
> own device attached?

Again, a domain can be attached to multiple PASID's *on the same
device*

The idea that there is only one PASID per domain per device is not
right.

Jason
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-24 Thread Jacob Pan
Hi Jason,

On Tue, 24 May 2022 10:51:35 -0300, Jason Gunthorpe  wrote:

> On Wed, May 18, 2022 at 11:21:17AM -0700, Jacob Pan wrote:
> > On VT-d platforms with scalable mode enabled, devices issue DMA requests
> > with PASID need to attach PASIDs to given IOMMU domains. The attach
> > operation involves the following:
> > - Programming the PASID into the device's PASID table
> > - Tracking device domain and the PASID relationship
> > - Managing IOTLB and device TLB invalidations
> > 
> > This patch add attach_dev_pasid functions to the default domain ops
> > which is used by DMA and identity domain types. It could be extended to
> > support other domain types whenever necessary.
> > 
> > Signed-off-by: Lu Baolu 
> > Signed-off-by: Jacob Pan 
> >  drivers/iommu/intel/iommu.c | 72 +++--
> >  1 file changed, 70 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> > index 1c2c92b657c7..75615c105fdf 100644
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -1556,12 +1556,18 @@ static void __iommu_flush_dev_iotlb(struct
> > device_domain_info *info, u64 addr, unsigned int mask)
> >  {
> > u16 sid, qdep;
> > +   ioasid_t pasid;
> >  
> > if (!info || !info->ats_enabled)
> > return;
> >  
> > sid = info->bus << 8 | info->devfn;
> > qdep = info->ats_qdep;
> > +   pasid = iommu_get_pasid_from_domain(info->dev,
> > >domain->domain);  
> 
> No, a simgple domain can be attached to multiple pasids, all need to
> be flushed.
> 
Here is device TLB flush, why would I want to flush PASIDs other than my
own device attached?

At one level up, we do have a list of device to be flushed.
list_for_each_entry(info, >devices, link)
__iommu_flush_dev_iotlb(info, addr, mask);


Note that RID2PASID is not in the pasid_array, its DEVTLB flush also needs
special handling in that the device is doing DMA w/o PASID, thus not aware
of RID2PASID.


> This whole API isn't suitable.
> 
> Jason


Thanks,

Jacob
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-24 Thread Jason Gunthorpe via iommu
On Wed, May 18, 2022 at 11:21:17AM -0700, Jacob Pan wrote:
> On VT-d platforms with scalable mode enabled, devices issue DMA requests
> with PASID need to attach PASIDs to given IOMMU domains. The attach
> operation involves the following:
> - Programming the PASID into the device's PASID table
> - Tracking device domain and the PASID relationship
> - Managing IOTLB and device TLB invalidations
> 
> This patch add attach_dev_pasid functions to the default domain ops which
> is used by DMA and identity domain types. It could be extended to support
> other domain types whenever necessary.
> 
> Signed-off-by: Lu Baolu 
> Signed-off-by: Jacob Pan 
>  drivers/iommu/intel/iommu.c | 72 +++--
>  1 file changed, 70 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index 1c2c92b657c7..75615c105fdf 100644
> +++ b/drivers/iommu/intel/iommu.c
> @@ -1556,12 +1556,18 @@ static void __iommu_flush_dev_iotlb(struct 
> device_domain_info *info,
>   u64 addr, unsigned int mask)
>  {
>   u16 sid, qdep;
> + ioasid_t pasid;
>  
>   if (!info || !info->ats_enabled)
>   return;
>  
>   sid = info->bus << 8 | info->devfn;
>   qdep = info->ats_qdep;
> + pasid = iommu_get_pasid_from_domain(info->dev, >domain->domain);

No, a simgple domain can be attached to multiple pasids, all need to
be flushed.

This whole API isn't suitable.

Jason
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 3/6] iommu/vt-d: Implement domain ops for attach_dev_pasid

2022-05-18 Thread Jacob Pan
On VT-d platforms with scalable mode enabled, devices issue DMA requests
with PASID need to attach PASIDs to given IOMMU domains. The attach
operation involves the following:
- Programming the PASID into the device's PASID table
- Tracking device domain and the PASID relationship
- Managing IOTLB and device TLB invalidations

This patch add attach_dev_pasid functions to the default domain ops which
is used by DMA and identity domain types. It could be extended to support
other domain types whenever necessary.

Signed-off-by: Lu Baolu 
Signed-off-by: Jacob Pan 
---
 drivers/iommu/intel/iommu.c | 72 +++--
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 1c2c92b657c7..75615c105fdf 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1556,12 +1556,18 @@ static void __iommu_flush_dev_iotlb(struct 
device_domain_info *info,
u64 addr, unsigned int mask)
 {
u16 sid, qdep;
+   ioasid_t pasid;
 
if (!info || !info->ats_enabled)
return;
 
sid = info->bus << 8 | info->devfn;
qdep = info->ats_qdep;
+   pasid = iommu_get_pasid_from_domain(info->dev, >domain->domain);
+   if (pasid != INVALID_IOASID) {
+   qi_flush_dev_iotlb_pasid(info->iommu, sid, info->pfsid,
+pasid, qdep, addr, mask);
+   }
qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
   qdep, addr, mask);
 }
@@ -1591,6 +1597,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu 
*iommu,
unsigned int mask = ilog2(aligned_pages);
uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
u16 did = domain->iommu_did[iommu->seq_id];
+   struct iommu_domain *iommu_domain = >domain;
 
BUG_ON(pages == 0);
 
@@ -1599,6 +1606,9 @@ static void iommu_flush_iotlb_psi(struct intel_iommu 
*iommu,
 
if (domain_use_first_level(domain)) {
qi_flush_piotlb(iommu, did, PASID_RID2PASID, addr, pages, ih);
+   /* flush additional kernel DMA PASIDs attached */
+   if (iommu_domain->dma_pasid)
+   qi_flush_piotlb(iommu, did, iommu_domain->dma_pasid, 
addr, pages, ih);
} else {
unsigned long bitmask = aligned_pages - 1;
 
@@ -4255,6 +4265,7 @@ static void __dmar_remove_one_dev_info(struct 
device_domain_info *info)
struct dmar_domain *domain;
struct intel_iommu *iommu;
unsigned long flags;
+   ioasid_t pasid;
 
assert_spin_locked(_domain_lock);
 
@@ -4265,10 +4276,15 @@ static void __dmar_remove_one_dev_info(struct 
device_domain_info *info)
domain = info->domain;
 
if (info->dev && !dev_is_real_dma_subdevice(info->dev)) {
-   if (dev_is_pci(info->dev) && sm_supported(iommu))
+   if (dev_is_pci(info->dev) && sm_supported(iommu)) {
intel_pasid_tear_down_entry(iommu, info->dev,
PASID_RID2PASID, false);
-
+   pasid = iommu_get_pasid_from_domain(info->dev,
+   
>domain->domain);
+   if (pasid != INVALID_IOASID)
+   intel_pasid_tear_down_entry(iommu, info->dev,
+   pasid, false);
+   }
iommu_disable_dev_iotlb(info);
domain_context_clear(info);
intel_pasid_free_table(info->dev);
@@ -4904,6 +4920,56 @@ static void intel_iommu_iotlb_sync_map(struct 
iommu_domain *domain,
}
 }
 
+static int intel_iommu_attach_dev_pasid(struct iommu_domain *domain,
+   struct device *dev,
+   ioasid_t pasid)
+{
+   struct device_domain_info *info = dev_iommu_priv_get(dev);
+   struct dmar_domain *dmar_domain = to_dmar_domain(domain);
+   struct intel_iommu *iommu = info->iommu;
+   unsigned long flags;
+   int ret = 0;
+
+   if (!sm_supported(iommu) || !info)
+   return -ENODEV;
+
+   if (WARN_ON(pasid == PASID_RID2PASID))
+   return -EINVAL;
+
+   spin_lock_irqsave(_domain_lock, flags);
+   spin_lock(>lock);
+   if (hw_pass_through && domain_type_is_si(dmar_domain))
+   ret = intel_pasid_setup_pass_through(iommu, dmar_domain,
+dev, pasid);
+   else if (domain_use_first_level(dmar_domain))
+   ret = domain_setup_first_level(iommu, dmar_domain,
+  dev, pasid);
+   else
+   ret = intel_pasid_setup_second_level(iommu, dmar_domain,
+dev, pasid);
+
+   spin_unlock(>lock);
+