rxtx_unmap() checks RX ownership without holding the RX/TX locks and
only enforces the ownership rule when FFA_RX_ACQUIRE is supported. This
allows a vCPU to acquire RX between the check and unmap, and it lets
RXTX_UNMAP proceed while RX is owned when buffers are not forwarded to
firmware.
Hold rx_lock/tx_lock across the ownership check and unmap, and deny
RXTX_UNMAP whenever RX is owned, independent of RX_ACQUIRE support. For
teardown, release RX ownership under the same lock window; use
FFA_RX_RELEASE directly because rx_lock is held, and clear the local
flag when the firmware path is unavailable.
Functional impact: RXTX_UNMAP now reliably returns DENIED while RX is
owned, and teardown releases/clears ownership without a race.
Signed-off-by: Bertrand Marquis <bertrand.marquis@arm.com>
---
xen/arch/arm/tee/ffa_rxtx.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c
index eff95a7955d7..450ce102cbdc 100644
--- a/xen/arch/arm/tee/ffa_rxtx.c
+++ b/xen/arch/arm/tee/ffa_rxtx.c
@@ -220,7 +220,7 @@ err_unlock_rxtx:
return ret;
}
-static int32_t rxtx_unmap(struct domain *d)
+static int32_t rxtx_unmap(struct domain *d, bool teardown)
{
struct ffa_ctx *ctx = d->arch.tee;
int32_t ret = FFA_RET_OK;
@@ -234,6 +234,36 @@ static int32_t rxtx_unmap(struct domain *d)
goto err_unlock_rxtx;
}
+ if ( !ctx->rx_is_free )
+ {
+ if ( teardown )
+ {
+ if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) )
+ {
+ int32_t rel_ret;
+
+ /* Can't use ffa_rx_release() while holding rx_lock. */
+ rel_ret = ffa_simple_call(FFA_RX_RELEASE, ctx->ffa_id,
+ 0, 0, 0);
+ if ( rel_ret )
+ gdprintk(XENLOG_DEBUG,
+ "ffa: RX release during teardown failed: %d\n",
+ rel_ret);
+ else
+ ctx->rx_is_free = true;
+ }
+ else
+ ctx->rx_is_free = true;
+ }
+ else
+ {
+ gdprintk(XENLOG_DEBUG,
+ "ffa: RXTX_UNMAP denied, RX buffer owned by VM\n");
+ ret = FFA_RET_DENIED;
+ goto err_unlock_rxtx;
+ }
+ }
+
if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) )
{
ret = ffa_rxtx_unmap(ffa_get_vm_id(d));
@@ -261,7 +291,7 @@ err_unlock_rxtx:
int32_t ffa_handle_rxtx_unmap(void)
{
- return rxtx_unmap(current->domain);
+ return rxtx_unmap(current->domain, false);
}
int32_t ffa_rx_acquire(struct ffa_ctx *ctx, void **buf, size_t *buf_size)
@@ -369,7 +399,7 @@ int32_t ffa_rxtx_domain_init(struct domain *d)
void ffa_rxtx_domain_destroy(struct domain *d)
{
- rxtx_unmap(d);
+ rxtx_unmap(d, true);
}
void *ffa_rxtx_spmc_rx_acquire(void)
--
2.50.1 (Apple Git-155)