|
3 | 3 | */ |
4 | 4 | #include <linux/iommu.h> |
5 | 5 | #include <linux/iommufd.h> |
| 6 | +#include <linux/pci-ats.h> |
6 | 7 | #include <linux/slab.h> |
7 | 8 | #include <uapi/linux/iommufd.h> |
8 | 9 |
|
@@ -1455,7 +1456,8 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) |
1455 | 1456 | void *data; |
1456 | 1457 | int rc; |
1457 | 1458 |
|
1458 | | - if (cmd->flags || cmd->__reserved) |
| 1459 | + if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] || |
| 1460 | + cmd->__reserved[2]) |
1459 | 1461 | return -EOPNOTSUPP; |
1460 | 1462 |
|
1461 | 1463 | idev = iommufd_get_device(ucmd, cmd->dev_id); |
@@ -1512,6 +1514,36 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd) |
1512 | 1514 | if (device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING)) |
1513 | 1515 | cmd->out_capabilities |= IOMMU_HW_CAP_DIRTY_TRACKING; |
1514 | 1516 |
|
| 1517 | + cmd->out_max_pasid_log2 = 0; |
| 1518 | + /* |
| 1519 | + * Currently, all iommu drivers enable PASID in the probe_device() |
| 1520 | + * op if iommu and device supports it. So the max_pasids stored in |
| 1521 | + * dev->iommu indicates both PASID support and enable status. A |
| 1522 | + * non-zero dev->iommu->max_pasids means PASID is supported and |
| 1523 | + * enabled. The iommufd only reports PASID capability to userspace |
| 1524 | + * if it's enabled. |
| 1525 | + */ |
| 1526 | + if (idev->dev->iommu->max_pasids) { |
| 1527 | + cmd->out_max_pasid_log2 = ilog2(idev->dev->iommu->max_pasids); |
| 1528 | + |
| 1529 | + if (dev_is_pci(idev->dev)) { |
| 1530 | + struct pci_dev *pdev = to_pci_dev(idev->dev); |
| 1531 | + int ctrl; |
| 1532 | + |
| 1533 | + ctrl = pci_pasid_status(pdev); |
| 1534 | + |
| 1535 | + WARN_ON_ONCE(ctrl < 0 || |
| 1536 | + !(ctrl & PCI_PASID_CTRL_ENABLE)); |
| 1537 | + |
| 1538 | + if (ctrl & PCI_PASID_CTRL_EXEC) |
| 1539 | + cmd->out_capabilities |= |
| 1540 | + IOMMU_HW_CAP_PCI_PASID_EXEC; |
| 1541 | + if (ctrl & PCI_PASID_CTRL_PRIV) |
| 1542 | + cmd->out_capabilities |= |
| 1543 | + IOMMU_HW_CAP_PCI_PASID_PRIV; |
| 1544 | + } |
| 1545 | + } |
| 1546 | + |
1515 | 1547 | rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); |
1516 | 1548 | out_free: |
1517 | 1549 | kfree(data); |
|
0 commit comments