mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
FROMLIST: KVM: arm64: Handle FFA_MEM_RECLAIM calls from the host
Intecept FFA_MEM_RECLAIM calls from the host and transition the host stage-2 page-table entries from the SHARED_OWNED state back to the OWNED state once EL3 has confirmed that the secure mapping has been reclaimed. Bug: 254811097 Change-Id: I58365e1b3fafa47f290a292fe57f6d2ed7f9091b Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Quentin Perret <qperret@google.com> Link: https://lore.kernel.org/r/20221116170335.2341003-11-qperret@google.com Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
committed by
Quentin Perret
parent
8453f39a4a
commit
2e47f0ecdc
@@ -130,6 +130,23 @@ static void spmd_mem_share(struct arm_smccc_res *res, u32 len, u32 fraglen)
|
||||
res);
|
||||
}
|
||||
|
||||
static void spmd_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo,
|
||||
u32 handle_hi, u32 flags)
|
||||
{
|
||||
arm_smccc_1_1_smc(FFA_MEM_RECLAIM,
|
||||
handle_lo, handle_hi, flags,
|
||||
0, 0, 0, 0,
|
||||
res);
|
||||
}
|
||||
|
||||
static void spmd_retrieve_req(struct arm_smccc_res *res, u32 len)
|
||||
{
|
||||
arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ,
|
||||
len, len,
|
||||
0, 0, 0, 0, 0,
|
||||
res);
|
||||
}
|
||||
|
||||
static void do_ffa_rxtx_map(struct arm_smccc_res *res,
|
||||
struct kvm_cpu_context *ctxt)
|
||||
{
|
||||
@@ -381,6 +398,65 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
|
||||
struct kvm_cpu_context *ctxt)
|
||||
{
|
||||
DECLARE_REG(u32, handle_lo, ctxt, 1);
|
||||
DECLARE_REG(u32, handle_hi, ctxt, 2);
|
||||
DECLARE_REG(u32, flags, ctxt, 3);
|
||||
struct ffa_composite_mem_region *reg;
|
||||
struct ffa_mem_region *buf;
|
||||
int ret = 0;
|
||||
u32 offset;
|
||||
u64 handle;
|
||||
|
||||
handle = PACK_HANDLE(handle_lo, handle_hi);
|
||||
|
||||
hyp_spin_lock(&host_buffers.lock);
|
||||
|
||||
buf = hyp_buffers.tx;
|
||||
*buf = (struct ffa_mem_region) {
|
||||
.sender_id = HOST_FFA_ID,
|
||||
.handle = handle,
|
||||
};
|
||||
|
||||
spmd_retrieve_req(res, sizeof(*buf));
|
||||
buf = hyp_buffers.rx;
|
||||
if (res->a0 != FFA_MEM_RETRIEVE_RESP)
|
||||
goto out_unlock;
|
||||
|
||||
/* Check for fragmentation */
|
||||
if (res->a1 != res->a2) {
|
||||
ret = FFA_RET_ABORTED;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
offset = buf->ep_mem_access[0].composite_off;
|
||||
/*
|
||||
* We can trust the SPMD to get this right, but let's at least
|
||||
* check that we end up with something that doesn't look _completely_
|
||||
* bogus.
|
||||
*/
|
||||
if (WARN_ON(offset > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
|
||||
ret = FFA_RET_ABORTED;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
reg = (void *)buf + offset;
|
||||
spmd_mem_reclaim(res, handle_lo, handle_hi, flags);
|
||||
if (res->a0 != FFA_SUCCESS)
|
||||
goto out_unlock;
|
||||
|
||||
/* If the SPMD was happy, then we should be too. */
|
||||
WARN_ON(ffa_host_unshare_ranges(reg->constituents,
|
||||
reg->addr_range_cnt));
|
||||
out_unlock:
|
||||
hyp_spin_unlock(&host_buffers.lock);
|
||||
|
||||
if (ret)
|
||||
ffa_to_smccc_res(res, ret);
|
||||
}
|
||||
|
||||
static bool ffa_call_unsupported(u64 func_id)
|
||||
{
|
||||
switch (func_id) {
|
||||
@@ -461,9 +537,11 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
|
||||
case FFA_FN64_MEM_SHARE:
|
||||
do_ffa_mem_share(&res, host_ctxt);
|
||||
goto out_handled;
|
||||
case FFA_MEM_RECLAIM:
|
||||
do_ffa_mem_reclaim(&res, host_ctxt);
|
||||
goto out_handled;
|
||||
case FFA_MEM_LEND:
|
||||
case FFA_FN64_MEM_LEND:
|
||||
case FFA_MEM_RECLAIM:
|
||||
case FFA_MEM_FRAG_TX:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user