ANDROID: iommu/arm-smmu-v3-kvm: Support block_dma for guests

Unlike the host, where block_dma would be called after VFIO has blocked
the device, the guest can die at any moment and the hypervisor have
to clean after it, so in case of block_dma the hypervisor would need
to handle live devices and free their resources.

Bug: 357781595
Bug: 348382247
Bug: 236685427
Change-Id: I8be4ade52d0055e5fc490c28813f54b8d03998c9
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2025-02-24 17:05:42 +00:00
committed by Carlos Llamas
parent 7a4cc58922
commit 3ab3693c96
@@ -1564,8 +1564,28 @@ static int smmu_dev_block_dma(struct kvm_hyp_iommu *iommu, u32 sid, bool is_host
* and the device might be translating, so we have to actually block
* the device and clean the STE/CD.
*/
if (dst->data[0])
ret = -EINVAL;
if (dst->data[0]) {
if (is_host2guest) {
ret = -EINVAL;
} else {
int i = 0;
u32 cfg = FIELD_GET(STRTAB_STE_0_CFG, dst->data[0]);
if (cfg == STRTAB_STE_0_CFG_S1_TRANS) {
size_t nr_entries, cd_sz;
u64 cd_table;
cd_table = (dst->data[0] & STRTAB_STE_0_S1CTXPTR_MASK);
nr_entries = 1 << FIELD_GET(STRTAB_STE_0_S1CDMAX, dst->data[0]);
cd_sz = (1 << nr_entries) * (CTXDESC_CD_DWORDS << 3);
kvm_iommu_reclaim_pages(hyp_phys_to_virt(cd_table), get_order(cd_sz));
}
/* zap zippity zop. */
for (i = 0; i < STRTAB_STE_DWORDS; i++)
dst->data[i] = 0;
ret = smmu_sync_ste(smmu, sid);
}
}
kvm_iommu_unlock(iommu);
return ret;