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 (2 of 39 files). Show all
Unified · Split
| @@ -55,6 +55,7 @@ enum { · 54 unmodified lines | |||
| 55 | IOMMUFD_CMD_VIOMMU_ALLOC = 0x90, | 55 | IOMMUFD_CMD_VIOMMU_ALLOC = 0x90, |
| 56 | IOMMUFD_CMD_VDEVICE_ALLOC = 0x91, | 56 | IOMMUFD_CMD_VDEVICE_ALLOC = 0x91, |
| 57 | IOMMUFD_CMD_IOAS_CHANGE_PROCESS = 0x92, | 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 | * Any domain attached to the non-PASID part of the | 393 | * Any domain attached to the non-PASID part of the |
| 393 | * device must also be flagged, otherwise attaching a | 394 | * device must also be flagged, otherwise attaching a |
| 394 | * PASID will blocked. | 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 | * If IOMMU does not support PASID it will return | 399 | * If IOMMU does not support PASID it will return |
| 396 | * error (-EOPNOTSUPP). | 400 | * error (-EOPNOTSUPP). |
| 397 | */ | 401 | */ |
| @@ -608,9 +612,17 @@ enum iommu_hw_info_type { · 210 unmodified lines | |||
| 608 | * IOMMU_HWPT_GET_DIRTY_BITMAP | 612 | * IOMMU_HWPT_GET_DIRTY_BITMAP |
| 609 | * IOMMU_HWPT_SET_DIRTY_TRACKING | 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 | enum iommufd_hw_capabilities { | 622 | enum iommufd_hw_capabilities { |
| 613 | IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0, | 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 | * iommu_hw_info_type. | 638 | * iommu_hw_info_type. |
| 627 | * @out_capabilities: Output the generic iommu capability info type as defined | 639 | * @out_capabilities: Output the generic iommu capability info type as defined |
| 628 | * in the enum iommu_hw_capabilities. | 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 | * @__reserved: Must be 0 | 644 | * @__reserved: Must be 0 |
| 630 | * | 645 | * |
| 631 | * Query an iommu type specific hardware information data from an iommu behind | 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 | __u32 data_len; | 664 | __u32 data_len; |
| 650 | __aligned_u64 data_uptr; | 665 | __aligned_u64 data_uptr; |
| 651 | __u32 out_data_type; | 666 | __u32 out_data_type; |
| 652 | __u32 __reserved; | 667 | __u8 out_max_pasid_log2; |
| 668 | __u8 __reserved[3]; | ||
| 653 | __aligned_u64 out_capabilities; | 669 | __aligned_u64 out_capabilities; |
| 654 | }; | 670 | }; |
| 655 | #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO) | 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 | #define IOMMU_IOAS_CHANGE_PROCESS \ | 1030 | #define IOMMU_IOAS_CHANGE_PROCESS \ |
| 1015 | _IO(IOMMUFD_TYPE, IOMMUFD_CMD_IOAS_CHANGE_PROCESS) | 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 | #endif | 1144 | #endif |
| @@ -932,29 +932,34 @@ struct vfio_device_bind_iommufd { · 931 unmodified lines | |||
| 932 | * VFIO_DEVICE_ATTACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 19, | 932 | * VFIO_DEVICE_ATTACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 19, |
| 933 | * struct vfio_device_attach_iommufd_pt) | 933 | * struct vfio_device_attach_iommufd_pt) |
| 934 | * @argsz: User filled size of this data. | 934 | * @argsz: User filled size of this data. |
| 935 | * @flags: Must be 0. | 935 | * @flags: Flags for attach. |
| 936 | * @pt_id: Input the target id which can represent an ioas or a hwpt | 936 | * @pt_id: Input the target id which can represent an ioas or a hwpt |
| 937 | * allocated via iommufd subsystem. | 937 | * allocated via iommufd subsystem. |
| 938 | * Output the input ioas id or the attached hwpt id which could | 938 | * Output the input ioas id or the attached hwpt id which could |
| 939 | * be the specified hwpt itself or a hwpt automatically created | 939 | * be the specified hwpt itself or a hwpt automatically created |
| 940 | * for the specified ioas by kernel during the attachment. | 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 | * Associate the device with an address space within the bound iommufd. | 944 | * Associate the device with an address space within the bound iommufd. |
| 943 | * Undo by VFIO_DEVICE_DETACH_IOMMUFD_PT or device fd close. This is only | 945 | * Undo by VFIO_DEVICE_DETACH_IOMMUFD_PT or device fd close. This is only |
| 944 | * allowed on cdev fds. | 946 | * allowed on cdev fds. |
| 945 | * | 947 | * |
| 946 | * If a vfio device is currently attached to a valid hw_pagetable, without doing | 948 | * If a vfio device or a pasid of this device is currently attached to a valid |
| 947 | * a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl | 949 | * hw_pagetable (hwpt), without doing a VFIO_DEVICE_DETACH_IOMMUFD_PT, a second |
| 948 | * passing in another hw_pagetable (hwpt) id is allowed. This action, also known | 950 | * VFIO_DEVICE_ATTACH_IOMMUFD_PT ioctl passing in another hwpt id is allowed. |
| 949 | * as a hw_pagetable replacement, will replace the device's currently attached | 951 | * This action, also known as a hw_pagetable replacement, will replace the |
| 950 | * hw_pagetable with a new hw_pagetable corresponding to the given pt_id. | 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 | * Return: 0 on success, -errno on failure. | 955 | * Return: 0 on success, -errno on failure. |
| 953 | */ | 956 | */ |
| 954 | struct vfio_device_attach_iommufd_pt { | 957 | struct vfio_device_attach_iommufd_pt { |
| 955 | __u32 argsz; | 958 | __u32 argsz; |
| 956 | __u32 flags; | 959 | __u32 flags; |
| 960 | #define VFIO_DEVICE_ATTACH_PASID (1 << 0) | ||
| 957 | __u32 pt_id; | 961 | __u32 pt_id; |
| 962 | __u32 pasid; | ||
| 958 | }; | 963 | }; |
| 959 | 964 | ||
| 960 | #define VFIO_DEVICE_ATTACH_IOMMUFD_PT _IO(VFIO_TYPE, VFIO_BASE + 19) | 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 | * VFIO_DEVICE_DETACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 20, | 968 | * VFIO_DEVICE_DETACH_IOMMUFD_PT - _IOW(VFIO_TYPE, VFIO_BASE + 20, |
| 964 | * struct vfio_device_detach_iommufd_pt) | 969 | * struct vfio_device_detach_iommufd_pt) |
| 965 | * @argsz: User filled size of this data. | 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 | 975 | * Remove the association of the device or a pasid of the device and its current |
| 969 | * space. After it, the device should be in a blocking DMA state. This is only | 976 | * associated address space. After it, the device or the pasid should be in a |
| 970 | * allowed on cdev fds. | 977 | * blocking DMA state. This is only allowed on cdev fds. |
| 971 | * | 978 | * |
| 972 | * Return: 0 on success, -errno on failure. | 979 | * Return: 0 on success, -errno on failure. |
| 973 | */ | 980 | */ |
| 974 | struct vfio_device_detach_iommufd_pt { | 981 | struct vfio_device_detach_iommufd_pt { |
| 975 | __u32 argsz; | 982 | __u32 argsz; |
| 976 | __u32 flags; | 983 | __u32 flags; |
| 984 | #define VFIO_DEVICE_DETACH_PASID (1 << 0) | ||
| 985 | __u32 pasid; | ||
| 977 | }; | 986 | }; |
| 978 | 987 | ||
| 979 | #define VFIO_DEVICE_DETACH_IOMMUFD_PT _IO(VFIO_TYPE, VFIO_BASE + 20) | 988 | #define VFIO_DEVICE_DETACH_IOMMUFD_PT _IO(VFIO_TYPE, VFIO_BASE + 20) |