ANDROID: KVM: arm64: Reland split the host ffa handle store

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 <sebastianene@google.com>
Reported-by: Arve Hjønnevåg <arve@android.com>
(cherry picked from commit 6c400c2e2e46f3a1117ce5da316ecdc1dbb1a031)
Signed-off-by: Lee Jones <joneslee@google.com>
This commit is contained in:
Sebastian Ene
2025-09-22 10:54:04 +00:00
committed by Lee Jones
parent 7b2f38b816
commit 793af0a746
+24 -22
View File
@@ -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;