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>
This commit is contained in:

committed by
Michael Ellerman

parent
bbb845c4ba
commit
4793d65d1a
@@ -135,7 +135,6 @@ static int tce_iommu_enable(struct tce_container *container)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long locked;
|
||||
struct iommu_table *tbl;
|
||||
struct iommu_table_group *table_group;
|
||||
|
||||
if (!container->grp)
|
||||
@@ -171,13 +170,19 @@ static int tce_iommu_enable(struct tce_container *container)
|
||||
* this is that we cannot tell here the amount of RAM used by the guest
|
||||
* as this information is only available from KVM and VFIO is
|
||||
* KVM agnostic.
|
||||
*
|
||||
* So we do not allow enabling a container without a group attached
|
||||
* as there is no way to know how much we should increment
|
||||
* the locked_vm counter.
|
||||
*/
|
||||
table_group = iommu_group_get_iommudata(container->grp);
|
||||
if (!table_group)
|
||||
return -ENODEV;
|
||||
|
||||
tbl = table_group->tables[0];
|
||||
locked = (tbl->it_size << tbl->it_page_shift) >> PAGE_SHIFT;
|
||||
if (!table_group->tce32_size)
|
||||
return -EPERM;
|
||||
|
||||
locked = table_group->tce32_size >> PAGE_SHIFT;
|
||||
ret = try_increment_locked_vm(locked);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -350,7 +355,6 @@ static long tce_iommu_ioctl(void *iommu_data,
|
||||
|
||||
case VFIO_IOMMU_SPAPR_TCE_GET_INFO: {
|
||||
struct vfio_iommu_spapr_tce_info info;
|
||||
struct iommu_table *tbl;
|
||||
struct iommu_table_group *table_group;
|
||||
|
||||
if (WARN_ON(!container->grp))
|
||||
@@ -358,8 +362,7 @@ static long tce_iommu_ioctl(void *iommu_data,
|
||||
|
||||
table_group = iommu_group_get_iommudata(container->grp);
|
||||
|
||||
tbl = table_group->tables[0];
|
||||
if (WARN_ON_ONCE(!tbl))
|
||||
if (!table_group)
|
||||
return -ENXIO;
|
||||
|
||||
minsz = offsetofend(struct vfio_iommu_spapr_tce_info,
|
||||
@@ -371,8 +374,8 @@ static long tce_iommu_ioctl(void *iommu_data,
|
||||
if (info.argsz < minsz)
|
||||
return -EINVAL;
|
||||
|
||||
info.dma32_window_start = tbl->it_offset << tbl->it_page_shift;
|
||||
info.dma32_window_size = tbl->it_size << tbl->it_page_shift;
|
||||
info.dma32_window_start = table_group->tce32_start;
|
||||
info.dma32_window_size = table_group->tce32_size;
|
||||
info.flags = 0;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &info, minsz))
|
||||
|
Reference in New Issue
Block a user