History

iommu/arm-smmu-v3: Report events that belong to devices attached to vIOMMU

Aside from the IOPF framework, iommufd provides an additional pathway to report hardware events, via the vEVENTQ of vIOMMU infrastructure. Define an iommu_vevent_arm_smmuv3 uAPI structure, and report stage-1 events in the threaded IRQ handler. Also, add another four event record types that can be forwarded to a VM.

Nicolin Chen committed 1 year ago

Commit e7d3fa31 parent f0ea2074 files · +80 −25Browse files

Unified · Split

4 files
  1. drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c +17 −0
  2. drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +33 −25
  3. drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +7 −0
  4. include/uapi/linux/iommufd.h +23 −0
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c+17−0
@@ -433,4 +433,21 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev, · 432 unmodified lines
433 return &vsmmu->core;433 return &vsmmu->core;
434}434}
435 435
436int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt)
437{
438 struct iommu_vevent_arm_smmuv3 vevt;
439 int i;
440
441 lockdep_assert_held(&vmaster->vsmmu->smmu->streams_mutex);
442
443 vevt.evt[0] = cpu_to_le64((evt[0] & ~EVTQ_0_SID) |
444 FIELD_PREP(EVTQ_0_SID, vmaster->vsid));
445 for (i = 1; i < EVTQ_ENT_DWORDS; i++)
446 vevt.evt[i] = cpu_to_le64(evt[i]);
447
448 return iommufd_viommu_report_event(&vmaster->vsmmu->core,
449 IOMMU_VEVENTQ_TYPE_ARM_SMMUV3, &vevt,
450 sizeof(vevt));
451}
452
436MODULE_IMPORT_NS("IOMMUFD");453MODULE_IMPORT_NS("IOMMUFD");
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c+33−25
@@ -1813,8 +1813,8 @@ static void arm_smmu_decode_event(struct arm_smmu_device *smmu, u64 *raw, · 1812 unmodified lines
1813 mutex_unlock(&smmu->streams_mutex);1813 mutex_unlock(&smmu->streams_mutex);
1814}1814}
1815 1815
1816static int arm_smmu_handle_event(struct arm_smmu_device *smmu,1816static int arm_smmu_handle_event(struct arm_smmu_device *smmu, u64 *evt,
1817 struct arm_smmu_event *event)1817 struct arm_smmu_event *event)
1818{1818{
1819 int ret = 0;1819 int ret = 0;
1820 u32 perm = 0;1820 u32 perm = 0;
@@ -1823,6 +1823,10 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu, · 2 unmodified lines
1823 struct iommu_fault *flt = &fault_evt.fault;1823 struct iommu_fault *flt = &fault_evt.fault;
1824 1824
1825 switch (event->id) {1825 switch (event->id) {
1826 case EVT_ID_BAD_STE_CONFIG:
1827 case EVT_ID_STREAM_DISABLED_FAULT:
1828 case EVT_ID_BAD_SUBSTREAMID_CONFIG:
1829 case EVT_ID_BAD_CD_CONFIG:
1826 case EVT_ID_TRANSLATION_FAULT:1830 case EVT_ID_TRANSLATION_FAULT:
1827 case EVT_ID_ADDR_SIZE_FAULT:1831 case EVT_ID_ADDR_SIZE_FAULT:
1828 case EVT_ID_ACCESS_FAULT:1832 case EVT_ID_ACCESS_FAULT:
@@ -1832,31 +1836,30 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu, · 3 unmodified lines
1832 return -EOPNOTSUPP;1836 return -EOPNOTSUPP;
1833 }1837 }
1834 1838
1835 if (!event->stall)1839 if (event->stall) {
1836 return -EOPNOTSUPP;1840 if (event->read)
1837 1841 perm |= IOMMU_FAULT_PERM_READ;
1838 if (event->read)1842 else
1839 perm |= IOMMU_FAULT_PERM_READ;1843 perm |= IOMMU_FAULT_PERM_WRITE;
1840 else
1841 perm |= IOMMU_FAULT_PERM_WRITE;
1842 1844
1843 if (event->instruction)1845 if (event->instruction)
1844 perm |= IOMMU_FAULT_PERM_EXEC;1846 perm |= IOMMU_FAULT_PERM_EXEC;
1845 1847
1846 if (event->privileged)1848 if (event->privileged)
1847 perm |= IOMMU_FAULT_PERM_PRIV;1849 perm |= IOMMU_FAULT_PERM_PRIV;
1848 1850
1849 flt->type = IOMMU_FAULT_PAGE_REQ;1851 flt->type = IOMMU_FAULT_PAGE_REQ;
1850 flt->prm = (struct iommu_fault_page_request) {1852 flt->prm = (struct iommu_fault_page_request){
1851 .flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE,1853 .flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE,
1852 .grpid = event->stag,1854 .grpid = event->stag,
1853 .perm = perm,1855 .perm = perm,
1854 .addr = event->iova,1856 .addr = event->iova,
1855 };1857 };
1856 1858
1857 if (event->ssv) {1859 if (event->ssv) {
1858 flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;1860 flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
1859 flt->prm.pasid = event->ssid;1861 flt->prm.pasid = event->ssid;
1862 }
1860 }1863 }
1861 1864
1862 mutex_lock(&smmu->streams_mutex);1865 mutex_lock(&smmu->streams_mutex);
@@ -1866,7 +1869,12 @@ static int arm_smmu_handle_event(struct arm_smmu_device *smmu, · 3 unmodified lines
1866 goto out_unlock;1869 goto out_unlock;
1867 }1870 }
1868 1871
1869 ret = iommu_report_device_fault(master->dev, &fault_evt);1872 if (event->stall)
1873 ret = iommu_report_device_fault(master->dev, &fault_evt);
1874 else if (master->vmaster && !event->s2)
1875 ret = arm_vmaster_report_event(master->vmaster, evt);
1876 else
1877 ret = -EOPNOTSUPP; /* Unhandled events should be pinned */
1870out_unlock:1878out_unlock:
1871 mutex_unlock(&smmu->streams_mutex);1879 mutex_unlock(&smmu->streams_mutex);
1872 return ret;1880 return ret;
@@ -1944,7 +1952,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) · 71 unmodified lines
1944 do {1952 do {
1945 while (!queue_remove_raw(q, evt)) {1953 while (!queue_remove_raw(q, evt)) {
1946 arm_smmu_decode_event(smmu, evt, &event);1954 arm_smmu_decode_event(smmu, evt, &event);
1947 if (arm_smmu_handle_event(smmu, &event))1955 if (arm_smmu_handle_event(smmu, evt, &event))
1948 arm_smmu_dump_event(smmu, evt, &event, &rs);1956 arm_smmu_dump_event(smmu, evt, &event, &rs);
1949 1957
1950 put_device(event.dev);1958 put_device(event.dev);
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h+7−0
@@ -1066,6 +1066,7 @@ int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state, · 1065 unmodified lines
1066 struct arm_smmu_nested_domain *nested_domain);1066 struct arm_smmu_nested_domain *nested_domain);
1067void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);1067void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
1068void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);1068void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
1069int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt);
1069#else1070#else
1070#define arm_smmu_hw_info NULL1071#define arm_smmu_hw_info NULL
1071#define arm_vsmmu_alloc NULL1072#define arm_vsmmu_alloc NULL
@@ -1086,6 +1087,12 @@ static inline void · 14 unmodified lines
1086arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)1087arm_smmu_master_clear_vmaster(struct arm_smmu_master *master)
1087{1088{
1088}1089}
1090
1091static inline int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster,
1092 u64 *evt)
1093{
1094 return -EOPNOTSUPP;
1095}
1089#endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */1096#endif /* CONFIG_ARM_SMMU_V3_IOMMUFD */
1090 1097
1091#endif /* _ARM_SMMU_V3_H */1098#endif /* _ARM_SMMU_V3_H */
include/uapi/linux/iommufd.h+23−0
@@ -1054,9 +1054,32 @@ struct iommufd_vevent_header { · 1053 unmodified lines
1054/**1054/**
1055 * enum iommu_veventq_type - Virtual Event Queue Type1055 * enum iommu_veventq_type - Virtual Event Queue Type
1056 * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use1056 * @IOMMU_VEVENTQ_TYPE_DEFAULT: Reserved for future use
1057 * @IOMMU_VEVENTQ_TYPE_ARM_SMMUV3: ARM SMMUv3 Virtual Event Queue
1057 */1058 */
1058enum iommu_veventq_type {1059enum iommu_veventq_type {
1059 IOMMU_VEVENTQ_TYPE_DEFAULT = 0,1060 IOMMU_VEVENTQ_TYPE_DEFAULT = 0,
1061 IOMMU_VEVENTQ_TYPE_ARM_SMMUV3 = 1,
1062};
1063
1064/**
1065 * struct iommu_vevent_arm_smmuv3 - ARM SMMUv3 Virtual Event
1066 * (IOMMU_VEVENTQ_TYPE_ARM_SMMUV3)
1067 * @evt: 256-bit ARM SMMUv3 Event record, little-endian.
1068 * Reported event records: (Refer to "7.3 Event records" in SMMUv3 HW Spec)
1069 * - 0x04 C_BAD_STE
1070 * - 0x06 F_STREAM_DISABLED
1071 * - 0x08 C_BAD_SUBSTREAMID
1072 * - 0x0a C_BAD_CD
1073 * - 0x10 F_TRANSLATION
1074 * - 0x11 F_ADDR_SIZE
1075 * - 0x12 F_ACCESS
1076 * - 0x13 F_PERMISSION
1077 *
1078 * StreamID field reports a virtual device ID. To receive a virtual event for a
1079 * device, a vDEVICE must be allocated via IOMMU_VDEVICE_ALLOC.
1080 */
1081struct iommu_vevent_arm_smmuv3 {
1082 __aligned_le64 evt[4];
1060};1083};
1061 1084
1062/**1085/**