Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu: Disambiguate MSI region types

The introduction of reserved regions has left a couple of rough edges
which we could do with sorting out sooner rather than later. Since we
are not yet addressing the potential dynamic aspect of software-managed
reservations and presenting them at arbitrary fixed addresses, it is
incongruous that we end up displaying hardware vs. software-managed MSI
regions to userspace differently, especially since ARM-based systems may
actually require one or the other, or even potentially both at once,
(which iommu-dma currently has no hope of dealing with at all). Let's
resolve the former user-visible inconsistency ASAP before the ABI has
been baked into a kernel release, in a way that also lays the groundwork
for the latter shortcoming to be addressed by follow-up patches.

For clarity, rename the software-managed type to IOMMU_RESV_SW_MSI, use
IOMMU_RESV_MSI to describe the hardware type, and document everything a
little bit. Since the x86 MSI remapping hardware falls squarely under
this meaning of IOMMU_RESV_MSI, apply that type to their regions as well,
so that we tell the same story to userspace across all platforms.

Secondly, as the various region types require quite different handling,
and it really makes little sense to ever try combining them, convert the
bitfield-esque #defines to a plain enum in the process before anyone
gets the wrong impression.

Fixes: d30ddcaa7b02 ("iommu: Add a new type field in iommu_resv_region")
Reviewed-by: Eric Auger <eric.auger@redhat.com>
CC: Alex Williamson <alex.williamson@redhat.com>
CC: David Woodhouse <dwmw2@infradead.org>
CC: kvm@vger.kernel.org
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>

authored by

Robin Murphy and committed by
Joerg Roedel
9d3a4de4 cd37a296

+23 -15
+1 -1
drivers/iommu/amd_iommu.c
··· 3202 3202 3203 3203 region = iommu_alloc_resv_region(MSI_RANGE_START, 3204 3204 MSI_RANGE_END - MSI_RANGE_START + 1, 3205 - 0, IOMMU_RESV_RESERVED); 3205 + 0, IOMMU_RESV_MSI); 3206 3206 if (!region) 3207 3207 return; 3208 3208 list_add_tail(&region->list, head);
+1 -1
drivers/iommu/arm-smmu-v3.c
··· 1888 1888 int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; 1889 1889 1890 1890 region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH, 1891 - prot, IOMMU_RESV_MSI); 1891 + prot, IOMMU_RESV_SW_MSI); 1892 1892 if (!region) 1893 1893 return; 1894 1894
+1 -1
drivers/iommu/arm-smmu.c
··· 1608 1608 int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; 1609 1609 1610 1610 region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH, 1611 - prot, IOMMU_RESV_MSI); 1611 + prot, IOMMU_RESV_SW_MSI); 1612 1612 if (!region) 1613 1613 return; 1614 1614
+1 -1
drivers/iommu/intel-iommu.c
··· 5249 5249 5250 5250 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START, 5251 5251 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1, 5252 - 0, IOMMU_RESV_RESERVED); 5252 + 0, IOMMU_RESV_MSI); 5253 5253 if (!reg) 5254 5254 return; 5255 5255 list_add_tail(&reg->list, head);
+3 -2
drivers/iommu/iommu.c
··· 72 72 [IOMMU_RESV_DIRECT] = "direct", 73 73 [IOMMU_RESV_RESERVED] = "reserved", 74 74 [IOMMU_RESV_MSI] = "msi", 75 + [IOMMU_RESV_SW_MSI] = "msi", 75 76 }; 76 77 77 78 #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ ··· 1744 1743 } 1745 1744 1746 1745 struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start, 1747 - size_t length, 1748 - int prot, int type) 1746 + size_t length, int prot, 1747 + enum iommu_resv_type type) 1749 1748 { 1750 1749 struct iommu_resv_region *region; 1751 1750
+3 -4
drivers/vfio/vfio_iommu_type1.c
··· 1182 1182 return NULL; 1183 1183 } 1184 1184 1185 - static bool vfio_iommu_has_resv_msi(struct iommu_group *group, 1186 - phys_addr_t *base) 1185 + static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base) 1187 1186 { 1188 1187 struct list_head group_resv_regions; 1189 1188 struct iommu_resv_region *region, *next; ··· 1191 1192 INIT_LIST_HEAD(&group_resv_regions); 1192 1193 iommu_get_group_resv_regions(group, &group_resv_regions); 1193 1194 list_for_each_entry(region, &group_resv_regions, list) { 1194 - if (region->type & IOMMU_RESV_MSI) { 1195 + if (region->type == IOMMU_RESV_SW_MSI) { 1195 1196 *base = region->start; 1196 1197 ret = true; 1197 1198 goto out; ··· 1282 1283 if (ret) 1283 1284 goto out_domain; 1284 1285 1285 - resv_msi = vfio_iommu_has_resv_msi(iommu_group, &resv_msi_base); 1286 + resv_msi = vfio_iommu_has_sw_msi(iommu_group, &resv_msi_base); 1286 1287 1287 1288 INIT_LIST_HEAD(&domain->group_list); 1288 1289 list_add(&group->next, &domain->group_list);
+13 -5
include/linux/iommu.h
··· 125 125 }; 126 126 127 127 /* These are the possible reserved region types */ 128 - #define IOMMU_RESV_DIRECT (1 << 0) 129 - #define IOMMU_RESV_RESERVED (1 << 1) 130 - #define IOMMU_RESV_MSI (1 << 2) 128 + enum iommu_resv_type { 129 + /* Memory regions which must be mapped 1:1 at all times */ 130 + IOMMU_RESV_DIRECT, 131 + /* Arbitrary "never map this or give it to a device" address ranges */ 132 + IOMMU_RESV_RESERVED, 133 + /* Hardware MSI region (untranslated) */ 134 + IOMMU_RESV_MSI, 135 + /* Software-managed MSI translation window */ 136 + IOMMU_RESV_SW_MSI, 137 + }; 131 138 132 139 /** 133 140 * struct iommu_resv_region - descriptor for a reserved memory region ··· 149 142 phys_addr_t start; 150 143 size_t length; 151 144 int prot; 152 - int type; 145 + enum iommu_resv_type type; 153 146 }; 154 147 155 148 #ifdef CONFIG_IOMMU_API ··· 295 288 extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); 296 289 extern int iommu_request_dm_for_dev(struct device *dev); 297 290 extern struct iommu_resv_region * 298 - iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); 291 + iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, 292 + enum iommu_resv_type type); 299 293 extern int iommu_get_group_resv_regions(struct iommu_group *group, 300 294 struct list_head *head); 301 295