提交 9d3a4de4 编写于 作者: R Robin Murphy 提交者: Joerg Roedel

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: d30ddcaa ("iommu: Add a new type field in iommu_resv_region")
Reviewed-by: NEric 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: NRobin Murphy <robin.murphy@arm.com>
Signed-off-by: NJoerg Roedel <jroedel@suse.de>
上级 cd37a296
...@@ -3202,7 +3202,7 @@ static void amd_iommu_get_resv_regions(struct device *dev, ...@@ -3202,7 +3202,7 @@ static void amd_iommu_get_resv_regions(struct device *dev,
region = iommu_alloc_resv_region(MSI_RANGE_START, region = iommu_alloc_resv_region(MSI_RANGE_START,
MSI_RANGE_END - MSI_RANGE_START + 1, MSI_RANGE_END - MSI_RANGE_START + 1,
0, IOMMU_RESV_RESERVED); 0, IOMMU_RESV_MSI);
if (!region) if (!region)
return; return;
list_add_tail(&region->list, head); list_add_tail(&region->list, head);
......
...@@ -1888,7 +1888,7 @@ static void arm_smmu_get_resv_regions(struct device *dev, ...@@ -1888,7 +1888,7 @@ static void arm_smmu_get_resv_regions(struct device *dev,
int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH, region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
prot, IOMMU_RESV_MSI); prot, IOMMU_RESV_SW_MSI);
if (!region) if (!region)
return; return;
......
...@@ -1608,7 +1608,7 @@ static void arm_smmu_get_resv_regions(struct device *dev, ...@@ -1608,7 +1608,7 @@ static void arm_smmu_get_resv_regions(struct device *dev,
int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH, region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
prot, IOMMU_RESV_MSI); prot, IOMMU_RESV_SW_MSI);
if (!region) if (!region)
return; return;
......
...@@ -5249,7 +5249,7 @@ static void intel_iommu_get_resv_regions(struct device *device, ...@@ -5249,7 +5249,7 @@ static void intel_iommu_get_resv_regions(struct device *device,
reg = iommu_alloc_resv_region(IOAPIC_RANGE_START, reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1, IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
0, IOMMU_RESV_RESERVED); 0, IOMMU_RESV_MSI);
if (!reg) if (!reg)
return; return;
list_add_tail(&reg->list, head); list_add_tail(&reg->list, head);
......
...@@ -72,6 +72,7 @@ static const char * const iommu_group_resv_type_string[] = { ...@@ -72,6 +72,7 @@ static const char * const iommu_group_resv_type_string[] = {
[IOMMU_RESV_DIRECT] = "direct", [IOMMU_RESV_DIRECT] = "direct",
[IOMMU_RESV_RESERVED] = "reserved", [IOMMU_RESV_RESERVED] = "reserved",
[IOMMU_RESV_MSI] = "msi", [IOMMU_RESV_MSI] = "msi",
[IOMMU_RESV_SW_MSI] = "msi",
}; };
#define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \
...@@ -1743,8 +1744,8 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list) ...@@ -1743,8 +1744,8 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
} }
struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start, struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start,
size_t length, size_t length, int prot,
int prot, int type) enum iommu_resv_type type)
{ {
struct iommu_resv_region *region; struct iommu_resv_region *region;
......
...@@ -1182,8 +1182,7 @@ static struct vfio_group *find_iommu_group(struct vfio_domain *domain, ...@@ -1182,8 +1182,7 @@ static struct vfio_group *find_iommu_group(struct vfio_domain *domain,
return NULL; return NULL;
} }
static bool vfio_iommu_has_resv_msi(struct iommu_group *group, static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base)
phys_addr_t *base)
{ {
struct list_head group_resv_regions; struct list_head group_resv_regions;
struct iommu_resv_region *region, *next; struct iommu_resv_region *region, *next;
...@@ -1192,7 +1191,7 @@ static bool vfio_iommu_has_resv_msi(struct iommu_group *group, ...@@ -1192,7 +1191,7 @@ static bool vfio_iommu_has_resv_msi(struct iommu_group *group,
INIT_LIST_HEAD(&group_resv_regions); INIT_LIST_HEAD(&group_resv_regions);
iommu_get_group_resv_regions(group, &group_resv_regions); iommu_get_group_resv_regions(group, &group_resv_regions);
list_for_each_entry(region, &group_resv_regions, list) { list_for_each_entry(region, &group_resv_regions, list) {
if (region->type & IOMMU_RESV_MSI) { if (region->type == IOMMU_RESV_SW_MSI) {
*base = region->start; *base = region->start;
ret = true; ret = true;
goto out; goto out;
...@@ -1283,7 +1282,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, ...@@ -1283,7 +1282,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
if (ret) if (ret)
goto out_domain; goto out_domain;
resv_msi = vfio_iommu_has_resv_msi(iommu_group, &resv_msi_base); resv_msi = vfio_iommu_has_sw_msi(iommu_group, &resv_msi_base);
INIT_LIST_HEAD(&domain->group_list); INIT_LIST_HEAD(&domain->group_list);
list_add(&group->next, &domain->group_list); list_add(&group->next, &domain->group_list);
......
...@@ -125,9 +125,16 @@ enum iommu_attr { ...@@ -125,9 +125,16 @@ enum iommu_attr {
}; };
/* These are the possible reserved region types */ /* These are the possible reserved region types */
#define IOMMU_RESV_DIRECT (1 << 0) enum iommu_resv_type {
#define IOMMU_RESV_RESERVED (1 << 1) /* Memory regions which must be mapped 1:1 at all times */
#define IOMMU_RESV_MSI (1 << 2) IOMMU_RESV_DIRECT,
/* Arbitrary "never map this or give it to a device" address ranges */
IOMMU_RESV_RESERVED,
/* Hardware MSI region (untranslated) */
IOMMU_RESV_MSI,
/* Software-managed MSI translation window */
IOMMU_RESV_SW_MSI,
};
/** /**
* struct iommu_resv_region - descriptor for a reserved memory region * struct iommu_resv_region - descriptor for a reserved memory region
...@@ -142,7 +149,7 @@ struct iommu_resv_region { ...@@ -142,7 +149,7 @@ struct iommu_resv_region {
phys_addr_t start; phys_addr_t start;
size_t length; size_t length;
int prot; int prot;
int type; enum iommu_resv_type type;
}; };
#ifdef CONFIG_IOMMU_API #ifdef CONFIG_IOMMU_API
...@@ -288,7 +295,8 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); ...@@ -288,7 +295,8 @@ extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev); extern int iommu_request_dm_for_dev(struct device *dev);
extern struct iommu_resv_region * extern struct iommu_resv_region *
iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot,
enum iommu_resv_type type);
extern int iommu_get_group_resv_regions(struct iommu_group *group, extern int iommu_get_group_resv_regions(struct iommu_group *group,
struct list_head *head); struct list_head *head);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册