From 2bc6495fedcec3d3e8ab5bb4ce49435a08c6d3a4 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Thu, 28 Oct 2021 14:23:05 +0100 Subject: [PATCH] ANDROID: KVM: arm64: Add 'host_stage2_adjust_mmio_range' to kvm_iommu_ops Add a new kvm_iommu_ops hook to the lower-EL instruction/data abort handler, which allows the IOMMU driver to restrict the region of device memory that is about to be mapped in the host stage-2. This can be used by the IOMMU driver to restrict access to the MMIO registers of the IOMMU itself. Test: builds, boots Bug: 190463801 Change-Id: I51cf3cfd84c889627e290d74579657447964ca16 Signed-off-by: David Brazdil (cherry picked from commit cc1ad46fb2618ea2346e52ace4b010b364d10e65) Signed-off-by: Mostafa Saleh Signed-off-by: Quentin Perret --- arch/arm64/include/asm/kvm_hyp.h | 2 ++ arch/arm64/kvm/hyp/nvhe/mem_protect.c | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index ffed0238279f..4728b1321d51 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -138,6 +138,8 @@ struct kvm_iommu_ops { phys_addr_t fault_pa, unsigned int len, bool is_write, int rd); void (*host_stage2_set_owner)(phys_addr_t addr, size_t size, u32 owner_id); + int (*host_stage2_adjust_mmio_range)(phys_addr_t addr, phys_addr_t *start, + phys_addr_t *end); }; extern struct kvm_iommu_ops kvm_iommu_ops; diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index eb6fe11362d4..c6f40dfc63ef 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -624,6 +624,17 @@ static int host_stage2_idmap(u64 addr) prot = is_memory ? PKVM_HOST_MEM_PROT : PKVM_HOST_MMIO_PROT; + /** + * Let device drivers adjust the permitted range first. + * host_stage2_adjust_range() should be last to also properly align it. + */ + if (!is_memory && kvm_iommu_ops.host_stage2_adjust_mmio_range) { + ret = kvm_iommu_ops.host_stage2_adjust_mmio_range(addr, &range.start, + &range.end); + if (ret) + return ret; + } + host_lock_component(); ret = host_stage2_adjust_range(addr, &range); if (ret)