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)