diff mbox series

[iommufd,2/9] vfio/type1: Check that every device supports IOMMU_CAP_INTR_REMAP

Message ID 2-v1-9e466539c244+47b5-secure_msi_jgg@nvidia.com (mailing list archive)
State New, archived
Headers show
Series Remove IOMMU_CAP_INTR_REMAP | expand

Commit Message

Jason Gunthorpe Dec. 8, 2022, 8:26 p.m. UTC
iommu_group_for_each_dev() exits the loop at the first callback that
returns 1 - thus returning 1 fails to check the rest of the devices in the
group.

msi_remap (aka secure MSI) requires that all the devices in the group
support it, not just any one. This is only a theoretical problem as no
current drivers will have different secure MSI properties within a group.

Make vfio_iommu_device_secure_msi() reduce AND across all the devices.

Fixes: eed20c782aea ("vfio/type1: Simplify bus_type determination")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/vfio/vfio_iommu_type1.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

Comments

Alex Williamson Dec. 8, 2022, 9:48 p.m. UTC | #1
On Thu,  8 Dec 2022 16:26:29 -0400
Jason Gunthorpe <jgg@nvidia.com> wrote:

> iommu_group_for_each_dev() exits the loop at the first callback that
> returns 1 - thus returning 1 fails to check the rest of the devices in the
> group.
> 
> msi_remap (aka secure MSI) requires that all the devices in the group
> support it, not just any one. This is only a theoretical problem as no
> current drivers will have different secure MSI properties within a group.

Which is exactly how Robin justified the behavior in the referenced
commit:

  As with domains, any capability must in practice be consistent for
  devices in a given group - and after all it's still the same
  capability which was expected to be consistent across an entire bus!
  - so there's no need for any complicated validation.

That suggests to me that it's intentional that we break if any device
supports the capability and therefore this isn't so much a "Fixes:", as
it is a refactoring expressly to support msi_device_has_secure_msi(),
which cannot make these sort of assumptions as a non-group API.  Thanks,

Alex

> Make vfio_iommu_device_secure_msi() reduce AND across all the devices.
> 
> Fixes: eed20c782aea ("vfio/type1: Simplify bus_type determination")
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  drivers/vfio/vfio_iommu_type1.c | 17 +++++++++++------
>  1 file changed, 11 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 23c24fe98c00d4..3025b4e643c135 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -2160,10 +2160,12 @@ static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu,
>  	list_splice_tail(iova_copy, iova);
>  }
>  
> -/* Redundantly walks non-present capabilities to simplify caller */
> -static int vfio_iommu_device_capable(struct device *dev, void *data)
> +static int vfio_iommu_device_secure_msi(struct device *dev, void *data)
>  {
> -	return device_iommu_capable(dev, (enum iommu_cap)data);
> +	bool *secure_msi = data;
> +
> +	*secure_msi &= device_iommu_capable(dev, IOMMU_CAP_INTR_REMAP);
> +	return 0;
>  }
>  
>  static int vfio_iommu_domain_alloc(struct device *dev, void *data)
> @@ -2278,9 +2280,12 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>  	INIT_LIST_HEAD(&domain->group_list);
>  	list_add(&group->next, &domain->group_list);
>  
> -	msi_remap = irq_domain_check_msi_remap() ||
> -		    iommu_group_for_each_dev(iommu_group, (void *)IOMMU_CAP_INTR_REMAP,
> -					     vfio_iommu_device_capable);
> +	msi_remap = irq_domain_check_msi_remap();
> +	if (!msi_remap) {
> +		msi_remap = true;
> +		iommu_group_for_each_dev(iommu_group, &msi_remap,
> +					 vfio_iommu_device_secure_msi);
> +	}
>  
>  	if (!allow_unsafe_interrupts && !msi_remap) {
>  		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
Jason Gunthorpe Dec. 9, 2022, 12:44 a.m. UTC | #2
On Thu, Dec 08, 2022 at 02:48:25PM -0700, Alex Williamson wrote:
> On Thu,  8 Dec 2022 16:26:29 -0400
> Jason Gunthorpe <jgg@nvidia.com> wrote:
> 
> > iommu_group_for_each_dev() exits the loop at the first callback that
> > returns 1 - thus returning 1 fails to check the rest of the devices in the
> > group.
> > 
> > msi_remap (aka secure MSI) requires that all the devices in the group
> > support it, not just any one. This is only a theoretical problem as no
> > current drivers will have different secure MSI properties within a group.
> 
> Which is exactly how Robin justified the behavior in the referenced
> commit:
> 
>   As with domains, any capability must in practice be consistent for
>   devices in a given group - and after all it's still the same
>   capability which was expected to be consistent across an entire bus!
>   - so there's no need for any complicated validation.
> 
> That suggests to me that it's intentional that we break if any device
> supports the capability and therefore this isn't so much a "Fixes:", as
> it is a refactoring expressly to support msi_device_has_secure_msi(),
> which cannot make these sort of assumptions as a non-group API.  Thanks,

Sure, lets drop the fixes and your analysis seems correct

Jason
Robin Murphy Dec. 9, 2022, 10:24 a.m. UTC | #3
On 2022-12-09 00:44, Jason Gunthorpe wrote:
> On Thu, Dec 08, 2022 at 02:48:25PM -0700, Alex Williamson wrote:
>> On Thu,  8 Dec 2022 16:26:29 -0400
>> Jason Gunthorpe <jgg@nvidia.com> wrote:
>>
>>> iommu_group_for_each_dev() exits the loop at the first callback that
>>> returns 1 - thus returning 1 fails to check the rest of the devices in the
>>> group.
>>>
>>> msi_remap (aka secure MSI) requires that all the devices in the group
>>> support it, not just any one. This is only a theoretical problem as no
>>> current drivers will have different secure MSI properties within a group.
>>
>> Which is exactly how Robin justified the behavior in the referenced
>> commit:
>>
>>    As with domains, any capability must in practice be consistent for
>>    devices in a given group - and after all it's still the same
>>    capability which was expected to be consistent across an entire bus!
>>    - so there's no need for any complicated validation.
>>
>> That suggests to me that it's intentional that we break if any device
>> supports the capability and therefore this isn't so much a "Fixes:", as
>> it is a refactoring expressly to support msi_device_has_secure_msi(),
>> which cannot make these sort of assumptions as a non-group API.  Thanks,
> 
> Sure, lets drop the fixes and your analysis seems correct

Yup, Alex is spot on - the fact is that all the IOMMU drivers supporting 
this cap have always returned global values, and continue to do so right 
up until we remove it later, so there's really no benefit in pretending 
otherwise. I'd say just fold this into patch #3 to keep it even simpler.

Thanks,
Robin.
diff mbox series

Patch

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 23c24fe98c00d4..3025b4e643c135 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2160,10 +2160,12 @@  static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu,
 	list_splice_tail(iova_copy, iova);
 }
 
-/* Redundantly walks non-present capabilities to simplify caller */
-static int vfio_iommu_device_capable(struct device *dev, void *data)
+static int vfio_iommu_device_secure_msi(struct device *dev, void *data)
 {
-	return device_iommu_capable(dev, (enum iommu_cap)data);
+	bool *secure_msi = data;
+
+	*secure_msi &= device_iommu_capable(dev, IOMMU_CAP_INTR_REMAP);
+	return 0;
 }
 
 static int vfio_iommu_domain_alloc(struct device *dev, void *data)
@@ -2278,9 +2280,12 @@  static int vfio_iommu_type1_attach_group(void *iommu_data,
 	INIT_LIST_HEAD(&domain->group_list);
 	list_add(&group->next, &domain->group_list);
 
-	msi_remap = irq_domain_check_msi_remap() ||
-		    iommu_group_for_each_dev(iommu_group, (void *)IOMMU_CAP_INTR_REMAP,
-					     vfio_iommu_device_capable);
+	msi_remap = irq_domain_check_msi_remap();
+	if (!msi_remap) {
+		msi_remap = true;
+		iommu_group_for_each_dev(iommu_group, &msi_remap,
+					 vfio_iommu_device_secure_msi);
+	}
 
 	if (!allow_unsafe_interrupts && !msi_remap) {
 		pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",