Hi Bertrand, On Wed, Feb 11, 2026 at 6:16 PM Bertrand Marquis <[email protected]> wrote: > > 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 <[email protected]> > --- > Changes since v1: > - Remove marking rx buffer as free during teardown as it is useless > - Add a comment when calling rxtx_unmap during teardown to remind code > readers that true is for teardown mode > --- > xen/arch/arm/tee/ffa_rxtx.c | 32 +++++++++++++++++++++++++++++--- > 1 file changed, 29 insertions(+), 3 deletions(-)
Looks good: Reviewed-by: Jens Wiklander <[email protected]> Cheers, Jens > > diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c > index eff95a7955d7..c4fc4c4934af 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,32 @@ 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 > + { > + 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 +287,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 +395,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 /* teardown */); > } > > void *ffa_rxtx_spmc_rx_acquire(void) > -- > 2.52.0 >
