@@ -538,6 +538,12 @@ static int32_t ffa_mem_share(uint32_t tot_len, uint32_t frag_len,
}
}
+static int32_t ffa_mem_reclaim(uint32_t handle_lo, uint32_t handle_hi,
+ uint32_t flags)
+{
+ return ffa_simple_call(FFA_MEM_RECLAIM, handle_lo, handle_hi, flags, 0);
+}
+
static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id,
uint8_t msg)
{
@@ -1278,6 +1284,43 @@ out_set_ret:
set_regs_error(regs, ret);
}
+static int handle_mem_reclaim(uint64_t handle, uint32_t flags)
+{
+ struct domain *d = current->domain;
+ struct ffa_ctx *ctx = d->arch.tee;
+ struct ffa_shm_mem *shm;
+ register_t handle_hi;
+ register_t handle_lo;
+ int ret;
+
+ spin_lock(&ctx->lock);
+ list_for_each_entry(shm, &ctx->shm_list, list)
+ {
+ if ( shm->handle == handle )
+ goto found_it;
+ }
+ shm = NULL;
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out;
+found_it:
+
+ uint64_to_regpair(&handle_hi, &handle_lo, handle);
+ ret = ffa_mem_reclaim(handle_lo, handle_hi, flags);
+ if ( ret )
+ {
+ shm = NULL;
+ goto out;
+ }
+
+ list_del(&shm->list);
+
+out:
+ free_ffa_shm_mem(ctx, shm);
+ spin_unlock(&ctx->lock);
+
+ return ret;
+}
+
static bool ffa_handle_call(struct cpu_user_regs *regs)
{
uint32_t fid = get_user_reg(regs, 0);
@@ -1339,6 +1382,15 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
case FFA_MEM_SHARE_64:
handle_mem_share(regs);
return true;
+ case FFA_MEM_RECLAIM:
+ e = handle_mem_reclaim(regpair_to_uint64(get_user_reg(regs, 2),
+ get_user_reg(regs, 1)),
+ get_user_reg(regs, 3));
+ if ( e )
+ set_regs_error(regs, e);
+ else
+ set_regs_success(regs, 0, 0);
+ return true;
default:
gprintk(XENLOG_ERR, "ffa: unhandled fid 0x%x\n", fid);
@@ -1573,6 +1625,7 @@ static bool ffa_probe(void)
!check_mandatory_feature(FFA_MEM_SHARE_64) ||
!check_mandatory_feature(FFA_RXTX_UNMAP) ||
!check_mandatory_feature(FFA_MEM_SHARE_32) ||
+ !check_mandatory_feature(FFA_MEM_RECLAIM) ||
!check_mandatory_feature(FFA_MSG_SEND_DIRECT_REQ_32) )
return false;