diff mbox series

[v3,16/19] iommu/amd: Add domain_alloc_user based domain allocation

Message ID 20230923012511.10379-17-joao.m.martins@oracle.com (mailing list archive)
State New, archived
Headers show
Series IOMMUFD Dirty Tracking | expand

Commit Message

Joao Martins Sept. 23, 2023, 1:25 a.m. UTC
Add the domain_alloc_user op implementation. To that end, refactor
amd_iommu_domain_alloc() to receive a dev pointer and flags, while
renaming it to .. such that it becomes a common function shared with
domain_alloc_user() implementation. The sole difference with
domain_alloc_user() is that we initialize also other fields that
iommu_domain_alloc() does. It lets it return the iommu domain
correctly initialized in one function.

This is in preparation to add dirty enforcement on AMD implementation
of domain_alloc_user.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
---
 drivers/iommu/amd/iommu.c | 46 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 43 insertions(+), 3 deletions(-)

Comments

Suravee Suthikulpanit Oct. 17, 2023, 2 a.m. UTC | #1
Hi Joao,

On 9/23/2023 8:25 AM, Joao Martins wrote:
> Add the domain_alloc_user op implementation. To that end, refactor
> amd_iommu_domain_alloc() to receive a dev pointer and flags, while
> renaming it to .. such that it becomes a common function shared with
> domain_alloc_user() implementation. The sole difference with
> domain_alloc_user() is that we initialize also other fields that
> iommu_domain_alloc() does. It lets it return the iommu domain
> correctly initialized in one function.
> 
> This is in preparation to add dirty enforcement on AMD implementation
> of domain_alloc_user.
> 
> Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
> ---
>   drivers/iommu/amd/iommu.c | 46 ++++++++++++++++++++++++++++++++++++---
>   1 file changed, 43 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index 95bd7c25ba6f..af36c627022f 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -37,6 +37,7 @@
>   #include <asm/iommu.h>
>   #include <asm/gart.h>
>   #include <asm/dma.h>
> +#include <uapi/linux/iommufd.h>
>   
>   #include "amd_iommu.h"
>   #include "../dma-iommu.h"
> @@ -2155,7 +2156,10 @@ static inline u64 dma_max_address(void)
>   	return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1);
>   }
>   
> -static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
> +static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
> +						  struct amd_iommu *iommu,
> +						  struct device *dev,
> +						  u32 flags)

Instead of passing in the struct amd_iommu here, what if we just derive 
it in the do_iommu_domain_alloc() as needed? This way, we don't need to 
... (see below)

>   {
>   	struct protection_domain *domain;
>   
> @@ -2164,19 +2168,54 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
>   	 * default to use IOMMU_DOMAIN_DMA[_FQ].
>   	 */
>   	if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY))
> -		return NULL;
> +		return ERR_PTR(-EINVAL);
>   
>   	domain = protection_domain_alloc(type);
>   	if (!domain)
> -		return NULL;
> +		return ERR_PTR(-ENOMEM);
>   
>   	domain->domain.geometry.aperture_start = 0;
>   	domain->domain.geometry.aperture_end   = dma_max_address();
>   	domain->domain.geometry.force_aperture = true;
>   
> +	if (dev) {
> +		domain->domain.type = type;
> +		domain->domain.pgsize_bitmap =
> +			iommu->iommu.ops->pgsize_bitmap;
> +		domain->domain.ops =
> +			iommu->iommu.ops->default_domain_ops;
> +	}
> +
>   	return &domain->domain;
>   }
>   
> +static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
> +{
> +	struct iommu_domain *domain;
> +
> +	domain = do_iommu_domain_alloc(type, NULL, NULL, 0);

... pass iommu = NULL here unnecessarily.

> +	if (IS_ERR(domain))
> +		return NULL;
> +
> +	return domain;
> +}
> +
> +static struct iommu_domain *amd_iommu_domain_alloc_user(struct device *dev,
> +							u32 flags)
> +{
> +	unsigned int type = IOMMU_DOMAIN_UNMANAGED;
> +	struct amd_iommu *iommu;
> +
> +	iommu = rlookup_amd_iommu(dev);
> +	if (!iommu)
> +		return ERR_PTR(-ENODEV);

We should not need to derive this here.

Other than this part.

Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>

Thanks,
Suravee
Joao Martins Oct. 17, 2023, 9:07 a.m. UTC | #2
On 17/10/2023 03:00, Suthikulpanit, Suravee wrote:
> Hi Joao,
> 
> On 9/23/2023 8:25 AM, Joao Martins wrote:
>> Add the domain_alloc_user op implementation. To that end, refactor
>> amd_iommu_domain_alloc() to receive a dev pointer and flags, while
>> renaming it to .. such that it becomes a common function shared with
>> domain_alloc_user() implementation. The sole difference with
>> domain_alloc_user() is that we initialize also other fields that
>> iommu_domain_alloc() does. It lets it return the iommu domain
>> correctly initialized in one function.
>>
>> This is in preparation to add dirty enforcement on AMD implementation
>> of domain_alloc_user.
>>
>> Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
>> ---
>>   drivers/iommu/amd/iommu.c | 46 ++++++++++++++++++++++++++++++++++++---
>>   1 file changed, 43 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
>> index 95bd7c25ba6f..af36c627022f 100644
>> --- a/drivers/iommu/amd/iommu.c
>> +++ b/drivers/iommu/amd/iommu.c
>> @@ -37,6 +37,7 @@
>>   #include <asm/iommu.h>
>>   #include <asm/gart.h>
>>   #include <asm/dma.h>
>> +#include <uapi/linux/iommufd.h>
>>     #include "amd_iommu.h"
>>   #include "../dma-iommu.h"
>> @@ -2155,7 +2156,10 @@ static inline u64 dma_max_address(void)
>>       return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1);
>>   }
>>   -static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
>> +static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
>> +                          struct amd_iommu *iommu,
>> +                          struct device *dev,
>> +                          u32 flags)
> 
> Instead of passing in the struct amd_iommu here, what if we just derive it in
> the do_iommu_domain_alloc() as needed? This way, we don't need to ... (see below)
> 
Hmm, you mean to derive amd_iommu from the dev pointer. Yeah, sounds good.

>>   {
>>       struct protection_domain *domain;
>>   @@ -2164,19 +2168,54 @@ static struct iommu_domain
>> *amd_iommu_domain_alloc(unsigned type)
>>        * default to use IOMMU_DOMAIN_DMA[_FQ].
>>        */
>>       if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY))
>> -        return NULL;
>> +        return ERR_PTR(-EINVAL);
>>         domain = protection_domain_alloc(type);
>>       if (!domain)
>> -        return NULL;
>> +        return ERR_PTR(-ENOMEM);
>>         domain->domain.geometry.aperture_start = 0;
>>       domain->domain.geometry.aperture_end   = dma_max_address();
>>       domain->domain.geometry.force_aperture = true;
>>   +    if (dev) {
>> +        domain->domain.type = type;
>> +        domain->domain.pgsize_bitmap =
>> +            iommu->iommu.ops->pgsize_bitmap;
>> +        domain->domain.ops =
>> +            iommu->iommu.ops->default_domain_ops;
>> +    }
>> +
>>       return &domain->domain;
>>   }
>>   +static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
>> +{
>> +    struct iommu_domain *domain;
>> +
>> +    domain = do_iommu_domain_alloc(type, NULL, NULL, 0);
> 
> ... pass iommu = NULL here unnecessarily.
> 
OK

>> +    if (IS_ERR(domain))
>> +        return NULL;
>> +
>> +    return domain;
>> +}
>> +
>> +static struct iommu_domain *amd_iommu_domain_alloc_user(struct device *dev,
>> +                            u32 flags)
>> +{
>> +    unsigned int type = IOMMU_DOMAIN_UNMANAGED;
>> +    struct amd_iommu *iommu;
>> +
>> +    iommu = rlookup_amd_iommu(dev);
>> +    if (!iommu)
>> +        return ERR_PTR(-ENODEV);
> 
> We should not need to derive this here.
> 
> Other than this part.
> 

OK, will do.

> Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> 
Thanks!

Here's the diff

diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index af36c627022f..cfc7d2992aa6 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2157,11 +2157,17 @@ static inline u64 dma_max_address(void)
 }

 static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
-                                                 struct amd_iommu *iommu,
                                                  struct device *dev,
                                                  u32 flags)
 {
        struct protection_domain *domain;
+       struct amd_iommu *iommu = NULL;
+
+       if (dev) {
+               iommu = rlookup_amd_iommu(dev);
+               if (!iommu)
+                       return ERR_PTR(-ENODEV);
+       }

        /*
         * Since DTE[Mode]=0 is prohibited on SNP-enabled system,
@@ -2178,7 +2184,7 @@ static struct iommu_domain *do_iommu_domain_alloc(unsigned
int type,
        domain->domain.geometry.aperture_end   = dma_max_address();
        domain->domain.geometry.force_aperture = true;

-       if (dev) {
+       if (iommu) {
                domain->domain.type = type;
                domain->domain.pgsize_bitmap =
                        iommu->iommu.ops->pgsize_bitmap;
@@ -2193,7 +2199,7 @@ static struct iommu_domain
*amd_iommu_domain_alloc(unsigned type)
 {
        struct iommu_domain *domain;

-       domain = do_iommu_domain_alloc(type, NULL, NULL, 0);
+       domain = do_iommu_domain_alloc(type, NULL, 0);
        if (IS_ERR(domain))
                return NULL;

@@ -2204,16 +2210,11 @@ static struct iommu_domain
*amd_iommu_domain_alloc_user(struct device *dev,
                                                        u32 flags)
 {
        unsigned int type = IOMMU_DOMAIN_UNMANAGED;
-       struct amd_iommu *iommu;
-
-       iommu = rlookup_amd_iommu(dev);
-       if (!iommu)
-               return ERR_PTR(-ENODEV);

        if (flags & IOMMU_HWPT_ALLOC_NEST_PARENT)
                return ERR_PTR(-EOPNOTSUPP);

-       return do_iommu_domain_alloc(type, iommu, dev, flags);
+       return do_iommu_domain_alloc(type, dev, flags);
 }
Jason Gunthorpe Oct. 17, 2023, 1:10 p.m. UTC | #3
On Tue, Oct 17, 2023 at 10:07:11AM +0100, Joao Martins wrote:
> 
>  static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
> -                                                 struct amd_iommu *iommu,
>                                                   struct device *dev,
>                                                   u32 flags)
>  {
>         struct protection_domain *domain;
> +       struct amd_iommu *iommu = NULL;
> +
> +       if (dev) {
> +               iommu = rlookup_amd_iommu(dev);
> +               if (!iommu)

This really shouldn't be rlookup_amd_iommu, didn't the series fixing
this get merged?

Jason
Joao Martins Oct. 17, 2023, 2:14 p.m. UTC | #4
On 17/10/2023 14:10, Jason Gunthorpe wrote:
> On Tue, Oct 17, 2023 at 10:07:11AM +0100, Joao Martins wrote:
>>
>>  static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
>> -                                                 struct amd_iommu *iommu,
>>                                                   struct device *dev,
>>                                                   u32 flags)
>>  {
>>         struct protection_domain *domain;
>> +       struct amd_iommu *iommu = NULL;
>> +
>> +       if (dev) {
>> +               iommu = rlookup_amd_iommu(dev);
>> +               if (!iommu)
> 
> This really shouldn't be rlookup_amd_iommu, didn't the series fixing
> this get merged?

From the latest linux-next, it's still there.
Joao Martins Oct. 17, 2023, 2:37 p.m. UTC | #5
On 17/10/2023 15:14, Joao Martins wrote:
> On 17/10/2023 14:10, Jason Gunthorpe wrote:
>> On Tue, Oct 17, 2023 at 10:07:11AM +0100, Joao Martins wrote:
>>>
>>>  static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
>>> -                                                 struct amd_iommu *iommu,
>>>                                                   struct device *dev,
>>>                                                   u32 flags)
>>>  {
>>>         struct protection_domain *domain;
>>> +       struct amd_iommu *iommu = NULL;
>>> +
>>> +       if (dev) {
>>> +               iommu = rlookup_amd_iommu(dev);
>>> +               if (!iommu)
>>
>> This really shouldn't be rlookup_amd_iommu, didn't the series fixing
>> this get merged?
> 
> From the latest linux-next, it's still there.
> 
I'm assuming you refer to this new helper:

https://lore.kernel.org/linux-iommu/20231013151652.6008-3-vasant.hegde@amd.com/

But it's part 3 out of a 4-part multi-series; and only the first part has been
merged.

	Joao
Jason Gunthorpe Oct. 17, 2023, 3:32 p.m. UTC | #6
On Tue, Oct 17, 2023 at 03:37:47PM +0100, Joao Martins wrote:
> On 17/10/2023 15:14, Joao Martins wrote:
> > On 17/10/2023 14:10, Jason Gunthorpe wrote:
> >> On Tue, Oct 17, 2023 at 10:07:11AM +0100, Joao Martins wrote:
> >>>
> >>>  static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
> >>> -                                                 struct amd_iommu *iommu,
> >>>                                                   struct device *dev,
> >>>                                                   u32 flags)
> >>>  {
> >>>         struct protection_domain *domain;
> >>> +       struct amd_iommu *iommu = NULL;
> >>> +
> >>> +       if (dev) {
> >>> +               iommu = rlookup_amd_iommu(dev);
> >>> +               if (!iommu)
> >>
> >> This really shouldn't be rlookup_amd_iommu, didn't the series fixing
> >> this get merged?
> > 
> > From the latest linux-next, it's still there.
> > 
> I'm assuming you refer to this new helper:
> 
> https://lore.kernel.org/linux-iommu/20231013151652.6008-3-vasant.hegde@amd.com/
> 
> But it's part 3 out of a 4-part multi-series; and only the first part has been
> merged.

Okay, then nothing to do here :\

Jason
Vasant Hegde Oct. 18, 2023, 8:29 a.m. UTC | #7
On 10/17/2023 8:07 PM, Joao Martins wrote:
> On 17/10/2023 15:14, Joao Martins wrote:
>> On 17/10/2023 14:10, Jason Gunthorpe wrote:
>>> On Tue, Oct 17, 2023 at 10:07:11AM +0100, Joao Martins wrote:
>>>>
>>>>  static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
>>>> -                                                 struct amd_iommu *iommu,
>>>>                                                   struct device *dev,
>>>>                                                   u32 flags)
>>>>  {
>>>>         struct protection_domain *domain;
>>>> +       struct amd_iommu *iommu = NULL;
>>>> +
>>>> +       if (dev) {
>>>> +               iommu = rlookup_amd_iommu(dev);
>>>> +               if (!iommu)
>>>
>>> This really shouldn't be rlookup_amd_iommu, didn't the series fixing
>>> this get merged?
>>
>> From the latest linux-next, it's still there.
>>
> I'm assuming you refer to this new helper:
> 
> https://lore.kernel.org/linux-iommu/20231013151652.6008-3-vasant.hegde@amd.com/
> 
> But it's part 3 out of a 4-part multi-series; and only the first part has been
> merged.

That's correct. Part 2 parts are merged. For now you can use
rlookup_amd_iommu(). I can fix it later.

-Vasant
diff mbox series

Patch

diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 95bd7c25ba6f..af36c627022f 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -37,6 +37,7 @@ 
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/dma.h>
+#include <uapi/linux/iommufd.h>
 
 #include "amd_iommu.h"
 #include "../dma-iommu.h"
@@ -2155,7 +2156,10 @@  static inline u64 dma_max_address(void)
 	return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1);
 }
 
-static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
+static struct iommu_domain *do_iommu_domain_alloc(unsigned int type,
+						  struct amd_iommu *iommu,
+						  struct device *dev,
+						  u32 flags)
 {
 	struct protection_domain *domain;
 
@@ -2164,19 +2168,54 @@  static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
 	 * default to use IOMMU_DOMAIN_DMA[_FQ].
 	 */
 	if (amd_iommu_snp_en && (type == IOMMU_DOMAIN_IDENTITY))
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	domain = protection_domain_alloc(type);
 	if (!domain)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	domain->domain.geometry.aperture_start = 0;
 	domain->domain.geometry.aperture_end   = dma_max_address();
 	domain->domain.geometry.force_aperture = true;
 
+	if (dev) {
+		domain->domain.type = type;
+		domain->domain.pgsize_bitmap =
+			iommu->iommu.ops->pgsize_bitmap;
+		domain->domain.ops =
+			iommu->iommu.ops->default_domain_ops;
+	}
+
 	return &domain->domain;
 }
 
+static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
+{
+	struct iommu_domain *domain;
+
+	domain = do_iommu_domain_alloc(type, NULL, NULL, 0);
+	if (IS_ERR(domain))
+		return NULL;
+
+	return domain;
+}
+
+static struct iommu_domain *amd_iommu_domain_alloc_user(struct device *dev,
+							u32 flags)
+{
+	unsigned int type = IOMMU_DOMAIN_UNMANAGED;
+	struct amd_iommu *iommu;
+
+	iommu = rlookup_amd_iommu(dev);
+	if (!iommu)
+		return ERR_PTR(-ENODEV);
+
+	if (flags & IOMMU_HWPT_ALLOC_NEST_PARENT)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return do_iommu_domain_alloc(type, iommu, dev, flags);
+}
+
 static void amd_iommu_domain_free(struct iommu_domain *dom)
 {
 	struct protection_domain *domain;
@@ -2464,6 +2503,7 @@  static bool amd_iommu_enforce_cache_coherency(struct iommu_domain *domain)
 const struct iommu_ops amd_iommu_ops = {
 	.capable = amd_iommu_capable,
 	.domain_alloc = amd_iommu_domain_alloc,
+	.domain_alloc_user = amd_iommu_domain_alloc_user,
 	.probe_device = amd_iommu_probe_device,
 	.release_device = amd_iommu_release_device,
 	.probe_finalize = amd_iommu_probe_finalize,