powerpc/pseries/iommu: Fix the VFIO_IOMMU_SPAPR_TCE_GET_INFO ioctl output

The ioctl VFIO_IOMMU_SPAPR_TCE_GET_INFO is not reporting the
actuals on the platform as not all the details are correctly
collected during the platform probe/scan into the iommu_table_group.

Collect the information during the device setup time as the DMA
window property is already looked up on parent nodes anyway.

Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/171923271138.1397.7908302630061814623.stgit@linux.ibm.com
This commit is contained in:
Shivaprasad G Bhat 2024-06-24 12:38:34 +00:00 committed by Michael Ellerman
parent b09c031d94
commit 6af67f2ddf

View File

@ -865,13 +865,6 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
be32_to_cpu(prop.tce_shift), NULL,
&iommu_table_lpar_multi_ops);
/* Only for normal boot with default window. Doesn't matter even
* if we set these with DDW which is 64bit during kdump, since
* these will not be used during kdump.
*/
ppci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
ppci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
if (!iommu_init_table(tbl, ppci->phb->node, 0, 0))
panic("Failed to initialize iommu table");
@ -1658,6 +1651,71 @@ out_unlock:
return direct_mapping;
}
static __u64 query_page_size_to_mask(u32 query_page_size)
{
const long shift[] = {
(SZ_4K), (SZ_64K), (SZ_16M),
(SZ_32M), (SZ_64M), (SZ_128M),
(SZ_256M), (SZ_16G), (SZ_2M)
};
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(shift); i++) {
if (query_page_size & (1 << i))
ret |= shift[i];
}
return ret;
}
static void spapr_tce_init_table_group(struct pci_dev *pdev,
struct device_node *pdn,
struct dynamic_dma_window_prop prop)
{
struct iommu_table_group *table_group = PCI_DN(pdn)->table_group;
u32 ddw_avail[DDW_APPLICABLE_SIZE];
struct ddw_query_response query;
int ret;
/* Only for normal boot with default window. Doesn't matter during
* kdump, since these will not be used during kdump.
*/
if (is_kdump_kernel())
return;
if (table_group->max_dynamic_windows_supported != 0)
return; /* already initialized */
table_group->tce32_start = be64_to_cpu(prop.dma_base);
table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
if (!of_find_property(pdn, "ibm,dma-window", NULL))
dev_err(&pdev->dev, "default dma window missing!\n");
ret = of_property_read_u32_array(pdn, "ibm,ddw-applicable",
&ddw_avail[0], DDW_APPLICABLE_SIZE);
if (ret) {
table_group->max_dynamic_windows_supported = -1;
return;
}
ret = query_ddw(pdev, ddw_avail, &query, pdn);
if (ret) {
dev_err(&pdev->dev, "%s: query_ddw failed\n", __func__);
table_group->max_dynamic_windows_supported = -1;
return;
}
if (query.windows_available == 0)
table_group->max_dynamic_windows_supported = 1;
else
table_group->max_dynamic_windows_supported = IOMMU_TABLE_GROUP_MAX_TABLES;
table_group->max_levels = 1;
table_group->pgsizes |= query_page_size_to_mask(query.page_size);
}
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
{
struct device_node *pdn, *dn;
@ -1697,13 +1755,6 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
be32_to_cpu(prop.tce_shift), NULL,
&iommu_table_lpar_multi_ops);
/* Only for normal boot with default window. Doesn't matter even
* if we set these with DDW which is 64bit during kdump, since
* these will not be used during kdump.
*/
pci->table_group->tce32_start = be64_to_cpu(prop.dma_base);
pci->table_group->tce32_size = 1 << be32_to_cpu(prop.window_shift);
iommu_init_table(tbl, pci->phb->node, 0, 0);
iommu_register_group(pci->table_group,
pci_domain_nr(pci->phb->bus), 0);
@ -1712,6 +1763,8 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
pr_debug(" found DMA window, table: %p\n", pci->table_group);
}
spapr_tce_init_table_group(dev, pdn, prop);
set_iommu_table_base(&dev->dev, pci->table_group->tables[0]);
iommu_add_device(pci->table_group, &dev->dev);
}