diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2015-06-05 02:35:20 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-06-11 01:16:52 -0400 |
commit | 4793d65d1ac056d92b594d05c6aab3c040d913dd (patch) | |
tree | 634824f7b5a7b65480bcf56b46506587801c1d06 /drivers/vfio | |
parent | bbb845c4bac88d8feffa8945dd28b50849984e30 (diff) |
vfio: powerpc/spapr: powerpc/powernv/ioda: Define and implement DMA windows API
This extends iommu_table_group_ops by a set of callbacks to support
dynamic DMA windows management.
create_table() creates a TCE table with specific parameters.
it receives iommu_table_group to know nodeid in order to allocate
TCE table memory closer to the PHB. The exact format of allocated
multi-level table might be also specific to the PHB model (not
the case now though).
This callback calculated the DMA window offset on a PCI bus from @num
and stores it in a just created table.
set_window() sets the window at specified TVT index + @num on PHB.
unset_window() unsets the window from specified TVT.
This adds a free() callback to iommu_table_ops to free the memory
(potentially a tree of tables) allocated for the TCE table.
create_table() and free() are supposed to be called once per
VFIO container and set_window()/unset_window() are supposed to be
called for every group in a container.
This adds IOMMU capabilities to iommu_table_group such as default
32bit window parameters and others. This makes use of new values in
vfio_iommu_spapr_tce. IODA1/P5IOC2 do not support DDW so they do not
advertise pagemasks to the userspace.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Acked-by: Alex Williamson <alex.williamson@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/vfio_iommu_spapr_tce.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index a9e2d13c03c0..6d919eb4251f 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c | |||
@@ -135,7 +135,6 @@ static int tce_iommu_enable(struct tce_container *container) | |||
135 | { | 135 | { |
136 | int ret = 0; | 136 | int ret = 0; |
137 | unsigned long locked; | 137 | unsigned long locked; |
138 | struct iommu_table *tbl; | ||
139 | struct iommu_table_group *table_group; | 138 | struct iommu_table_group *table_group; |
140 | 139 | ||
141 | if (!container->grp) | 140 | if (!container->grp) |
@@ -171,13 +170,19 @@ static int tce_iommu_enable(struct tce_container *container) | |||
171 | * this is that we cannot tell here the amount of RAM used by the guest | 170 | * this is that we cannot tell here the amount of RAM used by the guest |
172 | * as this information is only available from KVM and VFIO is | 171 | * as this information is only available from KVM and VFIO is |
173 | * KVM agnostic. | 172 | * KVM agnostic. |
173 | * | ||
174 | * So we do not allow enabling a container without a group attached | ||
175 | * as there is no way to know how much we should increment | ||
176 | * the locked_vm counter. | ||
174 | */ | 177 | */ |
175 | table_group = iommu_group_get_iommudata(container->grp); | 178 | table_group = iommu_group_get_iommudata(container->grp); |
176 | if (!table_group) | 179 | if (!table_group) |
177 | return -ENODEV; | 180 | return -ENODEV; |
178 | 181 | ||
179 | tbl = table_group->tables[0]; | 182 | if (!table_group->tce32_size) |
180 | locked = (tbl->it_size << tbl->it_page_shift) >> PAGE_SHIFT; | 183 | return -EPERM; |
184 | |||
185 | locked = table_group->tce32_size >> PAGE_SHIFT; | ||
181 | ret = try_increment_locked_vm(locked); | 186 | ret = try_increment_locked_vm(locked); |
182 | if (ret) | 187 | if (ret) |
183 | return ret; | 188 | return ret; |
@@ -350,7 +355,6 @@ static long tce_iommu_ioctl(void *iommu_data, | |||
350 | 355 | ||
351 | case VFIO_IOMMU_SPAPR_TCE_GET_INFO: { | 356 | case VFIO_IOMMU_SPAPR_TCE_GET_INFO: { |
352 | struct vfio_iommu_spapr_tce_info info; | 357 | struct vfio_iommu_spapr_tce_info info; |
353 | struct iommu_table *tbl; | ||
354 | struct iommu_table_group *table_group; | 358 | struct iommu_table_group *table_group; |
355 | 359 | ||
356 | if (WARN_ON(!container->grp)) | 360 | if (WARN_ON(!container->grp)) |
@@ -358,8 +362,7 @@ static long tce_iommu_ioctl(void *iommu_data, | |||
358 | 362 | ||
359 | table_group = iommu_group_get_iommudata(container->grp); | 363 | table_group = iommu_group_get_iommudata(container->grp); |
360 | 364 | ||
361 | tbl = table_group->tables[0]; | 365 | if (!table_group) |
362 | if (WARN_ON_ONCE(!tbl)) | ||
363 | return -ENXIO; | 366 | return -ENXIO; |
364 | 367 | ||
365 | minsz = offsetofend(struct vfio_iommu_spapr_tce_info, | 368 | minsz = offsetofend(struct vfio_iommu_spapr_tce_info, |
@@ -371,8 +374,8 @@ static long tce_iommu_ioctl(void *iommu_data, | |||
371 | if (info.argsz < minsz) | 374 | if (info.argsz < minsz) |
372 | return -EINVAL; | 375 | return -EINVAL; |
373 | 376 | ||
374 | info.dma32_window_start = tbl->it_offset << tbl->it_page_shift; | 377 | info.dma32_window_start = table_group->tce32_start; |
375 | info.dma32_window_size = tbl->it_size << tbl->it_page_shift; | 378 | info.dma32_window_size = table_group->tce32_size; |
376 | info.flags = 0; | 379 | info.flags = 0; |
377 | 380 | ||
378 | if (copy_to_user((void __user *)arg, &info, minsz)) | 381 | if (copy_to_user((void __user *)arg, &info, minsz)) |