On 05/02/2024 3:49 pm, Jens Wiklander wrote:
> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
> index 0793c1c7585d..bbb6b819ee2b 100644
> --- a/xen/arch/arm/tee/ffa.c
> +++ b/xen/arch/arm/tee/ffa.c
> @@ -992,53 +1008,75 @@ static void put_shm_pages(struct ffa_shm_mem *shm)
>      }
>  }
>  
> -static bool inc_ctx_shm_count(struct ffa_ctx *ctx)
> +static bool inc_ctx_shm_count(struct domain *d, struct ffa_ctx *ctx)
>  {
>      bool ret = true;
>  
>      spin_lock(&ctx->lock);
> +
> +    /*
> +     * If this is the first shm added, increase the domain reference
> +     * counter as we need to keep domain around a bit longer to reclaim the
> +     * shared memory in the teardown path.
> +     */
> +    if ( !ctx->shm_count )
> +        get_knownalive_domain(d);
> +
>      if (ctx->shm_count >= FFA_MAX_SHM_COUNT)
>          ret = false;
>      else
>          ctx->shm_count++;
> +
>      spin_unlock(&ctx->lock);

This is subtle.  It reads as if there is a reference leak.  There really
will be one if FFA_MAX_SHM_COUNT happens to be 0.

You could add a BUILD_BUG_ON(), but IMO it would be far clearer to
follow if you moved the get_knownalive_domain() into the else clause.

>  
>      return ret;
>  }
>  
> -static void dec_ctx_shm_count(struct ffa_ctx *ctx)
> +static void dec_ctx_shm_count(struct domain *d, struct ffa_ctx *ctx)
>  {
>      spin_lock(&ctx->lock);
> +
>      ASSERT(ctx->shm_count > 0);
>      ctx->shm_count--;
> +
> +    /*
> +     * If this was the last shm removed, let go of the domain reference we
> +     * took in inc_ctx_shm_count() above.
> +     */
> +    if ( !ctx->shm_count )
> +        put_domain(d);
> +
>      spin_unlock(&ctx->lock);

You want a local bool called drop_ref, set within the lock, and move the
put_domain() down here.  put_domain() is potentially a large operation.

~Andrew

Reply via email to