From 97b35a4c104974b719496f5274be66ded8a9f197 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Fri, 14 Mar 2025 11:09:56 +0000 Subject: [PATCH] ANDROID: KVM: arm64: iommu: Return map error code The driver already returns the error code which is ignored by the hypercall, so return the error code in X0. And don't return -ENOMEM as that is communicated by requests. Bug: 401132481 Change-Id: I9479028f3c49c11aa3071bc24222027c5b4c1a85 Signed-off-by: Mostafa Saleh --- arch/arm64/kvm/hyp/include/nvhe/iommu.h | 2 +- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 8 +++++--- arch/arm64/kvm/hyp/nvhe/iommu/iommu.c | 18 ++++++++++++------ arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c | 6 +++--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h index 6980fd7dd252..2f20a2908369 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/iommu.h +++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h @@ -23,7 +23,7 @@ int kvm_iommu_detach_dev(pkvm_handle_t iommu_id, pkvm_handle_t domain_id, u32 endpoint_id, u32 pasid); size_t kvm_iommu_map_pages(pkvm_handle_t domain_id, unsigned long iova, phys_addr_t paddr, size_t pgsize, - size_t pgcount, int prot); + size_t pgcount, int prot, unsigned long *mapped); size_t kvm_iommu_unmap_pages(pkvm_handle_t domain_id, unsigned long iova, size_t pgsize, size_t pgcount); phys_addr_t kvm_iommu_iova_to_phys(pkvm_handle_t domain_id, unsigned long iova); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index e03abea3b46d..d80b2bdb6561 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -1744,7 +1744,8 @@ static void handle___pkvm_host_iommu_detach_dev(struct kvm_cpu_context *host_ctx static void handle___pkvm_host_iommu_map_pages(struct kvm_cpu_context *host_ctxt) { - unsigned long ret; + int ret; + unsigned long mapped; DECLARE_REG(pkvm_handle_t, domain, host_ctxt, 1); DECLARE_REG(unsigned long, iova, host_ctxt, 2); DECLARE_REG(phys_addr_t, paddr, host_ctxt, 3); @@ -1753,8 +1754,9 @@ static void handle___pkvm_host_iommu_map_pages(struct kvm_cpu_context *host_ctxt DECLARE_REG(unsigned int, prot, host_ctxt, 6); ret = kvm_iommu_map_pages(domain, iova, paddr, - pgsize, pgcount, prot); - hyp_reqs_smccc_encode(ret, host_ctxt, this_cpu_ptr(&host_hyp_reqs)); + pgsize, pgcount, prot, &mapped); + cpu_reg(host_ctxt, 0) = ret; + hyp_reqs_smccc_encode(mapped, host_ctxt, this_cpu_ptr(&host_hyp_reqs)); } static void handle___pkvm_host_iommu_unmap_pages(struct kvm_cpu_context *host_ctxt) diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c index 55caabfae3c2..f40f2d1a06b2 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c @@ -464,29 +464,32 @@ out_unlock: size_t kvm_iommu_map_pages(pkvm_handle_t domain_id, unsigned long iova, phys_addr_t paddr, size_t pgsize, - size_t pgcount, int prot) + size_t pgcount, int prot, unsigned long *mapped) { size_t size; int ret; size_t total_mapped = 0; struct kvm_hyp_iommu_domain *domain; + *mapped = 0; + if (prot & ~IOMMU_PROT_MASK) - return 0; + return -EOPNOTSUPP; if (__builtin_mul_overflow(pgsize, pgcount, &size) || iova + size < iova || paddr + size < paddr) - return 0; + return -E2BIG; domain = handle_to_domain(domain_id); if (!domain || domain_get(domain)) - return 0; + return -ENOENT; ret = __pkvm_use_dma(paddr, size, __get_vcpu()); if (ret) goto out_put_domain; - kvm_iommu_ops->map_pages(domain, iova, paddr, pgsize, pgcount, prot, &total_mapped); + ret = kvm_iommu_ops->map_pages(domain, iova, paddr, pgsize, pgcount, + prot, &total_mapped); pgcount -= total_mapped / pgsize; /* @@ -497,9 +500,12 @@ size_t kvm_iommu_map_pages(pkvm_handle_t domain_id, if (pgcount) __pkvm_unuse_dma(paddr + total_mapped, pgcount * pgsize, __get_vcpu()); + *mapped = total_mapped; + out_put_domain: domain_put(domain); - return total_mapped; + /* Mask -ENOMEM, as it's passed as a request. */ + return ret == -ENOMEM ? 0 : ret; } static inline void kvm_iommu_iotlb_sync(struct kvm_hyp_iommu_domain *domain, diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c index 33db3917f643..ddd9f9ffdee1 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/pviommu.c @@ -282,9 +282,9 @@ static bool pkvm_guest_iommu_map(struct pkvm_hyp_vcpu *hyp_vcpu, u64 *exit_code) break; } - mapped = kvm_iommu_map_pages(domain, iova, paddr, - PAGE_SIZE, min(size, kvm_granule_size(level)) / PAGE_SIZE, - __smccc_prot_linux(prot)); + kvm_iommu_map_pages(domain, iova, paddr, + PAGE_SIZE, min(size, kvm_granule_size(level)) / PAGE_SIZE, + __smccc_prot_linux(prot), &mapped); WARN_ON(__pkvm_unuse_dma(paddr, kvm_granule_size(level), hyp_vcpu)); if (!mapped) { if (!__need_req(vcpu)) {