diff --git a/hw-arm-smmuv3-Implement-fault-injection.patch b/hw-arm-smmuv3-Implement-fault-injection.patch new file mode 100644 index 0000000..0260e28 --- /dev/null +++ b/hw-arm-smmuv3-Implement-fault-injection.patch @@ -0,0 +1,107 @@ +From 55bfd18b7671c82705d83d543281add0afcda31f Mon Sep 17 00:00:00 2001 +From: Eric Auger +Date: Thu, 13 Sep 2018 14:24:45 +0200 +Subject: [PATCH] hw/arm/smmuv3: Implement fault injection + +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 +Signed-off-by: Kunkun Jiang +--- + hw/arm/smmuv3.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c +index 3d2151857d..931d6eae57 100644 +--- a/hw/arm/smmuv3.c ++++ b/hw/arm/smmuv3.c +@@ -1594,6 +1594,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) + { +@@ -1602,6 +1672,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 = { +-- +2.27.0 +