@@ -1569,6 +1569,76 @@ static int smmuv3_get_attr(IOMMUMemoryRegion *iommu,
return -EINVAL;
}
+struct iommu_fault;
+
+static inline int
+smmuv3_inject_faults(IOMMUMemoryRegion *iommu_mr, int count,
+ struct iommu_fault *buf)
+{
+#ifdef __linux__
+ SMMUDevice *sdev = container_of(iommu_mr, SMMUDevice, iommu);
+ SMMUv3State *s3 = sdev->smmu;
+ uint32_t sid = smmu_get_sid(sdev);
+ int i;
+
+ for (i = 0; i < count; i++) {
+ SMMUEventInfo info = {};
+ struct iommu_fault_unrecoverable *record;
+
+ if (buf[i].type != IOMMU_FAULT_DMA_UNRECOV) {
+ continue;
+ }
+
+ info.sid = sid;
+ record = &buf[i].event;
+
+ switch (record->reason) {
+ case IOMMU_FAULT_REASON_PASID_INVALID:
+ info.type = SMMU_EVT_C_BAD_SUBSTREAMID;
+ /* TODO further fill info.u.c_bad_substream */
+ break;
+ case IOMMU_FAULT_REASON_PASID_FETCH:
+ info.type = SMMU_EVT_F_CD_FETCH;
+ break;
+ case IOMMU_FAULT_REASON_BAD_PASID_ENTRY:
+ info.type = SMMU_EVT_C_BAD_CD;
+ /* TODO further fill info.u.c_bad_cd */
+ break;
+ case IOMMU_FAULT_REASON_WALK_EABT:
+ info.type = SMMU_EVT_F_WALK_EABT;
+ info.u.f_walk_eabt.addr = record->addr;
+ info.u.f_walk_eabt.addr2 = record->fetch_addr;
+ break;
+ case IOMMU_FAULT_REASON_PTE_FETCH:
+ info.type = SMMU_EVT_F_TRANSLATION;
+ info.u.f_translation.addr = record->addr;
+ break;
+ case IOMMU_FAULT_REASON_OOR_ADDRESS:
+ info.type = SMMU_EVT_F_ADDR_SIZE;
+ info.u.f_addr_size.addr = record->addr;
+ break;
+ case IOMMU_FAULT_REASON_ACCESS:
+ info.type = SMMU_EVT_F_ACCESS;
+ info.u.f_access.addr = record->addr;
+ break;
+ case IOMMU_FAULT_REASON_PERMISSION:
+ info.type = SMMU_EVT_F_PERMISSION;
+ info.u.f_permission.addr = record->addr;
+ break;
+ default:
+ warn_report("%s Unexpected fault reason received from host: %d",
+ __func__, record->reason);
+ continue;
+ }
+
+ smmuv3_record_event(s3, &info);
+ }
+ return 0;
+#else
+ return -1;
+#endif
+}
+
static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
void *data)
{
@@ -1577,6 +1647,7 @@ static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass,
imrc->translate = smmuv3_translate;
imrc->notify_flag_changed = smmuv3_notify_flag_changed;
imrc->get_attr = smmuv3_get_attr;
+ imrc->inject_faults = smmuv3_inject_faults;
}
static const TypeInfo smmuv3_type_info = {
We convert iommu_fault structs received from the kernel into the data struct used by the emulation code and record the evnts into the virtual event queue. Signed-off-by: Eric Auger <eric.auger@redhat.com> --- v3 -> v4: - fix compil issue on mingw Exhaustive mapping remains to be done --- hw/arm/smmuv3.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+)