Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-07 Thread Auger Eric
Hi Jacob,

On 9/3/20 11:07 PM, Jacob Pan wrote:
> On Tue, 1 Sep 2020 13:51:26 +0200
> Auger Eric  wrote:
> 
>> Hi Jacob,
>>
>> On 8/22/20 6:35 AM, Jacob Pan wrote:
>>> ioasid_set was introduced as an arbitrary token that are shared by
>>> a  
>> that is
> got it
> 
>>> group of IOASIDs. For example, if IOASID #1 and #2 are allocated
>>> via the same ioasid_set*, they are viewed as to belong to the same
>>> set.  
>> two IOASIDs allocated via the same ioasid_set pointer belong to the
>> same set?
>>>
> yes, better.
> 
>>> For guest SVA usages, system-wide IOASID resources need to be
>>> partitioned such that VMs can have its own quota and being managed  
>> their own
> right,
> 
>>> separately. ioasid_set is the perfect candidate for meeting such
>>> requirements. This patch redefines and extends ioasid_set with the
>>> following new fields:
>>> - Quota
>>> - Reference count
>>> - Storage of its namespace
>>> - The token is stored in the new ioasid_set but with optional types
>>>
>>> ioasid_set level APIs are introduced that wires up these new data.  
>> that wire
> right
> 
>>> Existing users of IOASID APIs are converted where a host IOASID set
>>> is allocated for bare-metal usage.
>>>
>>> Signed-off-by: Liu Yi L 
>>> Signed-off-by: Jacob Pan 
>>> ---
>>>  drivers/iommu/intel/iommu.c |  27 ++-
>>>  drivers/iommu/intel/pasid.h |   1 +
>>>  drivers/iommu/intel/svm.c   |   8 +-
>>>  drivers/iommu/ioasid.c  | 390
>>> +---
>>> include/linux/ioasid.h  |  82 -- 5 files changed, 465
>>> insertions(+), 43 deletions(-)
>>>
>>> diff --git a/drivers/iommu/intel/iommu.c
>>> b/drivers/iommu/intel/iommu.c index a3a0b5c8921d..5813eeaa5edb
>>> 100644 --- a/drivers/iommu/intel/iommu.c
>>> +++ b/drivers/iommu/intel/iommu.c
>>> @@ -42,6 +42,7 @@
>>>  #include 
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -103,6 +104,9 @@
>>>   */
>>>  #define INTEL_IOMMU_PGSIZES(~0xFFFUL)
>>>  
>>> +/* PASIDs used by host SVM */
>>> +struct ioasid_set *host_pasid_set;
>>> +
>>>  static inline int agaw_to_level(int agaw)
>>>  {
>>> return agaw + 2;
>>> @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t
>>> ioasid, void *data)
>>>  * Sanity check the ioasid owner is done at upper layer,
>>> e.g. VFIO
>>>  * We can only free the PASID when all the devices are
>>> unbound. */
>>> -   if (ioasid_find(NULL, ioasid, NULL)) {
>>> -   pr_alert("Cannot free active IOASID %d\n", ioasid);
>>> +   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
>>> +   pr_err("Cannot free IOASID %d, not in system
>>> set\n", ioasid);  
>> not sure the change in the trace is worth. Also you may be more
>> explicit like IOASID %d to be freed cannot be found in the system
>> ioasid set.
> Yes, better. will do.
> 
>> shouldn't it be rate_limited as it is originated from
>> user space?
> virtual command is only used in the guest kernel, not from userspace
> though. But I should add ratelimited to all user originated calls.
Sure I mixed things up. Sorry for the noise

Eric
> 
>>> return;
>>> }
>>> vcmd_free_pasid(iommu, ioasid);
>>> @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
>>> if (ret)
>>> goto free_iommu;
>>>  
>>> +   /* PASID is needed for scalable mode irrespective to SVM */
>>> +   if (intel_iommu_sm) {
>>> +   ioasid_install_capacity(intel_pasid_max_id);
>>> +   /* We should not run out of IOASIDs at boot */
>>> +   host_pasid_set = ioasid_alloc_set(NULL,
>>> PID_MAX_DEFAULT,  
>> s/PID_MAX_DEFAULT/intel_pasid_max_id?
> Not really, when both baremetal and guest SVA are used on the same
> system, we want to to limit the baremetal SVM PASID to the number of
> host processes. host_pasid_set is for baremetal only.
> 
> intel_pasid_max_id would take up the entire PASID resource and leave no
> PASIDs for guest usages.
> 
>>> +
>>> IOASID_SET_TYPE_NULL);  
>> as suggested by jean-Philippe ioasid_set_alloc
>>> +   if (IS_ERR_OR_NULL(host_pasid_set)) {
>>> +   pr_err("Failed to enable host PASID
>>> allocator %lu\n",
>>> +   PTR_ERR(host_pasid_set));  
>> does not sound like the correct error message? failed to allocate the
>> system ioasid_set?
> right
> 
>>> +   intel_iommu_sm = 0;
>>> +   }
>>> +   }
>>> +
>>> /*
>>>  * for each drhd
>>>  *   enable fault log
>>> @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct
>>> dmar_domain *domain, domain->auxd_refcnt--;
>>>  
>>> if (!domain->auxd_refcnt && domain->default_pasid > 0)
>>> -   ioasid_free(domain->default_pasid);
>>> +   ioasid_free(host_pasid_set, domain->default_pasid);
>>>  }
>>>  
>>>  static int aux_domain_add_dev(struct dmar_domain *domain,
>>> @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct
>>> dmar_domain *domain, int pasid;
>>>  
>>> 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-03 Thread Jacob Pan
On Tue, 1 Sep 2020 13:51:26 +0200
Auger Eric  wrote:

> Hi Jacob,
> 
> On 8/22/20 6:35 AM, Jacob Pan wrote:
> > ioasid_set was introduced as an arbitrary token that are shared by
> > a  
> that is
got it

> > group of IOASIDs. For example, if IOASID #1 and #2 are allocated
> > via the same ioasid_set*, they are viewed as to belong to the same
> > set.  
> two IOASIDs allocated via the same ioasid_set pointer belong to the
> same set?
> > 
yes, better.

> > For guest SVA usages, system-wide IOASID resources need to be
> > partitioned such that VMs can have its own quota and being managed  
> their own
right,

> > separately. ioasid_set is the perfect candidate for meeting such
> > requirements. This patch redefines and extends ioasid_set with the
> > following new fields:
> > - Quota
> > - Reference count
> > - Storage of its namespace
> > - The token is stored in the new ioasid_set but with optional types
> > 
> > ioasid_set level APIs are introduced that wires up these new data.  
> that wire
right

> > Existing users of IOASID APIs are converted where a host IOASID set
> > is allocated for bare-metal usage.
> > 
> > Signed-off-by: Liu Yi L 
> > Signed-off-by: Jacob Pan 
> > ---
> >  drivers/iommu/intel/iommu.c |  27 ++-
> >  drivers/iommu/intel/pasid.h |   1 +
> >  drivers/iommu/intel/svm.c   |   8 +-
> >  drivers/iommu/ioasid.c  | 390
> > +---
> > include/linux/ioasid.h  |  82 -- 5 files changed, 465
> > insertions(+), 43 deletions(-)
> > 
> > diff --git a/drivers/iommu/intel/iommu.c
> > b/drivers/iommu/intel/iommu.c index a3a0b5c8921d..5813eeaa5edb
> > 100644 --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -42,6 +42,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -103,6 +104,9 @@
> >   */
> >  #define INTEL_IOMMU_PGSIZES(~0xFFFUL)
> >  
> > +/* PASIDs used by host SVM */
> > +struct ioasid_set *host_pasid_set;
> > +
> >  static inline int agaw_to_level(int agaw)
> >  {
> > return agaw + 2;
> > @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t
> > ioasid, void *data)
> >  * Sanity check the ioasid owner is done at upper layer,
> > e.g. VFIO
> >  * We can only free the PASID when all the devices are
> > unbound. */
> > -   if (ioasid_find(NULL, ioasid, NULL)) {
> > -   pr_alert("Cannot free active IOASID %d\n", ioasid);
> > +   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
> > +   pr_err("Cannot free IOASID %d, not in system
> > set\n", ioasid);  
> not sure the change in the trace is worth. Also you may be more
> explicit like IOASID %d to be freed cannot be found in the system
> ioasid set.
Yes, better. will do.

> shouldn't it be rate_limited as it is originated from
> user space?
virtual command is only used in the guest kernel, not from userspace
though. But I should add ratelimited to all user originated calls.

> > return;
> > }
> > vcmd_free_pasid(iommu, ioasid);
> > @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
> > if (ret)
> > goto free_iommu;
> >  
> > +   /* PASID is needed for scalable mode irrespective to SVM */
> > +   if (intel_iommu_sm) {
> > +   ioasid_install_capacity(intel_pasid_max_id);
> > +   /* We should not run out of IOASIDs at boot */
> > +   host_pasid_set = ioasid_alloc_set(NULL,
> > PID_MAX_DEFAULT,  
> s/PID_MAX_DEFAULT/intel_pasid_max_id?
Not really, when both baremetal and guest SVA are used on the same
system, we want to to limit the baremetal SVM PASID to the number of
host processes. host_pasid_set is for baremetal only.

intel_pasid_max_id would take up the entire PASID resource and leave no
PASIDs for guest usages.

> > +
> > IOASID_SET_TYPE_NULL);  
> as suggested by jean-Philippe ioasid_set_alloc
> > +   if (IS_ERR_OR_NULL(host_pasid_set)) {
> > +   pr_err("Failed to enable host PASID
> > allocator %lu\n",
> > +   PTR_ERR(host_pasid_set));  
> does not sound like the correct error message? failed to allocate the
> system ioasid_set?
right

> > +   intel_iommu_sm = 0;
> > +   }
> > +   }
> > +
> > /*
> >  * for each drhd
> >  *   enable fault log
> > @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct
> > dmar_domain *domain, domain->auxd_refcnt--;
> >  
> > if (!domain->auxd_refcnt && domain->default_pasid > 0)
> > -   ioasid_free(domain->default_pasid);
> > +   ioasid_free(host_pasid_set, domain->default_pasid);
> >  }
> >  
> >  static int aux_domain_add_dev(struct dmar_domain *domain,
> > @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct
> > dmar_domain *domain, int pasid;
> >  
> > /* No private data needed for the default pasid */
> > -   pasid = ioasid_alloc(NULL, PASID_MIN,
> > +   pasid = ioasid_alloc(host_pasid_set, 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-02 Thread Jacob Pan
On Mon, 24 Aug 2020 11:34:29 -0700
Randy Dunlap  wrote:

> On 8/24/20 11:28 AM, Jean-Philippe Brucker wrote:
> >> +/**
> >> + * struct ioasid_set - Meta data about ioasid_set
> >> + * @type: Token types and other features  
> > nit: doesn't follow struct order
> >   
> >> + * @token:Unique to identify an IOASID set
> >> + * @xa:   XArray to store ioasid_set private IDs, can be used for
> >> + *guest-host IOASID mapping, or just a private IOASID 
> >> namespace.
> >> + * @quota:Max number of IOASIDs can be allocated within the set
> >> + * @nr_ioasidsNumber of IOASIDs currently allocated in the set  
> 
>  * @nr_ioasids: Number of IOASIDs currently allocated in the set
> 
got it. thanks!

> >> + * @sid:  ID of the set
> >> + * @ref:  Reference count of the users
> >> + */
> >>  struct ioasid_set {
> >> -  int dummy;
> >> +  void *token;
> >> +  struct xarray xa;
> >> +  int type;
> >> +  int quota;
> >> +  int nr_ioasids;
> >> +  int sid;
> >> +  refcount_t ref;
> >> +  struct rcu_head rcu;
> >>  };  
> 
> 

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


Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-02 Thread Jacob Pan
On Mon, 24 Aug 2020 11:30:47 -0700
Randy Dunlap  wrote:

> On 8/24/20 11:28 AM, Jean-Philippe Brucker wrote:
> >> +/**
> >> + * struct ioasid_data - Meta data about ioasid
> >> + *
> >> + * @id:   Unique ID
> >> + * @users Number of active users
> >> + * @state Track state of the IOASID
> >> + * @set   Meta data of the set this IOASID belongs to
> >> + * @private   Private data associated with the IOASID
> >> + * @rcu   For free after RCU grace period  
> > nit: it would be nicer to follow the struct order  
> 
> and use a ':' after each struct member name, as is done for @id:
> 
Got it, thanks.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-02 Thread Jacob Pan
On Mon, 24 Aug 2020 20:28:48 +0200
Jean-Philippe Brucker  wrote:

> On Fri, Aug 21, 2020 at 09:35:12PM -0700, Jacob Pan wrote:
> > ioasid_set was introduced as an arbitrary token that are shared by a
> > group of IOASIDs. For example, if IOASID #1 and #2 are allocated
> > via the same ioasid_set*, they are viewed as to belong to the same
> > set.
> > 
> > For guest SVA usages, system-wide IOASID resources need to be
> > partitioned such that VMs can have its own quota and being managed
> > separately. ioasid_set is the perfect candidate for meeting such
> > requirements. This patch redefines and extends ioasid_set with the
> > following new fields:
> > - Quota
> > - Reference count
> > - Storage of its namespace
> > - The token is stored in the new ioasid_set but with optional types
> > 
> > ioasid_set level APIs are introduced that wires up these new data.
> > Existing users of IOASID APIs are converted where a host IOASID set
> > is allocated for bare-metal usage.
> > 
> > Signed-off-by: Liu Yi L 
> > Signed-off-by: Jacob Pan 
> > ---
> >  drivers/iommu/intel/iommu.c |  27 ++-
> >  drivers/iommu/intel/pasid.h |   1 +
> >  drivers/iommu/intel/svm.c   |   8 +-
> >  drivers/iommu/ioasid.c  | 390
> > +---
> > include/linux/ioasid.h  |  82 -- 5 files changed, 465
> > insertions(+), 43 deletions(-)
> > 
> > diff --git a/drivers/iommu/intel/iommu.c
> > b/drivers/iommu/intel/iommu.c index a3a0b5c8921d..5813eeaa5edb
> > 100644 --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -42,6 +42,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -103,6 +104,9 @@
> >   */
> >  #define INTEL_IOMMU_PGSIZES(~0xFFFUL)
> >  
> > +/* PASIDs used by host SVM */
> > +struct ioasid_set *host_pasid_set;
> > +
> >  static inline int agaw_to_level(int agaw)
> >  {
> > return agaw + 2;
> > @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t
> > ioasid, void *data)
> >  * Sanity check the ioasid owner is done at upper layer,
> > e.g. VFIO
> >  * We can only free the PASID when all the devices are
> > unbound. */
> > -   if (ioasid_find(NULL, ioasid, NULL)) {
> > -   pr_alert("Cannot free active IOASID %d\n", ioasid);
> > +   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
> > +   pr_err("Cannot free IOASID %d, not in system
> > set\n", ioasid); return;
> > }
> > vcmd_free_pasid(iommu, ioasid);
> > @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
> > if (ret)
> > goto free_iommu;
> >  
> > +   /* PASID is needed for scalable mode irrespective to SVM */
> > +   if (intel_iommu_sm) {
> > +   ioasid_install_capacity(intel_pasid_max_id);
> > +   /* We should not run out of IOASIDs at boot */
> > +   host_pasid_set = ioasid_alloc_set(NULL,
> > PID_MAX_DEFAULT,
> > +
> > IOASID_SET_TYPE_NULL);
> > +   if (IS_ERR_OR_NULL(host_pasid_set)) {
> > +   pr_err("Failed to enable host PASID
> > allocator %lu\n",
> > +   PTR_ERR(host_pasid_set));
> > +   intel_iommu_sm = 0;
> > +   }
> > +   }
> > +
> > /*
> >  * for each drhd
> >  *   enable fault log
> > @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct
> > dmar_domain *domain, domain->auxd_refcnt--;
> >  
> > if (!domain->auxd_refcnt && domain->default_pasid > 0)
> > -   ioasid_free(domain->default_pasid);
> > +   ioasid_free(host_pasid_set, domain->default_pasid);
> >  }
> >  
> >  static int aux_domain_add_dev(struct dmar_domain *domain,
> > @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct
> > dmar_domain *domain, int pasid;
> >  
> > /* No private data needed for the default pasid */
> > -   pasid = ioasid_alloc(NULL, PASID_MIN,
> > +   pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
> >  pci_max_pasids(to_pci_dev(dev))
> > - 1, NULL);
> > if (pasid == INVALID_IOASID) {
> > @@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct
> > dmar_domain *domain, spin_unlock(>lock);
> > spin_unlock_irqrestore(_domain_lock, flags);
> > if (!domain->auxd_refcnt && domain->default_pasid > 0)
> > -   ioasid_free(domain->default_pasid);
> > +   ioasid_free(host_pasid_set, domain->default_pasid);
> >  
> > return ret;
> >  }
> > diff --git a/drivers/iommu/intel/pasid.h
> > b/drivers/iommu/intel/pasid.h index c9850766c3a9..ccdc23446015
> > 100644 --- a/drivers/iommu/intel/pasid.h
> > +++ b/drivers/iommu/intel/pasid.h
> > @@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct
> > pasid_entry *pte) }
> >  
> >  extern u32 intel_pasid_max_id;
> > +extern struct ioasid_set *host_pasid_set;
> >  int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
> >  void intel_pasid_free_id(int pasid);
> >  void 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-01 Thread Lu Baolu

Hi,

On 9/2/20 5:28 AM, Jacob Pan wrote:

On Mon, 24 Aug 2020 10:24:11 +0800
Lu Baolu  wrote:


Hi Jacob,

On 8/22/20 12:35 PM, Jacob Pan wrote:

ioasid_set was introduced as an arbitrary token that are shared by a
group of IOASIDs. For example, if IOASID #1 and #2 are allocated
via the same ioasid_set*, they are viewed as to belong to the same
set.

For guest SVA usages, system-wide IOASID resources need to be
partitioned such that VMs can have its own quota and being managed
separately. ioasid_set is the perfect candidate for meeting such
requirements. This patch redefines and extends ioasid_set with the
following new fields:
- Quota
- Reference count
- Storage of its namespace
- The token is stored in the new ioasid_set but with optional types

ioasid_set level APIs are introduced that wires up these new data.
Existing users of IOASID APIs are converted where a host IOASID set
is allocated for bare-metal usage.

Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
   drivers/iommu/intel/iommu.c |  27 ++-
   drivers/iommu/intel/pasid.h |   1 +
   drivers/iommu/intel/svm.c   |   8 +-
   drivers/iommu/ioasid.c  | 390
+---
include/linux/ioasid.h  |  82 -- 5 files changed, 465
insertions(+), 43 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c
b/drivers/iommu/intel/iommu.c index a3a0b5c8921d..5813eeaa5edb
100644 --- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -42,6 +42,7 @@
   #include 
   #include 
   #include 
+#include 
   #include 
   #include 
   #include 
@@ -103,6 +104,9 @@
*/
   #define INTEL_IOMMU_PGSIZES  (~0xFFFUL)
   
+/* PASIDs used by host SVM */

+struct ioasid_set *host_pasid_set;
+
   static inline int agaw_to_level(int agaw)
   {
return agaw + 2;
@@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t
ioasid, void *data)
 * Sanity check the ioasid owner is done at upper layer,
e.g. VFIO
 * We can only free the PASID when all the devices are
unbound. */
-   if (ioasid_find(NULL, ioasid, NULL)) {
-   pr_alert("Cannot free active IOASID %d\n", ioasid);
+   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
+   pr_err("Cannot free IOASID %d, not in system
set\n", ioasid); return;
}
vcmd_free_pasid(iommu, ioasid);
@@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
if (ret)
goto free_iommu;
   
+	/* PASID is needed for scalable mode irrespective to SVM */

+   if (intel_iommu_sm) {
+   ioasid_install_capacity(intel_pasid_max_id);
+   /* We should not run out of IOASIDs at boot */
+   host_pasid_set = ioasid_alloc_set(NULL,
PID_MAX_DEFAULT,
+
IOASID_SET_TYPE_NULL);
+   if (IS_ERR_OR_NULL(host_pasid_set)) {
+   pr_err("Failed to enable host PASID
allocator %lu\n",
+   PTR_ERR(host_pasid_set));
+   intel_iommu_sm = 0;
+   }
+   }
+
/*
 * for each drhd
 *   enable fault log
@@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct
dmar_domain *domain, domain->auxd_refcnt--;
   
   	if (!domain->auxd_refcnt && domain->default_pasid > 0)

-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
   }
   
   static int aux_domain_add_dev(struct dmar_domain *domain,

@@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct
dmar_domain *domain, int pasid;
   
   		/* No private data needed for the default pasid */

-   pasid = ioasid_alloc(NULL, PASID_MIN,
+   pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
 pci_max_pasids(to_pci_dev(dev))
- 1, NULL);
if (pasid == INVALID_IOASID) {
@@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct
dmar_domain *domain, spin_unlock(>lock);
spin_unlock_irqrestore(_domain_lock, flags);
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
   
   	return ret;

   }
diff --git a/drivers/iommu/intel/pasid.h
b/drivers/iommu/intel/pasid.h index c9850766c3a9..ccdc23446015
100644 --- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct
pasid_entry *pte) }
   
   extern u32 intel_pasid_max_id;

+extern struct ioasid_set *host_pasid_set;
   int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t
gfp); void intel_pasid_free_id(int pasid);
   void *intel_pasid_lookup_id(int pasid);
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 37a9beabc0ca..634e191ca2c3 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -551,7 +551,7 @@ intel_svm_bind_mm(struct device *dev, int
flags, struct svm_dev_ops *ops, pasid_max = 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-01 Thread Jacob Pan
On Mon, 24 Aug 2020 10:24:11 +0800
Lu Baolu  wrote:

> Hi Jacob,
> 
> On 8/22/20 12:35 PM, Jacob Pan wrote:
> > ioasid_set was introduced as an arbitrary token that are shared by a
> > group of IOASIDs. For example, if IOASID #1 and #2 are allocated
> > via the same ioasid_set*, they are viewed as to belong to the same
> > set.
> > 
> > For guest SVA usages, system-wide IOASID resources need to be
> > partitioned such that VMs can have its own quota and being managed
> > separately. ioasid_set is the perfect candidate for meeting such
> > requirements. This patch redefines and extends ioasid_set with the
> > following new fields:
> > - Quota
> > - Reference count
> > - Storage of its namespace
> > - The token is stored in the new ioasid_set but with optional types
> > 
> > ioasid_set level APIs are introduced that wires up these new data.
> > Existing users of IOASID APIs are converted where a host IOASID set
> > is allocated for bare-metal usage.
> > 
> > Signed-off-by: Liu Yi L 
> > Signed-off-by: Jacob Pan 
> > ---
> >   drivers/iommu/intel/iommu.c |  27 ++-
> >   drivers/iommu/intel/pasid.h |   1 +
> >   drivers/iommu/intel/svm.c   |   8 +-
> >   drivers/iommu/ioasid.c  | 390
> > +---
> > include/linux/ioasid.h  |  82 -- 5 files changed, 465
> > insertions(+), 43 deletions(-)
> > 
> > diff --git a/drivers/iommu/intel/iommu.c
> > b/drivers/iommu/intel/iommu.c index a3a0b5c8921d..5813eeaa5edb
> > 100644 --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -42,6 +42,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >   #include 
> >   #include 
> > @@ -103,6 +104,9 @@
> >*/
> >   #define INTEL_IOMMU_PGSIZES   (~0xFFFUL)
> >   
> > +/* PASIDs used by host SVM */
> > +struct ioasid_set *host_pasid_set;
> > +
> >   static inline int agaw_to_level(int agaw)
> >   {
> > return agaw + 2;
> > @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t
> > ioasid, void *data)
> >  * Sanity check the ioasid owner is done at upper layer,
> > e.g. VFIO
> >  * We can only free the PASID when all the devices are
> > unbound. */
> > -   if (ioasid_find(NULL, ioasid, NULL)) {
> > -   pr_alert("Cannot free active IOASID %d\n", ioasid);
> > +   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
> > +   pr_err("Cannot free IOASID %d, not in system
> > set\n", ioasid); return;
> > }
> > vcmd_free_pasid(iommu, ioasid);
> > @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
> > if (ret)
> > goto free_iommu;
> >   
> > +   /* PASID is needed for scalable mode irrespective to SVM */
> > +   if (intel_iommu_sm) {
> > +   ioasid_install_capacity(intel_pasid_max_id);
> > +   /* We should not run out of IOASIDs at boot */
> > +   host_pasid_set = ioasid_alloc_set(NULL,
> > PID_MAX_DEFAULT,
> > +
> > IOASID_SET_TYPE_NULL);
> > +   if (IS_ERR_OR_NULL(host_pasid_set)) {
> > +   pr_err("Failed to enable host PASID
> > allocator %lu\n",
> > +   PTR_ERR(host_pasid_set));
> > +   intel_iommu_sm = 0;
> > +   }
> > +   }
> > +
> > /*
> >  * for each drhd
> >  *   enable fault log
> > @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct
> > dmar_domain *domain, domain->auxd_refcnt--;
> >   
> > if (!domain->auxd_refcnt && domain->default_pasid > 0)
> > -   ioasid_free(domain->default_pasid);
> > +   ioasid_free(host_pasid_set, domain->default_pasid);
> >   }
> >   
> >   static int aux_domain_add_dev(struct dmar_domain *domain,
> > @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct
> > dmar_domain *domain, int pasid;
> >   
> > /* No private data needed for the default pasid */
> > -   pasid = ioasid_alloc(NULL, PASID_MIN,
> > +   pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
> >  pci_max_pasids(to_pci_dev(dev))
> > - 1, NULL);
> > if (pasid == INVALID_IOASID) {
> > @@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct
> > dmar_domain *domain, spin_unlock(>lock);
> > spin_unlock_irqrestore(_domain_lock, flags);
> > if (!domain->auxd_refcnt && domain->default_pasid > 0)
> > -   ioasid_free(domain->default_pasid);
> > +   ioasid_free(host_pasid_set, domain->default_pasid);
> >   
> > return ret;
> >   }
> > diff --git a/drivers/iommu/intel/pasid.h
> > b/drivers/iommu/intel/pasid.h index c9850766c3a9..ccdc23446015
> > 100644 --- a/drivers/iommu/intel/pasid.h
> > +++ b/drivers/iommu/intel/pasid.h
> > @@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct
> > pasid_entry *pte) }
> >   
> >   extern u32 intel_pasid_max_id;
> > +extern struct ioasid_set *host_pasid_set;
> >   int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t
> > gfp); void intel_pasid_free_id(int pasid);
> >   void 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-09-01 Thread Auger Eric
Hi Jacob,

On 8/22/20 6:35 AM, Jacob Pan wrote:
> ioasid_set was introduced as an arbitrary token that are shared by a
that is
> group of IOASIDs. For example, if IOASID #1 and #2 are allocated via the
> same ioasid_set*, they are viewed as to belong to the same set.
two IOASIDs allocated via the same ioasid_set pointer belong to the same
set?
> 
> For guest SVA usages, system-wide IOASID resources need to be
> partitioned such that VMs can have its own quota and being managed
their own
> separately. ioasid_set is the perfect candidate for meeting such
> requirements. This patch redefines and extends ioasid_set with the
> following new fields:
> - Quota
> - Reference count
> - Storage of its namespace
> - The token is stored in the new ioasid_set but with optional types
> 
> ioasid_set level APIs are introduced that wires up these new data.
that wire
> Existing users of IOASID APIs are converted where a host IOASID set is
> allocated for bare-metal usage.
> 
> Signed-off-by: Liu Yi L 
> Signed-off-by: Jacob Pan 
> ---
>  drivers/iommu/intel/iommu.c |  27 ++-
>  drivers/iommu/intel/pasid.h |   1 +
>  drivers/iommu/intel/svm.c   |   8 +-
>  drivers/iommu/ioasid.c  | 390 
> +---
>  include/linux/ioasid.h  |  82 --
>  5 files changed, 465 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index a3a0b5c8921d..5813eeaa5edb 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -42,6 +42,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -103,6 +104,9 @@
>   */
>  #define INTEL_IOMMU_PGSIZES  (~0xFFFUL)
>  
> +/* PASIDs used by host SVM */
> +struct ioasid_set *host_pasid_set;
> +
>  static inline int agaw_to_level(int agaw)
>  {
>   return agaw + 2;
> @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t ioasid, 
> void *data)
>* Sanity check the ioasid owner is done at upper layer, e.g. VFIO
>* We can only free the PASID when all the devices are unbound.
>*/
> - if (ioasid_find(NULL, ioasid, NULL)) {
> - pr_alert("Cannot free active IOASID %d\n", ioasid);
> + if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
> + pr_err("Cannot free IOASID %d, not in system set\n", ioasid);
not sure the change in the trace is worth. Also you may be more explicit
like IOASID %d to be freed cannot be found in the system ioasid set.
shouldn't it be rate_limited as it is originated from user space?
>   return;
>   }
>   vcmd_free_pasid(iommu, ioasid);
> @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
>   if (ret)
>   goto free_iommu;
>  
> + /* PASID is needed for scalable mode irrespective to SVM */
> + if (intel_iommu_sm) {
> + ioasid_install_capacity(intel_pasid_max_id);
> + /* We should not run out of IOASIDs at boot */
> + host_pasid_set = ioasid_alloc_set(NULL, PID_MAX_DEFAULT,
s/PID_MAX_DEFAULT/intel_pasid_max_id?
> + IOASID_SET_TYPE_NULL);
as suggested by jean-Philippe ioasid_set_alloc
> + if (IS_ERR_OR_NULL(host_pasid_set)) {
> + pr_err("Failed to enable host PASID allocator %lu\n",
> + PTR_ERR(host_pasid_set));
does not sound like the correct error message? failed to allocate the
system ioasid_set?
> + intel_iommu_sm = 0;
> + }
> + }
> +
>   /*
>* for each drhd
>*   enable fault log
> @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
> *domain,
>   domain->auxd_refcnt--;
>  
>   if (!domain->auxd_refcnt && domain->default_pasid > 0)
> - ioasid_free(domain->default_pasid);
> + ioasid_free(host_pasid_set, domain->default_pasid);
>  }
>  
>  static int aux_domain_add_dev(struct dmar_domain *domain,
> @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct dmar_domain 
> *domain,
>   int pasid;
>  
>   /* No private data needed for the default pasid */
> - pasid = ioasid_alloc(NULL, PASID_MIN,
> + pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
>pci_max_pasids(to_pci_dev(dev)) - 1,
>NULL);
don't you want to ioasid_set_put() the ioasid_set in
intel_iommu_free_dmars()?
>   if (pasid == INVALID_IOASID) {
> @@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct dmar_domain 
> *domain,
>   spin_unlock(>lock);
>   spin_unlock_irqrestore(_domain_lock, flags);
>   if (!domain->auxd_refcnt && domain->default_pasid > 0)
> - ioasid_free(domain->default_pasid);
> + ioasid_free(host_pasid_set, domain->default_pasid);
>  
>   return ret;
>  }
> diff --git a/drivers/iommu/intel/pasid.h 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-24 Thread Randy Dunlap
On 8/24/20 11:28 AM, Jean-Philippe Brucker wrote:
>> +/**
>> + * struct ioasid_set - Meta data about ioasid_set
>> + * @type:   Token types and other features
> nit: doesn't follow struct order
> 
>> + * @token:  Unique to identify an IOASID set
>> + * @xa: XArray to store ioasid_set private IDs, can be used for
>> + *  guest-host IOASID mapping, or just a private IOASID namespace.
>> + * @quota:  Max number of IOASIDs can be allocated within the set
>> + * @nr_ioasids  Number of IOASIDs currently allocated in the set

 * @nr_ioasids: Number of IOASIDs currently allocated in the set

>> + * @sid:ID of the set
>> + * @ref:Reference count of the users
>> + */
>>  struct ioasid_set {
>> -int dummy;
>> +void *token;
>> +struct xarray xa;
>> +int type;
>> +int quota;
>> +int nr_ioasids;
>> +int sid;
>> +refcount_t ref;
>> +struct rcu_head rcu;
>>  };


-- 
~Randy

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


Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-24 Thread Randy Dunlap
On 8/24/20 11:28 AM, Jean-Philippe Brucker wrote:
>> +/**
>> + * struct ioasid_data - Meta data about ioasid
>> + *
>> + * @id: Unique ID
>> + * @users   Number of active users
>> + * @state   Track state of the IOASID
>> + * @set Meta data of the set this IOASID belongs to
>> + * @private Private data associated with the IOASID
>> + * @rcu For free after RCU grace period
> nit: it would be nicer to follow the struct order

and use a ':' after each struct member name, as is done for @id:

-- 
~Randy

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


Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-24 Thread Jean-Philippe Brucker
On Fri, Aug 21, 2020 at 09:35:12PM -0700, Jacob Pan wrote:
> ioasid_set was introduced as an arbitrary token that are shared by a
> group of IOASIDs. For example, if IOASID #1 and #2 are allocated via the
> same ioasid_set*, they are viewed as to belong to the same set.
> 
> For guest SVA usages, system-wide IOASID resources need to be
> partitioned such that VMs can have its own quota and being managed
> separately. ioasid_set is the perfect candidate for meeting such
> requirements. This patch redefines and extends ioasid_set with the
> following new fields:
> - Quota
> - Reference count
> - Storage of its namespace
> - The token is stored in the new ioasid_set but with optional types
> 
> ioasid_set level APIs are introduced that wires up these new data.
> Existing users of IOASID APIs are converted where a host IOASID set is
> allocated for bare-metal usage.
> 
> Signed-off-by: Liu Yi L 
> Signed-off-by: Jacob Pan 
> ---
>  drivers/iommu/intel/iommu.c |  27 ++-
>  drivers/iommu/intel/pasid.h |   1 +
>  drivers/iommu/intel/svm.c   |   8 +-
>  drivers/iommu/ioasid.c  | 390 
> +---
>  include/linux/ioasid.h  |  82 --
>  5 files changed, 465 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index a3a0b5c8921d..5813eeaa5edb 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -42,6 +42,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -103,6 +104,9 @@
>   */
>  #define INTEL_IOMMU_PGSIZES  (~0xFFFUL)
>  
> +/* PASIDs used by host SVM */
> +struct ioasid_set *host_pasid_set;
> +
>  static inline int agaw_to_level(int agaw)
>  {
>   return agaw + 2;
> @@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t ioasid, 
> void *data)
>* Sanity check the ioasid owner is done at upper layer, e.g. VFIO
>* We can only free the PASID when all the devices are unbound.
>*/
> - if (ioasid_find(NULL, ioasid, NULL)) {
> - pr_alert("Cannot free active IOASID %d\n", ioasid);
> + if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
> + pr_err("Cannot free IOASID %d, not in system set\n", ioasid);
>   return;
>   }
>   vcmd_free_pasid(iommu, ioasid);
> @@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
>   if (ret)
>   goto free_iommu;
>  
> + /* PASID is needed for scalable mode irrespective to SVM */
> + if (intel_iommu_sm) {
> + ioasid_install_capacity(intel_pasid_max_id);
> + /* We should not run out of IOASIDs at boot */
> + host_pasid_set = ioasid_alloc_set(NULL, PID_MAX_DEFAULT,
> + IOASID_SET_TYPE_NULL);
> + if (IS_ERR_OR_NULL(host_pasid_set)) {
> + pr_err("Failed to enable host PASID allocator %lu\n",
> + PTR_ERR(host_pasid_set));
> + intel_iommu_sm = 0;
> + }
> + }
> +
>   /*
>* for each drhd
>*   enable fault log
> @@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
> *domain,
>   domain->auxd_refcnt--;
>  
>   if (!domain->auxd_refcnt && domain->default_pasid > 0)
> - ioasid_free(domain->default_pasid);
> + ioasid_free(host_pasid_set, domain->default_pasid);
>  }
>  
>  static int aux_domain_add_dev(struct dmar_domain *domain,
> @@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct dmar_domain 
> *domain,
>   int pasid;
>  
>   /* No private data needed for the default pasid */
> - pasid = ioasid_alloc(NULL, PASID_MIN,
> + pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
>pci_max_pasids(to_pci_dev(dev)) - 1,
>NULL);
>   if (pasid == INVALID_IOASID) {
> @@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct dmar_domain 
> *domain,
>   spin_unlock(>lock);
>   spin_unlock_irqrestore(_domain_lock, flags);
>   if (!domain->auxd_refcnt && domain->default_pasid > 0)
> - ioasid_free(domain->default_pasid);
> + ioasid_free(host_pasid_set, domain->default_pasid);
>  
>   return ret;
>  }
> diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
> index c9850766c3a9..ccdc23446015 100644
> --- a/drivers/iommu/intel/pasid.h
> +++ b/drivers/iommu/intel/pasid.h
> @@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct pasid_entry 
> *pte)
>  }
>  
>  extern u32 intel_pasid_max_id;
> +extern struct ioasid_set *host_pasid_set;
>  int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
>  void intel_pasid_free_id(int pasid);
>  void *intel_pasid_lookup_id(int pasid);
> diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
> index 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-23 Thread Lu Baolu

Hi Jacob,

On 8/22/20 12:35 PM, Jacob Pan wrote:

ioasid_set was introduced as an arbitrary token that are shared by a
group of IOASIDs. For example, if IOASID #1 and #2 are allocated via the
same ioasid_set*, they are viewed as to belong to the same set.

For guest SVA usages, system-wide IOASID resources need to be
partitioned such that VMs can have its own quota and being managed
separately. ioasid_set is the perfect candidate for meeting such
requirements. This patch redefines and extends ioasid_set with the
following new fields:
- Quota
- Reference count
- Storage of its namespace
- The token is stored in the new ioasid_set but with optional types

ioasid_set level APIs are introduced that wires up these new data.
Existing users of IOASID APIs are converted where a host IOASID set is
allocated for bare-metal usage.

Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
  drivers/iommu/intel/iommu.c |  27 ++-
  drivers/iommu/intel/pasid.h |   1 +
  drivers/iommu/intel/svm.c   |   8 +-
  drivers/iommu/ioasid.c  | 390 +---
  include/linux/ioasid.h  |  82 --
  5 files changed, 465 insertions(+), 43 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index a3a0b5c8921d..5813eeaa5edb 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -42,6 +42,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -103,6 +104,9 @@
   */
  #define INTEL_IOMMU_PGSIZES   (~0xFFFUL)
  
+/* PASIDs used by host SVM */

+struct ioasid_set *host_pasid_set;
+
  static inline int agaw_to_level(int agaw)
  {
return agaw + 2;
@@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t ioasid, void 
*data)
 * Sanity check the ioasid owner is done at upper layer, e.g. VFIO
 * We can only free the PASID when all the devices are unbound.
 */
-   if (ioasid_find(NULL, ioasid, NULL)) {
-   pr_alert("Cannot free active IOASID %d\n", ioasid);
+   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
+   pr_err("Cannot free IOASID %d, not in system set\n", ioasid);
return;
}
vcmd_free_pasid(iommu, ioasid);
@@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
if (ret)
goto free_iommu;
  
+	/* PASID is needed for scalable mode irrespective to SVM */

+   if (intel_iommu_sm) {
+   ioasid_install_capacity(intel_pasid_max_id);
+   /* We should not run out of IOASIDs at boot */
+   host_pasid_set = ioasid_alloc_set(NULL, PID_MAX_DEFAULT,
+   IOASID_SET_TYPE_NULL);
+   if (IS_ERR_OR_NULL(host_pasid_set)) {
+   pr_err("Failed to enable host PASID allocator %lu\n",
+   PTR_ERR(host_pasid_set));
+   intel_iommu_sm = 0;
+   }
+   }
+
/*
 * for each drhd
 *   enable fault log
@@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
*domain,
domain->auxd_refcnt--;
  
  	if (!domain->auxd_refcnt && domain->default_pasid > 0)

-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
  }
  
  static int aux_domain_add_dev(struct dmar_domain *domain,

@@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
int pasid;
  
  		/* No private data needed for the default pasid */

-   pasid = ioasid_alloc(NULL, PASID_MIN,
+   pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
 pci_max_pasids(to_pci_dev(dev)) - 1,
 NULL);
if (pasid == INVALID_IOASID) {
@@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
spin_unlock(>lock);
spin_unlock_irqrestore(_domain_lock, flags);
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
  
  	return ret;

  }
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index c9850766c3a9..ccdc23446015 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct pasid_entry 
*pte)
  }
  
  extern u32 intel_pasid_max_id;

+extern struct ioasid_set *host_pasid_set;
  int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
  void intel_pasid_free_id(int pasid);
  void *intel_pasid_lookup_id(int pasid);
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 37a9beabc0ca..634e191ca2c3 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -551,7 +551,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct 

Re: [PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-22 Thread kernel test robot
Hi Jacob,

I love your patch! Perhaps something to improve:

[auto build test WARNING on iommu/next]
[also build test WARNING on linux/master linus/master v5.9-rc1 next-20200821]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Jacob-Pan/IOASID-extensions-for-guest-SVA/20200822-123111
base:   https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce (this is a W=1 build):
# save the attached .config to linux build tree
make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All warnings (new ones prefixed by >>):

   drivers/iommu/ioasid.c: In function 'ioasid_get_capacity':
>> drivers/iommu/ioasid.c:50:10: warning: old-style function definition 
>> [-Wold-style-definition]
  50 | ioasid_t ioasid_get_capacity()
 |  ^~~
   drivers/iommu/ioasid.c: At top level:
>> drivers/iommu/ioasid.c:577:6: warning: no previous prototype for 
>> 'ioasid_set_get' [-Wmissing-prototypes]
 577 | void ioasid_set_get(struct ioasid_set *set)
 |  ^~

# 
https://github.com/0day-ci/linux/commit/59b6f319b27588b2a8a0268a4f4f09f7be458861
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Jacob-Pan/IOASID-extensions-for-guest-SVA/20200822-123111
git checkout 59b6f319b27588b2a8a0268a4f4f09f7be458861
vim +50 drivers/iommu/ioasid.c

49  
  > 50  ioasid_t ioasid_get_capacity()
51  {
52  return ioasid_capacity;
53  }
54  EXPORT_SYMBOL_GPL(ioasid_get_capacity);
55  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v2 3/9] iommu/ioasid: Introduce ioasid_set APIs

2020-08-22 Thread Jacob Pan
ioasid_set was introduced as an arbitrary token that are shared by a
group of IOASIDs. For example, if IOASID #1 and #2 are allocated via the
same ioasid_set*, they are viewed as to belong to the same set.

For guest SVA usages, system-wide IOASID resources need to be
partitioned such that VMs can have its own quota and being managed
separately. ioasid_set is the perfect candidate for meeting such
requirements. This patch redefines and extends ioasid_set with the
following new fields:
- Quota
- Reference count
- Storage of its namespace
- The token is stored in the new ioasid_set but with optional types

ioasid_set level APIs are introduced that wires up these new data.
Existing users of IOASID APIs are converted where a host IOASID set is
allocated for bare-metal usage.

Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
 drivers/iommu/intel/iommu.c |  27 ++-
 drivers/iommu/intel/pasid.h |   1 +
 drivers/iommu/intel/svm.c   |   8 +-
 drivers/iommu/ioasid.c  | 390 +---
 include/linux/ioasid.h  |  82 --
 5 files changed, 465 insertions(+), 43 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index a3a0b5c8921d..5813eeaa5edb 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -103,6 +104,9 @@
  */
 #define INTEL_IOMMU_PGSIZES(~0xFFFUL)
 
+/* PASIDs used by host SVM */
+struct ioasid_set *host_pasid_set;
+
 static inline int agaw_to_level(int agaw)
 {
return agaw + 2;
@@ -3103,8 +3107,8 @@ static void intel_vcmd_ioasid_free(ioasid_t ioasid, void 
*data)
 * Sanity check the ioasid owner is done at upper layer, e.g. VFIO
 * We can only free the PASID when all the devices are unbound.
 */
-   if (ioasid_find(NULL, ioasid, NULL)) {
-   pr_alert("Cannot free active IOASID %d\n", ioasid);
+   if (IS_ERR(ioasid_find(host_pasid_set, ioasid, NULL))) {
+   pr_err("Cannot free IOASID %d, not in system set\n", ioasid);
return;
}
vcmd_free_pasid(iommu, ioasid);
@@ -3288,6 +3292,19 @@ static int __init init_dmars(void)
if (ret)
goto free_iommu;
 
+   /* PASID is needed for scalable mode irrespective to SVM */
+   if (intel_iommu_sm) {
+   ioasid_install_capacity(intel_pasid_max_id);
+   /* We should not run out of IOASIDs at boot */
+   host_pasid_set = ioasid_alloc_set(NULL, PID_MAX_DEFAULT,
+   IOASID_SET_TYPE_NULL);
+   if (IS_ERR_OR_NULL(host_pasid_set)) {
+   pr_err("Failed to enable host PASID allocator %lu\n",
+   PTR_ERR(host_pasid_set));
+   intel_iommu_sm = 0;
+   }
+   }
+
/*
 * for each drhd
 *   enable fault log
@@ -5149,7 +5166,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
*domain,
domain->auxd_refcnt--;
 
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
 }
 
 static int aux_domain_add_dev(struct dmar_domain *domain,
@@ -5167,7 +5184,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
int pasid;
 
/* No private data needed for the default pasid */
-   pasid = ioasid_alloc(NULL, PASID_MIN,
+   pasid = ioasid_alloc(host_pasid_set, PASID_MIN,
 pci_max_pasids(to_pci_dev(dev)) - 1,
 NULL);
if (pasid == INVALID_IOASID) {
@@ -5210,7 +5227,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
spin_unlock(>lock);
spin_unlock_irqrestore(_domain_lock, flags);
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   ioasid_free(domain->default_pasid);
+   ioasid_free(host_pasid_set, domain->default_pasid);
 
return ret;
 }
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index c9850766c3a9..ccdc23446015 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -99,6 +99,7 @@ static inline bool pasid_pte_is_present(struct pasid_entry 
*pte)
 }
 
 extern u32 intel_pasid_max_id;
+extern struct ioasid_set *host_pasid_set;
 int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
 void intel_pasid_free_id(int pasid);
 void *intel_pasid_lookup_id(int pasid);
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 37a9beabc0ca..634e191ca2c3 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -551,7 +551,7 @@ intel_svm_bind_mm(struct device *dev, int flags, struct 
svm_dev_ops *ops,
pasid_max =