Pull iommufd updates from Jason Gunthorpe: "Two significant new items: - Allow reporting IOMMU HW events to userspace when the events are clearly linked to a device. This is linked to the VIOMMU object and is intended to be used by a VMM to forward HW events to the virtual machine as part of emulating a vIOMMU. ARM SMMUv3 is the first driver to use this mechanism. Like the existing fault events the data is delivered through a simple FD returning event records on read(). - PASID support in VFIO. The "Process Address Space ID" is a PCI feature that allows the device to tag all PCI DMA operations with an ID. The IOMMU will then use the ID to select a unique translation for those DMAs. This is part of Intel's vIOMMU support as VT-D HW requires the hypervisor to manage each PASID entry. The support is generic so any VFIO user could attach any translation to a PASID, and the support should work on ARM SMMUv3 as well. AMD requires additional driver work. Some minor updates, along with fixes: - Prevent using nested parents with fault's, no driver support today - Put a single "cookie_type" value in the iommu_domain to indicate what owns the various opaque owner fields" * tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd: (49 commits) iommufd: Test attach before detaching pasid iommufd: Fix iommu_vevent_header tables markup iommu: Convert unreachable() to BUG() iommufd: Balance veventq->num_events inc/dec iommufd: Initialize the flags of vevent in iommufd_viommu_report_event() iommufd/selftest: Add coverage for reporting max_pasid_log2 via IOMMU_HW_INFO iommufd: Extend IOMMU_GET_HW_INFO to report PASID capability vfio: VFIO_DEVICE_[AT|DE]TACH_IOMMUFD_PT support pasid vfio-iommufd: Support pasid [at|de]tach for physical VFIO devices ida: Add ida_find_first_range() iommufd/selftest: Add coverage for iommufd pasid attach/detach iommufd/selftest: Add test ops to test pasid attach/detach iommufd/selftest: Add a helper to get test device iommufd/selftest: Add set_dev_pasid in mock iommu iommufd: Allow allocating PASID-compatible domain iommu/vt-d: Add IOMMU_HWPT_ALLOC_PASID support iommufd: Enforce PASID-compatible domain for RID iommufd: Support pasid attach/replace iommufd: Enforce PASID-compatible domain in PASID path iommufd/device: Add pasid_attach array to track per-PASID attach ...
Showing the changes to include/uapi/linux (2 of 39 files). Show all
Unified · Split
| @@ -55,6 +55,7 @@ enum { · 54 unmodified lines | ||
| 55 | 55 | IOMMUFD_CMD_VIOMMU_ALLOC = 0x90, |
| 56 | 56 | IOMMUFD_CMD_VDEVICE_ALLOC = 0x91, |
| 57 | 57 | IOMMUFD_CMD_IOAS_CHANGE_PROCESS = 0x92, |
| 58 | + IOMMUFD_CMD_VEVENTQ_ALLOC = 0x93, | |
| 58 | 59 | }; |
| 59 | 60 | |
| 60 | 61 | /** |
| @@ -392,6 +393,9 @@ struct iommu_vfio_ioas { · 331 unmodified lines | ||
| 392 | 393 | * Any domain attached to the non-PASID part of the |
| 393 | 394 | * device must also be flagged, otherwise attaching a |
| 394 | 395 | * PASID will blocked. |
| 396 | + * For the user that wants to attach PASID, ioas is | |
| 397 | + * not recommended for both the non-PASID part | |
| 398 | + * and PASID part of the device. | |
| 395 | 399 | * If IOMMU does not support PASID it will return |
| 396 | 400 | * error (-EOPNOTSUPP). |
| 397 | 401 | */ |
| @@ -608,9 +612,17 @@ enum iommu_hw_info_type { · 210 unmodified lines | ||
| 608 | 612 | * IOMMU_HWPT_GET_DIRTY_BITMAP |
| 609 | 613 | * IOMMU_HWPT_SET_DIRTY_TRACKING |
| 610 | 614 | * |
| 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. | |
| 611 | 621 | */ |
| 612 | 622 | enum iommufd_hw_capabilities { |
| 613 | 623 | 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, | |
| 614 | 626 | }; |
| 615 | 627 | |
| 616 | 628 | /** |
| @@ -626,6 +638,9 @@ enum iommufd_hw_capabilities { · 9 unmodified lines | ||
| 626 | 638 | * iommu_hw_info_type. |
| 627 | 639 | * @out_capabilities: Output the generic iommu capability info type as defined |
| 628 | 640 | * 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. | |
| 629 | 644 | * @__reserved: Must be 0 |
| 630 | 645 | * |
| 631 | 646 | * Query an iommu type specific hardware information data from an iommu behind |
| @@ -649,7 +664,8 @@ struct iommu_hw_info { · 17 unmodified lines | ||
| 649 | 664 | __u32 data_len; |
| 650 | 665 | __aligned_u64 data_uptr; |
| 651 | 666 | __u32 out_data_type; |
| 652 | − __u32 __reserved; | |
| 667 | + __u8 out_max_pasid_log2; | |
| 668 | + __u8 __reserved[3]; | |
| 653 | 669 | __aligned_u64 out_capabilities; |
| 654 | 670 | }; |
| 655 | 671 | #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO) |
| @@ -1014,4 +1030,115 @@ struct iommu_ioas_change_process { · 358 unmodified lines | ||
| 1014 | 1030 | #define IOMMU_IOAS_CHANGE_PROCESS \ |
| 1015 | 1031 | _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_CHANGE_PROCESS) |
| 1016 | 1032 | |
| 1033 | +/** | |
| 1034 | + * enum iommu_veventq_flag - flag for struct iommufd_vevent_header | |
| 1035 | + * @IOMMU_VEVENTQ_FLAG_LOST_EVENTS: vEVENTQ has lost vEVENTs | |
| 1036 | + */ | |
| 1037 | +enum iommu_veventq_flag { | |
| 1038 | + IOMMU_VEVENTQ_FLAG_LOST_EVENTS = (1U << 0), | |
| 1039 | +}; | |
| 1040 | + | |
| 1041 | +/** | |
| 1042 | + * struct iommufd_vevent_header - Virtual Event Header for a vEVENTQ Status | |
| 1043 | + * @flags: Combination of enum iommu_veventq_flag | |
| 1044 | + * @sequence: The sequence index of a vEVENT in the vEVENTQ, with a range of | |
| 1045 | + * [0, INT_MAX] where the following index of INT_MAX is 0 | |
| 1046 | + * | |
| 1047 | + * Each iommufd_vevent_header reports a sequence index of the following vEVENT: | |
| 1048 | + * | |
| 1049 | + * +----------------------+-------+----------------------+-------+---+-------+ | |
| 1050 | + * | header0 {sequence=0} | data0 | header1 {sequence=1} | data1 |...| dataN | | |
| 1051 | + * +----------------------+-------+----------------------+-------+---+-------+ | |
| 1052 | + * | |
| 1053 | + * And this sequence index is expected to be monotonic to the sequence index of | |
| 1054 | + * the previous vEVENT. If two adjacent sequence indexes has a delta larger than | |
| 1055 | + * 1, it means that delta - 1 number of vEVENTs has lost, e.g. two lost vEVENTs: | |
| 1056 | + * | |
| 1057 | + * +-----+----------------------+-------+----------------------+-------+-----+ | |
| 1058 | + * | ... | header3 {sequence=3} | data3 | header6 {sequence=6} | data6 | ... | | |
| 1059 | + * +-----+----------------------+-------+----------------------+-------+-----+ | |
| 1060 | + * | |
| 1061 | + * If a vEVENT lost at the tail of the vEVENTQ and there is no following vEVENT | |
| 1062 | + * providing the next sequence index, an IOMMU_VEVENTQ_FLAG_LOST_EVENTS header | |
| 1063 | + * would be added to the tail, and no data would follow this header: | |
| 1064 | + * | |
| 1065 | + * +--+----------------------+-------+-----------------------------------------+ | |
| 1066 | + * |..| header3 {sequence=3} | data3 | header4 {flags=LOST_EVENTS, sequence=4} | | |
| 1067 | + * +--+----------------------+-------+-----------------------------------------+ | |
| 1068 | + */ | |
| 1069 | +struct iommufd_vevent_header { | |
| 1070 | + __u32 flags; | |
| 1071 | + __u32 sequence; | |
| 1072 | +}; | |
| 1073 | + | |
| 1074 | +/** | |
| 1075 | + * enum iommu_veventq_type - Virtual Event Queue Type | |
| 1076 | + * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use | |
| 1077 | + * @IOMMU_VEVENTQ_TYPE_ARM_SMMUV3: ARM SMMUv3 Virtual Event Queue | |
| 1078 | + */ | |
| 1079 | +enum iommu_veventq_type { | |
| 1080 | + IOMMU_VEVENTQ_TYPE_DEFAULT = 0, | |
| 1081 | + IOMMU_VEVENTQ_TYPE_ARM_SMMUV3 = 1, | |
| 1082 | +}; | |
| 1083 | + | |
| 1084 | +/** | |
| 1085 | + * struct iommu_vevent_arm_smmuv3 - ARM SMMUv3 Virtual Event | |
| 1086 | + * (IOMMU_VEVENTQ_TYPE_ARM_SMMUV3) | |
| 1087 | + * @evt: 256-bit ARM SMMUv3 Event record, little-endian. | |
| 1088 | + * Reported event records: (Refer to "7.3 Event records" in SMMUv3 HW Spec) | |
| 1089 | + * - 0x04 C_BAD_STE | |
| 1090 | + * - 0x06 F_STREAM_DISABLED | |
| 1091 | + * - 0x08 C_BAD_SUBSTREAMID | |
| 1092 | + * - 0x0a C_BAD_CD | |
| 1093 | + * - 0x10 F_TRANSLATION | |
| 1094 | + * - 0x11 F_ADDR_SIZE | |
| 1095 | + * - 0x12 F_ACCESS | |
| 1096 | + * - 0x13 F_PERMISSION | |
| 1097 | + * | |
| 1098 | + * StreamID field reports a virtual device ID. To receive a virtual event for a | |
| 1099 | + * device, a vDEVICE must be allocated via IOMMU_VDEVICE_ALLOC. | |
| 1100 | + */ | |
| 1101 | +struct iommu_vevent_arm_smmuv3 { | |
| 1102 | + __aligned_le64 evt[4]; | |
| 1103 | +}; | |
| 1104 | + | |
| 1105 | +/** | |
| 1106 | + * struct iommu_veventq_alloc - ioctl(IOMMU_VEVENTQ_ALLOC) | |
| 1107 | + * @size: sizeof(struct iommu_veventq_alloc) | |
| 1108 | + * @flags: Must be 0 | |
| 1109 | + * @viommu_id: virtual IOMMU ID to associate the vEVENTQ with | |
| 1110 | + * @type: Type of the vEVENTQ. Must be defined in enum iommu_veventq_type | |
| 1111 | + * @veventq_depth: Maximum number of events in the vEVENTQ | |
| 1112 | + * @out_veventq_id: The ID of the new vEVENTQ | |
| 1113 | + * @out_veventq_fd: The fd of the new vEVENTQ. User space must close the | |
| 1114 | + * successfully returned fd after using it | |
| 1115 | + * @__reserved: Must be 0 | |
| 1116 | + * | |
| 1117 | + * Explicitly allocate a virtual event queue interface for a vIOMMU. A vIOMMU | |
| 1118 | + * can have multiple FDs for different types, but is confined to one per @type. | |
| 1119 | + * User space should open the @out_veventq_fd to read vEVENTs out of a vEVENTQ, | |
| 1120 | + * if there are vEVENTs available. A vEVENTQ will lose events due to overflow, | |
| 1121 | + * if the number of the vEVENTs hits @veventq_depth. | |
| 1122 | + * | |
| 1123 | + * Each vEVENT in a vEVENTQ encloses a struct iommufd_vevent_header followed by | |
| 1124 | + * a type-specific data structure, in a normal case: | |
| 1125 | + * | |
| 1126 | + * +-+---------+-------+---------+-------+-----+---------+-------+-+ | |
| 1127 | + * | | header0 | data0 | header1 | data1 | ... | headerN | dataN | | | |
| 1128 | + * +-+---------+-------+---------+-------+-----+---------+-------+-+ | |
| 1129 | + * | |
| 1130 | + * unless a tailing IOMMU_VEVENTQ_FLAG_LOST_EVENTS header is logged (refer to | |
| 1131 | + * struct iommufd_vevent_header). | |
| 1132 | + */ | |
| 1133 | +struct iommu_veventq_alloc { | |
| 1134 | + __u32 size; | |
| 1135 | + __u32 flags; | |
| 1136 | + __u32 viommu_id; | |
| 1137 | + __u32 type; | |
| 1138 | + __u32 veventq_depth; | |
| 1139 | + __u32 out_veventq_id; | |
| 1140 | + __u32 out_veventq_fd; | |
| 1141 | + __u32 __reserved; | |
| 1142 | +}; | |
| 1143 | +#define IOMMU_VEVENTQ_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VEVENTQ_ALLOC) | |
| 1017 | 1144 | #endif |
| @@ -932,29 +932,34 @@ struct vfio_device_bind_iommufd { · 931 unmodified lines | ||
| 932 | 932 | * VFIO_DEVICE_ATTACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 19, |
| 933 | 933 | * struct vfio_device_attach_iommufd_pt) |
| 934 | 934 | * @argsz: User filled size of this data. |
| 935 | − * @flags: Must be 0. | |
| 935 | + * @flags: Flags for attach. | |
| 936 | 936 | * @pt_id: Input the target id which can represent an ioas or a hwpt |
| 937 | 937 | * allocated via iommufd subsystem. |
| 938 | 938 | * Output the input ioas id or the attached hwpt id which could |
| 939 | 939 | * be the specified hwpt itself or a hwpt automatically created |
| 940 | 940 | * for the specified ioas by kernel during the attachment. |
| 941 | + * @pasid: The pasid to be attached, only meaningful when | |
| 942 | + * VFIO_DEVICE_ATTACH_PASID is set in @flags | |
| 941 | 943 | * |
| 942 | 944 | * Associate the device with an address space within the bound iommufd. |
| 943 | 945 | * Undo by VFIO_DEVICE_DETACH_IOMMUFD_PT or device fd close. This is only |
| 944 | 946 | * allowed on cdev fds. |
| 945 | 947 | * |
| 946 | − * If a vfio device is currently attached to a valid hw_pagetable, without doing | |
| 947 | − * a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl | |
| 948 | − * passing in another hw_pagetable (hwpt) id is allowed. This action, also known | |
| 949 | − * as a hw_pagetable replacement, will replace the device's currently attached | |
| 950 | − * hw_pagetable with a new hw_pagetable corresponding to the given pt_id. | |
| 948 | + * If a vfio device or a pasid of this device is currently attached to a valid | |
| 949 | + * hw_pagetable (hwpt), without doing a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second | |
| 950 | + * VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl passing in another hwpt id is allowed. | |
| 951 | + * This action, also known as a hw_pagetable replacement, will replace the | |
| 952 | + * currently attached hwpt of the device or the pasid of this device with a new | |
| 953 | + * hwpt corresponding to the given pt_id. | |
| 951 | 954 | * |
| 952 | 955 | * Return: 0 on success, -errno on failure. |
| 953 | 956 | */ |
| 954 | 957 | struct vfio_device_attach_iommufd_pt { |
| 955 | 958 | __u32 argsz; |
| 956 | 959 | __u32 flags; |
| 960 | +#define VFIO_DEVICE_ATTACH_PASID (1 << 0) | |
| 957 | 961 | __u32 pt_id; |
| 962 | + __u32 pasid; | |
| 958 | 963 | }; |
| 959 | 964 | |
| 960 | 965 | #define VFIO_DEVICE_ATTACH_IOMMUFD_PT _IO(VFIO_TYPE, VFIO_BASE + 19) |
| @@ -963,17 +968,21 @@ struct vfio_device_attach_iommufd_pt { · 2 unmodified lines | ||
| 963 | 968 | * VFIO_DEVICE_DETACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 20, |
| 964 | 969 | * struct vfio_device_detach_iommufd_pt) |
| 965 | 970 | * @argsz: User filled size of this data. |
| 966 | − * @flags: Must be 0. | |
| 971 | + * @flags: Flags for detach. | |
| 972 | + * @pasid: The pasid to be detached, only meaningful when | |
| 973 | + * VFIO_DEVICE_DETACH_PASID is set in @flags | |
| 967 | 974 | * |
| 968 | − * Remove the association of the device and its current associated address | |
| 969 | − * space. After it, the device should be in a blocking DMA state. This is only | |
| 970 | − * allowed on cdev fds. | |
| 975 | + * Remove the association of the device or a pasid of the device and its current | |
| 976 | + * associated address space. After it, the device or the pasid should be in a | |
| 977 | + * blocking DMA state. This is only allowed on cdev fds. | |
| 971 | 978 | * |
| 972 | 979 | * Return: 0 on success, -errno on failure. |
| 973 | 980 | */ |
| 974 | 981 | struct vfio_device_detach_iommufd_pt { |
| 975 | 982 | __u32 argsz; |
| 976 | 983 | __u32 flags; |
| 984 | +#define VFIO_DEVICE_DETACH_PASID (1 << 0) | |
| 985 | + __u32 pasid; | |
| 977 | 986 | }; |
| 978 | 987 | |
| 979 | 988 | #define VFIO_DEVICE_DETACH_IOMMUFD_PT _IO(VFIO_TYPE, VFIO_BASE + 20) |