Skip to content

Commit 803f972

Browse files
yiliu1765jgunthorpe
authored andcommitted
iommufd: Extend IOMMU_GET_HW_INFO to report PASID capability
PASID usage requires PASID support in both device and IOMMU. Since the iommu drivers always enable the PASID capability for the device if it is supported, this extends the IOMMU_GET_HW_INFO to report the PASID capability to userspace. Also, enhances the selftest accordingly. Link: https://patch.msgid.link/r/[email protected] Cc: Bjorn Helgaas <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Tested-by: Zhangfei Gao <[email protected]> #aarch64 platform Tested-by: Nicolin Chen <[email protected]> Signed-off-by: Yi Liu <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent ad744ed commit 803f972

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

drivers/iommu/iommufd/device.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
#include <linux/iommu.h>
55
#include <linux/iommufd.h>
6+
#include <linux/pci-ats.h>
67
#include <linux/slab.h>
78
#include <uapi/linux/iommufd.h>
89

@@ -1455,7 +1456,8 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
14551456
void *data;
14561457
int rc;
14571458

1458-
if (cmd->flags || cmd->__reserved)
1459+
if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] ||
1460+
cmd->__reserved[2])
14591461
return -EOPNOTSUPP;
14601462

14611463
idev = iommufd_get_device(ucmd, cmd->dev_id);
@@ -1512,6 +1514,36 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
15121514
if (device_iommu_capable(idev->dev, IOMMU_CAP_DIRTY_TRACKING))
15131515
cmd->out_capabilities |= IOMMU_HW_CAP_DIRTY_TRACKING;
15141516

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+
15151547
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
15161548
out_free:
15171549
kfree(data);

drivers/pci/ats.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,4 +538,37 @@ int pci_max_pasids(struct pci_dev *pdev)
538538
return (1 << FIELD_GET(PCI_PASID_CAP_WIDTH, supported));
539539
}
540540
EXPORT_SYMBOL_GPL(pci_max_pasids);
541+
542+
/**
543+
* pci_pasid_status - Check the PASID status
544+
* @pdev: PCI device structure
545+
*
546+
* Returns a negative value when no PASID capability is present.
547+
* Otherwise the value of the control register is returned.
548+
* Status reported are:
549+
*
550+
* PCI_PASID_CTRL_ENABLE - PASID enabled
551+
* PCI_PASID_CTRL_EXEC - Execute permission enabled
552+
* PCI_PASID_CTRL_PRIV - Privileged mode enabled
553+
*/
554+
int pci_pasid_status(struct pci_dev *pdev)
555+
{
556+
int pasid;
557+
u16 ctrl;
558+
559+
if (pdev->is_virtfn)
560+
pdev = pci_physfn(pdev);
561+
562+
pasid = pdev->pasid_cap;
563+
if (!pasid)
564+
return -EINVAL;
565+
566+
pci_read_config_word(pdev, pasid + PCI_PASID_CTRL, &ctrl);
567+
568+
ctrl &= PCI_PASID_CTRL_ENABLE | PCI_PASID_CTRL_EXEC |
569+
PCI_PASID_CTRL_PRIV;
570+
571+
return ctrl;
572+
}
573+
EXPORT_SYMBOL_GPL(pci_pasid_status);
541574
#endif /* CONFIG_PCI_PASID */

include/linux/pci-ats.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int pci_enable_pasid(struct pci_dev *pdev, int features);
4242
void pci_disable_pasid(struct pci_dev *pdev);
4343
int pci_pasid_features(struct pci_dev *pdev);
4444
int pci_max_pasids(struct pci_dev *pdev);
45+
int pci_pasid_status(struct pci_dev *pdev);
4546
#else /* CONFIG_PCI_PASID */
4647
static inline int pci_enable_pasid(struct pci_dev *pdev, int features)
4748
{ return -EINVAL; }
@@ -50,6 +51,8 @@ static inline int pci_pasid_features(struct pci_dev *pdev)
5051
{ return -EINVAL; }
5152
static inline int pci_max_pasids(struct pci_dev *pdev)
5253
{ return -EINVAL; }
54+
static inline int pci_pasid_status(struct pci_dev *pdev)
55+
{ return -EINVAL; }
5356
#endif /* CONFIG_PCI_PASID */
5457

5558
#endif /* LINUX_PCI_ATS_H */

include/uapi/linux/iommufd.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,17 @@ enum iommu_hw_info_type {
612612
* IOMMU_HWPT_GET_DIRTY_BITMAP
613613
* IOMMU_HWPT_SET_DIRTY_TRACKING
614614
*
615+
* @IOMMU_HW_CAP_PCI_PASID_EXEC: Execute Permission Supported, user ignores it
616+
* when the struct
617+
* iommu_hw_info::out_max_pasid_log2 is zero.
618+
* @IOMMU_HW_CAP_PCI_PASID_PRIV: Privileged Mode Supported, user ignores it
619+
* when the struct
620+
* iommu_hw_info::out_max_pasid_log2 is zero.
615621
*/
616622
enum iommufd_hw_capabilities {
617623
IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
624+
IOMMU_HW_CAP_PCI_PASID_EXEC = 1 << 1,
625+
IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2,
618626
};
619627

620628
/**
@@ -630,6 +638,9 @@ enum iommufd_hw_capabilities {
630638
* iommu_hw_info_type.
631639
* @out_capabilities: Output the generic iommu capability info type as defined
632640
* in the enum iommu_hw_capabilities.
641+
* @out_max_pasid_log2: Output the width of PASIDs. 0 means no PASID support.
642+
* PCI devices turn to out_capabilities to check if the
643+
* specific capabilities is supported or not.
633644
* @__reserved: Must be 0
634645
*
635646
* Query an iommu type specific hardware information data from an iommu behind
@@ -653,7 +664,8 @@ struct iommu_hw_info {
653664
__u32 data_len;
654665
__aligned_u64 data_uptr;
655666
__u32 out_data_type;
656-
__u32 __reserved;
667+
__u8 out_max_pasid_log2;
668+
__u8 __reserved[3];
657669
__aligned_u64 out_capabilities;
658670
};
659671
#define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)

0 commit comments

Comments
 (0)