ANDROID: KVM: arm64: iommu: Use force_free for free_domain
Previously, free_domain would call the io-pgtable-arm free_domain
which destroys the page table. However, the it can have valid
entries, for the host that would mean that this memory won't
be allowed to be donated anywhere, however allowing that
from guest would mean that the guest can break the host,
by mapping pages in the domain and freeing the domain without
doing an unmap first.
So, just force_free domain to clean the pages mapped in the
domain after destroying it.
Alternatively, we can keep track of mapped pages and reject
to free domains that are busy.
Change-Id: I1d02c1de030e0ab43d8b3342f46460004f4f07e6
Signed-off-by: Mostafa Saleh <smostafa@google.com>
diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
index d31a95c..7f203f1 100644
--- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
+++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c
@@ -306,6 +306,7 @@ int kvm_iommu_free_domain(pkvm_handle_t domain_id)
{
int ret = 0;
struct kvm_hyp_iommu_domain *domain;
+ struct kvm_iommu_paddr_cache *cache = this_cpu_ptr(&kvm_iommu_unmap_cache);
domain = handle_to_domain(domain_id);
ret = access_allowed(domain);
@@ -318,7 +319,8 @@ int kvm_iommu_free_domain(pkvm_handle_t domain_id)
goto out_unlock;
}
- kvm_iommu_ops->free_domain(domain);
+ kvm_iommu_ops->force_free_domain(domain, cache);
+ kvm_iommu_flush_unmap_cache(cache);
/* Set domain->refs to 0 and mark it as unused. */
memset(domain, 0, sizeof(*domain));