diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c index 0a06631f80b4..f6c28d714f3e 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c @@ -446,6 +446,40 @@ static int smmu_init_strtab(struct hyp_arm_smmu_v3_device *smmu) return 0; } +static int smmu_reset_device(struct hyp_arm_smmu_v3_device *smmu) +{ + int ret; + struct arm_smmu_cmdq_ent cfgi_cmd = { + .opcode = CMDQ_OP_CFGI_ALL, + }; + struct arm_smmu_cmdq_ent tlbi_cmd = { + .opcode = CMDQ_OP_TLBI_NSNH_ALL, + }; + + /* Invalidate all cached configs and TLBs */ + ret = smmu_write_cr0(smmu, CR0_CMDQEN); + if (ret) + return ret; + + ret = smmu_add_cmd(smmu, &cfgi_cmd); + if (ret) + goto err_disable_cmdq; + + ret = smmu_add_cmd(smmu, &tlbi_cmd); + if (ret) + goto err_disable_cmdq; + + ret = smmu_sync_cmd(smmu); + if (ret) + goto err_disable_cmdq; + + /* Enable translation */ + return smmu_write_cr0(smmu, CR0_SMMUEN | CR0_CMDQEN | CR0_ATSCHK); + +err_disable_cmdq: + return smmu_write_cr0(smmu, 0); +} + static int smmu_init_device(struct hyp_arm_smmu_v3_device *smmu) { int ret; @@ -477,6 +511,10 @@ static int smmu_init_device(struct hyp_arm_smmu_v3_device *smmu) if (ret) return ret; + ret = smmu_reset_device(smmu); + if (ret) + return ret; + return kvm_iommu_init_device(&smmu->iommu); }