diff options
author | Jason Gunthorpe <jgg@nvidia.com> | 2022-12-07 23:44:43 +0300 |
---|---|---|
committer | Jason Gunthorpe <jgg@nvidia.com> | 2022-12-09 22:24:30 +0300 |
commit | d6c55c0a20e5059abdde81713ddf6324a946eb3c (patch) | |
tree | 4776645a117fe8140102f412a04b20f451a40bd6 /drivers/iommu/iommufd/io_pagetable.c | |
parent | a26fa392068d1dcdf781397b7a7dd908dd68f030 (diff) | |
download | linux-d6c55c0a20e5059abdde81713ddf6324a946eb3c.tar.xz |
iommufd: Change the order of MSI setup
Eric points out this is wrong for the rare case of someone using
allow_unsafe_interrupts on ARM. We always have to setup the MSI window in
the domain if the iommu driver asks for it.
Move the iommu_get_msi_cookie() setup to the top of the function and
always do it, regardless of the security mode. Add checks to
iommufd_device_setup_msi() to ensure the driver is not doing something
incomprehensible. No current driver will set both a HW and SW MSI window,
or have more than one SW MSI window.
Fixes: e8d57210035b ("iommufd: Add kAPI toward external drivers for physical devices")
Link: https://lore.kernel.org/r/3-v1-0362a1a1c034+98-iommufd_fixes1_jgg@nvidia.com
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reported-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers/iommu/iommufd/io_pagetable.c')
-rw-r--r-- | drivers/iommu/iommufd/io_pagetable.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c index 3467cea79568..e0ae72b9e67f 100644 --- a/drivers/iommu/iommufd/io_pagetable.c +++ b/drivers/iommu/iommufd/io_pagetable.c @@ -1170,6 +1170,8 @@ int iopt_table_enforce_group_resv_regions(struct io_pagetable *iopt, struct iommu_resv_region *resv; struct iommu_resv_region *tmp; LIST_HEAD(group_resv_regions); + unsigned int num_hw_msi = 0; + unsigned int num_sw_msi = 0; int rc; down_write(&iopt->iova_rwsem); @@ -1181,23 +1183,25 @@ int iopt_table_enforce_group_resv_regions(struct io_pagetable *iopt, if (resv->type == IOMMU_RESV_DIRECT_RELAXABLE) continue; - /* - * The presence of any 'real' MSI regions should take precedence - * over the software-managed one if the IOMMU driver happens to - * advertise both types. - */ - if (sw_msi_start && resv->type == IOMMU_RESV_MSI) { - *sw_msi_start = 0; - sw_msi_start = NULL; - } - if (sw_msi_start && resv->type == IOMMU_RESV_SW_MSI) + if (sw_msi_start && resv->type == IOMMU_RESV_MSI) + num_hw_msi++; + if (sw_msi_start && resv->type == IOMMU_RESV_SW_MSI) { *sw_msi_start = resv->start; + num_sw_msi++; + } rc = iopt_reserve_iova(iopt, resv->start, resv->length - 1 + resv->start, device); if (rc) goto out_reserved; } + + /* Drivers must offer sane combinations of regions */ + if (WARN_ON(num_sw_msi && num_hw_msi) || WARN_ON(num_sw_msi > 1)) { + rc = -EINVAL; + goto out_reserved; + } + rc = 0; goto out_free_resv; |