summaryrefslogtreecommitdiffstats
path: root/drivers/vfio
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2015-06-05 02:35:20 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-06-11 01:16:52 -0400
commit4793d65d1ac056d92b594d05c6aab3c040d913dd (patch)
tree634824f7b5a7b65480bcf56b46506587801c1d06 /drivers/vfio
parentbbb845c4bac88d8feffa8945dd28b50849984e30 (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.c19
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))