Skip to content

Commit d66e50b

Browse files
vdonnefortMarc Zyngier
authored andcommitted
KVM: arm64: FFA: Release hyp rx buffer
According to the FF-A spec (Buffer states and ownership), after a producer has written into a buffer, it is "full" and now owned by the consumer. The producer won't be able to use that buffer, until the consumer hands it over with an invocation such as RX_RELEASE. It is clear in the following paragraph (Transfer of buffer ownership), that MEM_RETRIEVE_RESP is transferring the ownership from producer (in our case SPM) to consumer (hypervisor). RX_RELEASE is therefore mandatory here. It is less clear though what is happening with MEM_FRAG_TX. But this invocation, as a response to MEM_FRAG_RX writes into the same hypervisor RX buffer (see paragraph "Transmission of transaction descriptor in fragments"). Also this is matching the TF-A implementation where the RX buffer is marked "full" during a MEM_FRAG_RX. Release the RX hypervisor buffer in those two cases. This will unblock later invocations using this buffer which would otherwise fail. (RETRIEVE_REQ, MEM_FRAG_RX and PARTITION_INFO_GET). Signed-off-by: Vincent Donnefort <vdonnefort@google.com> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com> Link: https://lore.kernel.org/r/20240611175317.1220842-1-vdonnefort@google.com Signed-off-by: Marc Zyngier <maz@kernel.org>
1 parent 0d92e4a commit d66e50b

File tree

1 file changed

+12
-0
lines changed
  • arch/arm64/kvm/hyp/nvhe

1 file changed

+12
-0
lines changed

arch/arm64/kvm/hyp/nvhe/ffa.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len)
177177
res);
178178
}
179179

180+
static void ffa_rx_release(struct arm_smccc_res *res)
181+
{
182+
arm_smccc_1_1_smc(FFA_RX_RELEASE,
183+
0, 0,
184+
0, 0, 0, 0, 0,
185+
res);
186+
}
187+
180188
static void do_ffa_rxtx_map(struct arm_smccc_res *res,
181189
struct kvm_cpu_context *ctxt)
182190
{
@@ -543,16 +551,19 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
543551
if (WARN_ON(offset > len ||
544552
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
545553
ret = FFA_RET_ABORTED;
554+
ffa_rx_release(res);
546555
goto out_unlock;
547556
}
548557

549558
if (len > ffa_desc_buf.len) {
550559
ret = FFA_RET_NO_MEMORY;
560+
ffa_rx_release(res);
551561
goto out_unlock;
552562
}
553563

554564
buf = ffa_desc_buf.buf;
555565
memcpy(buf, hyp_buffers.rx, fraglen);
566+
ffa_rx_release(res);
556567

557568
for (fragoff = fraglen; fragoff < len; fragoff += fraglen) {
558569
ffa_mem_frag_rx(res, handle_lo, handle_hi, fragoff);
@@ -563,6 +574,7 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
563574

564575
fraglen = res->a3;
565576
memcpy((void *)buf + fragoff, hyp_buffers.rx, fraglen);
577+
ffa_rx_release(res);
566578
}
567579

568580
ffa_mem_reclaim(res, handle_lo, handle_hi, flags);

0 commit comments

Comments
 (0)