From 793af0a7461cc45934bf4651f3d2ac14fc68be74 Mon Sep 17 00:00:00 2001 From: Sebastian Ene Date: Mon, 22 Sep 2025 10:54:04 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Reland split the host ffa handle store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reserve an ffa handle entry before we commit the memory transfer to TZ to avoid rolling back the memory transaction with TZ in case we have no space the accomodate the handle. Bug: 440584506 Bug: 357781595 Fixes: Ifbdc82adb2675f5e7d1ee16ec5356c6f24b031bb Change-Id: Ie5307769e5e3913de4b974d8f3d829cacc84aa9e Signed-off-by: Sebastian Ene Reported-by: Arve Hjønnevåg (cherry picked from commit 6c400c2e2e46f3a1117ce5da316ecdc1dbb1a031) Signed-off-by: Lee Jones --- arch/arm64/kvm/hyp/nvhe/ffa.c | 46 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c index feaba59af32e..b595d5d80d3c 100644 --- a/arch/arm64/kvm/hyp/nvhe/ffa.c +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c @@ -113,33 +113,27 @@ static struct kvm_ffa_buffers *ffa_get_buffers(struct pkvm_hyp_vcpu *hyp_vcpu) DECLARE_STATIC_KEY_FALSE(kvm_ffa_unmap_on_lend); -static int ffa_host_store_handle(u64 ffa_handle, bool is_lend) +static struct ffa_handle *ffa_host_alloc_handle(void) { u32 i; - struct ffa_handle *free_handle = NULL; - - if (!static_branch_unlikely(&kvm_ffa_unmap_on_lend)) - return 0; + struct ffa_handle *handle; if (spm_free_handle) { WARN_ON(spm_free_handle < spm_handles || spm_free_handle >= (spm_handles + num_spm_handles)); - free_handle = spm_free_handle; + handle = spm_free_handle; spm_free_handle = NULL; - } else { - for (i = 0; i < num_spm_handles; i++) - if (spm_handles[i].handle == FFA_INVALID_SPM_HANDLE) - break; - - if (i == num_spm_handles) - return -ENOSPC; - - free_handle = &spm_handles[i]; + return handle; } - free_handle->handle = ffa_handle; - free_handle->is_lend = is_lend; - return 0; + for (i = 0; i < num_spm_handles; i++) + if (spm_handles[i].handle == FFA_INVALID_SPM_HANDLE) + break; + + if (i == num_spm_handles) + return NULL; + + return &spm_handles[i]; } static struct ffa_handle *ffa_host_get_handle(u64 ffa_handle) @@ -909,6 +903,7 @@ static int __do_ffa_mem_xfer(const u64 func_id, struct ffa_mem_transfer *transfer = NULL; u64 ffa_handle; bool is_lend = func_id == FFA_FN64_MEM_LEND; + struct ffa_handle *handle = NULL; if (addr_mbz || npages_mbz || fraglen > len || fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) { @@ -1009,6 +1004,14 @@ static int __do_ffa_mem_xfer(const u64 func_id, if (ret) goto out_unlock; + if (!hyp_vcpu && static_branch_unlikely(&kvm_ffa_unmap_on_lend)) { + handle = ffa_host_alloc_handle(); + if (!handle) { + ret = -ENOSPC; + goto out_unlock; + } + } + ffa_mem_xfer(res, func_id, len, fraglen); if (fraglen != len) { if (res->a0 != FFA_MEM_FRAG_RX) @@ -1027,10 +1030,9 @@ static int __do_ffa_mem_xfer(const u64 func_id, if (hyp_vcpu && transfer) { transfer->ffa_handle = ffa_handle; list_add(&transfer->node, &ffa_buf->xfer_list); - } else if (!hyp_vcpu) { - ret = ffa_host_store_handle(ffa_handle, is_lend); - if (ret) - goto err_unshare; + } else if (handle) { + handle->handle = ffa_handle; + handle->is_lend = is_lend; } hyp_spin_unlock(&kvm_ffa_hyp_lock); return 0;