Provide a helper and use that to issue the invalidation cmd to host SMMUv3. We only issue one cmd at a time for now.
Support for batching of commands will be added later after analysing the impact. Signed-off-by: Shameer Kolothum <[email protected]> --- hw/arm/smmuv3-accel.c | 38 ++++++++++++++++++++++++++++++++++++++ hw/arm/smmuv3-accel.h | 8 ++++++++ hw/arm/smmuv3.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/hw/arm/smmuv3-accel.c b/hw/arm/smmuv3-accel.c index f4e01fba6d..9ad8595ce2 100644 --- a/hw/arm/smmuv3-accel.c +++ b/hw/arm/smmuv3-accel.c @@ -218,6 +218,44 @@ bool smmuv3_accel_install_nested_ste_range(SMMUv3State *s, SMMUSIDRange *range, return true; } +/* + * This issues the invalidation cmd to the host SMMUv3. + * Note: sdev can be NULL for certain invalidation commands + * e.g., SMMU_CMD_TLBI_NH_ASID, SMMU_CMD_TLBI_NH_VA etc. + */ +bool smmuv3_accel_issue_inv_cmd(SMMUv3State *bs, void *cmd, SMMUDevice *sdev, + Error **errp) +{ + SMMUv3State *s = ARM_SMMUV3(bs); + SMMUv3AccelState *s_accel = s->s_accel; + IOMMUFDViommu *viommu_core; + uint32_t entry_num = 1; + + if (!s->accel || !s_accel->viommu) { + return true; + } + + /* + * We may end up here for any emulated PCI bridge or root port type devices. + * However, passing invalidation commands with sid (eg: CFGI_CD) to host + * SMMUv3 only matters for vfio-pci endpoint devices. Hence check that if + * sdev is valid. + */ + if (sdev) { + SMMUv3AccelDevice *accel_dev = container_of(sdev, SMMUv3AccelDevice, + sdev); + if (!accel_dev->vdev) { + return true; + } + } + + viommu_core = &s_accel->viommu->core; + return iommufd_backend_invalidate_cache( + viommu_core->iommufd, viommu_core->viommu_id, + IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3, + sizeof(Cmd), &entry_num, cmd, errp); +} + static SMMUv3AccelDevice *smmuv3_accel_get_dev(SMMUState *bs, SMMUPciBus *sbus, PCIBus *bus, int devfn) { diff --git a/hw/arm/smmuv3-accel.h b/hw/arm/smmuv3-accel.h index 6242614c00..3bdba47616 100644 --- a/hw/arm/smmuv3-accel.h +++ b/hw/arm/smmuv3-accel.h @@ -46,6 +46,8 @@ bool smmuv3_accel_install_nested_ste(SMMUv3State *s, SMMUDevice *sdev, int sid, Error **errp); bool smmuv3_accel_install_nested_ste_range(SMMUv3State *s, SMMUSIDRange *range, Error **errp); +bool smmuv3_accel_issue_inv_cmd(SMMUv3State *s, void *cmd, SMMUDevice *sdev, + Error **errp); #else static inline void smmuv3_accel_init(SMMUv3State *s) { @@ -62,6 +64,12 @@ smmuv3_accel_install_nested_ste_range(SMMUv3State *s, SMMUSIDRange *range, { return true; } +static inline bool +smmuv3_accel_issue_inv_cmd(SMMUv3State *s, void *cmd, SMMUDevice *sdev, + Error **errp) +{ + return true; +} #endif #endif /* HW_ARM_SMMUV3_ACCEL_H */ diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 1fd8aaa0c7..3963bdc87f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1381,6 +1381,7 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) { uint32_t sid = CMD_SID(&cmd); SMMUDevice *sdev = smmu_find_sdev(bs, sid); + Error *local_err = NULL; if (CMD_SSEC(&cmd)) { cmd_error = SMMU_CERROR_ILL; @@ -1393,11 +1394,17 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) trace_smmuv3_cmdq_cfgi_cd(sid); smmuv3_flush_config(sdev); + if (!smmuv3_accel_issue_inv_cmd(s, &cmd, sdev, &local_err)) { + error_report_err(local_err); + cmd_error = SMMU_CERROR_ILL; + break; + } break; } case SMMU_CMD_TLBI_NH_ASID: { int asid = CMD_ASID(&cmd); + Error *local_err = NULL; int vmid = -1; if (!STAGE1_SUPPORTED(s)) { @@ -1416,6 +1423,11 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) trace_smmuv3_cmdq_tlbi_nh_asid(asid); smmu_inv_notifiers_all(&s->smmu_state); smmu_iotlb_inv_asid_vmid(bs, asid, vmid); + if (!smmuv3_accel_issue_inv_cmd(s, &cmd, NULL, &local_err)) { + error_report_err(local_err); + cmd_error = SMMU_CERROR_ILL; + break; + } break; } case SMMU_CMD_TLBI_NH_ALL: @@ -1440,18 +1452,36 @@ static int smmuv3_cmdq_consume(SMMUv3State *s) QEMU_FALLTHROUGH; } case SMMU_CMD_TLBI_NSNH_ALL: + { + Error *local_err = NULL; + trace_smmuv3_cmdq_tlbi_nsnh(); smmu_inv_notifiers_all(&s->smmu_state); smmu_iotlb_inv_all(bs); + if (!smmuv3_accel_issue_inv_cmd(s, &cmd, NULL, &local_err)) { + error_report_err(local_err); + cmd_error = SMMU_CERROR_ILL; + break; + } break; + } case SMMU_CMD_TLBI_NH_VAA: case SMMU_CMD_TLBI_NH_VA: + { + Error *local_err = NULL; + if (!STAGE1_SUPPORTED(s)) { cmd_error = SMMU_CERROR_ILL; break; } smmuv3_range_inval(bs, &cmd, SMMU_STAGE_1); + if (!smmuv3_accel_issue_inv_cmd(s, &cmd, NULL, &local_err)) { + error_report_err(local_err); + cmd_error = SMMU_CERROR_ILL; + break; + } break; + } case SMMU_CMD_TLBI_S12_VMALL: { int vmid = CMD_VMID(&cmd); -- 2.43.0
