[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 05/10] xen/arm: ffa: Rework partition info get



Hi Bertrand,

On Wed, Oct 16, 2024 at 10:32 AM Bertrand Marquis
<bertrand.marquis@xxxxxxx> wrote:
>
> Rework the partition info get implementation to use the correct size of
> structure depending on the version of the protocol and simplifies the
> structure copy to use only memcpy and prevent recreating the structure
> each time.
> The goal here is to have an implementation that will be easier to
> maintain in the long term as the specification is only adding fields to
> structure with versions to simplify support of several protocol
> versions and as such an SPMC implementation in the future could use this
> and return a size higher than the one we expect.
> The patch is fixing the part_info_get function for this and the
> subscriber discovery on probe.
>
> No functional changes expected.
>
> Signed-off-by: Bertrand Marquis <bertrand.marquis@xxxxxxx>
> ---
> Changes in v2:
> - rebase
> ---
>  xen/arch/arm/tee/ffa.c          |  13 +--
>  xen/arch/arm/tee/ffa_partinfo.c | 185 ++++++++++++++++++++------------
>  xen/arch/arm/tee/ffa_private.h  |   4 +-
>  3 files changed, 118 insertions(+), 84 deletions(-)

Looks good.
Reviewed-by: Jens Wiklander <jens.wiklander@xxxxxxxxxx>

Cheers,
Jens

>
> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
> index 267d4435ac08..4b55e8b48f01 100644
> --- a/xen/arch/arm/tee/ffa.c
> +++ b/xen/arch/arm/tee/ffa.c
> @@ -311,8 +311,6 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
>      uint32_t fid = get_user_reg(regs, 0);
>      struct domain *d = current->domain;
>      struct ffa_ctx *ctx = d->arch.tee;
> -    uint32_t fpi_size;
> -    uint32_t count;
>      int e;
>
>      if ( !ctx )
> @@ -338,16 +336,7 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
>          e = ffa_handle_rxtx_unmap();
>          break;
>      case FFA_PARTITION_INFO_GET:
> -        e = ffa_handle_partition_info_get(get_user_reg(regs, 1),
> -                                          get_user_reg(regs, 2),
> -                                          get_user_reg(regs, 3),
> -                                          get_user_reg(regs, 4),
> -                                          get_user_reg(regs, 5), &count,
> -                                          &fpi_size);
> -        if ( e )
> -            ffa_set_regs_error(regs, e);
> -        else
> -            ffa_set_regs_success(regs, count, fpi_size);
> +        ffa_handle_partition_info_get(regs);
>          return true;
>      case FFA_RX_RELEASE:
>          e = ffa_handle_rx_release();
> diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinfo.c
> index 99c48f0e5c05..75a073d090e0 100644
> --- a/xen/arch/arm/tee/ffa_partinfo.c
> +++ b/xen/arch/arm/tee/ffa_partinfo.c
> @@ -33,21 +33,24 @@ static uint16_t subscr_vm_created_count __read_mostly;
>  static uint16_t *subscr_vm_destroyed __read_mostly;
>  static uint16_t subscr_vm_destroyed_count __read_mostly;
>
> -static int32_t ffa_partition_info_get(uint32_t w1, uint32_t w2, uint32_t w3,
> -                                      uint32_t w4, uint32_t w5, uint32_t 
> *count,
> -                                      uint32_t *fpi_size)
> +static int32_t ffa_partition_info_get(uint32_t *uuid, uint32_t flags,
> +                                      uint32_t *count, uint32_t *fpi_size)
>  {
> -    const struct arm_smccc_1_2_regs arg = {
> +    struct arm_smccc_1_2_regs arg = {
>          .a0 = FFA_PARTITION_INFO_GET,
> -        .a1 = w1,
> -        .a2 = w2,
> -        .a3 = w3,
> -        .a4 = w4,
> -        .a5 = w5,
> +        .a5 = flags,
>      };
>      struct arm_smccc_1_2_regs resp;
>      uint32_t ret;
>
> +    if ( uuid )
> +    {
> +        arg.a1 = uuid[0];
> +        arg.a2 = uuid[1];
> +        arg.a3 = uuid[2];
> +        arg.a4 = uuid[3];
> +    }
> +
>      arm_smccc_1_2_smc(&arg, &resp);
>
>      ret = ffa_get_ret_code(&resp);
> @@ -60,13 +63,31 @@ static int32_t ffa_partition_info_get(uint32_t w1, 
> uint32_t w2, uint32_t w3,
>      return ret;
>  }
>
> -int32_t ffa_handle_partition_info_get(uint32_t w1, uint32_t w2, uint32_t w3,
> -                                      uint32_t w4, uint32_t w5, uint32_t 
> *count,
> -                                      uint32_t *fpi_size)
> +void ffa_handle_partition_info_get(struct cpu_user_regs *regs)
>  {
> -    int32_t ret = FFA_RET_DENIED;
> +    int32_t ret;
>      struct domain *d = current->domain;
>      struct ffa_ctx *ctx = d->arch.tee;
> +    uint32_t flags = get_user_reg(regs, 5);
> +    uint32_t uuid[4] = {
> +        get_user_reg(regs, 1),
> +        get_user_reg(regs, 2),
> +        get_user_reg(regs, 3),
> +        get_user_reg(regs, 4),
> +    };
> +    uint32_t src_size, dst_size;
> +    void *dst_buf;
> +    uint32_t ffa_sp_count = 0;
> +
> +    /*
> +     * If the guest is v1.0, he does not get back the entry size so we must
> +     * use the v1.0 structure size in the destination buffer.
> +     * Otherwise use the size of the highest version we support, here 1.1.
> +     */
> +    if ( ctx->guest_vers == FFA_VERSION_1_0 )
> +        dst_size = sizeof(struct ffa_partition_info_1_0);
> +    else
> +        dst_size = sizeof(struct ffa_partition_info_1_1);
>
>      /*
>       * FF-A v1.0 has w5 MBZ while v1.1 allows
> @@ -75,90 +96,105 @@ int32_t ffa_handle_partition_info_get(uint32_t w1, 
> uint32_t w2, uint32_t w3,
>       * FFA_PARTITION_INFO_GET_COUNT is only using registers and not the
>       * rxtx buffer so do the partition_info_get directly.
>       */
> -    if ( w5 == FFA_PARTITION_INFO_GET_COUNT_FLAG &&
> +    if ( flags == FFA_PARTITION_INFO_GET_COUNT_FLAG &&
>           ctx->guest_vers == FFA_VERSION_1_1 )
>      {
>          if ( ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) )
> -            return ffa_partition_info_get(w1, w2, w3, w4, w5, count, 
> fpi_size);
> +            ret = ffa_partition_info_get(uuid, flags, &ffa_sp_count,
> +                                        &src_size);
>          else
> -        {
> -            *count = 0;
> -            return FFA_RET_OK;
> -        }
> -    }
> -    if ( w5 )
> -        return FFA_RET_INVALID_PARAMETERS;
> +            ret = FFA_RET_OK;
>
> -    if ( !ffa_rx )
> -        return FFA_RET_DENIED;
> +        goto out;
> +    }
>
> -    if ( !spin_trylock(&ctx->rx_lock) )
> -        return FFA_RET_BUSY;
> +    if ( flags )
> +    {
> +        ret = FFA_RET_INVALID_PARAMETERS;
> +        goto out;
> +    }
>
>      if ( !ffa_fw_supports_fid(FFA_PARTITION_INFO_GET) )
>      {
> -        if ( ctx->guest_vers == FFA_VERSION_1_0 )
> -            *fpi_size = sizeof(struct ffa_partition_info_1_0);
> -        else
> -            *fpi_size = sizeof(struct ffa_partition_info_1_1);
> -
> -        *count = 0;
> +        /* Just give an empty partition list to the caller */
>          ret = FFA_RET_OK;
>          goto out;
>      }
>
> -    if ( !ctx->page_count || !ctx->rx_is_free )
> +    if ( !spin_trylock(&ctx->rx_lock) )
> +    {
> +        ret = FFA_RET_BUSY;
>          goto out;
> +    }
> +
> +    dst_buf = ctx->rx;
> +
> +    if ( !ffa_rx )
> +    {
> +        ret = FFA_RET_DENIED;
> +        goto out_rx_release;
> +    }
> +
> +    if ( !ctx->page_count || !ctx->rx_is_free )
> +    {
> +        ret = FFA_RET_DENIED;
> +        goto out_rx_release;
> +    }
> +
>      spin_lock(&ffa_rx_buffer_lock);
> -    ret = ffa_partition_info_get(w1, w2, w3, w4, w5, count, fpi_size);
> +
> +    ret = ffa_partition_info_get(uuid, 0, &ffa_sp_count, &src_size);
> +
>      if ( ret )
>          goto out_rx_buf_unlock;
> +
>      /*
>       * ffa_partition_info_get() succeeded so we now own the RX buffer we
>       * share with the SPMC. We must give it back using ffa_rx_release()
>       * once we've copied the content.
>       */
>
> -    if ( ctx->guest_vers == FFA_VERSION_1_0 )
> +    /* we cannot have a size smaller than 1.0 structure */
> +    if ( src_size < sizeof(struct ffa_partition_info_1_0) )
>      {
> -        size_t n;
> -        struct ffa_partition_info_1_1 *src = ffa_rx;
> -        struct ffa_partition_info_1_0 *dst = ctx->rx;
> -
> -        if ( ctx->page_count * FFA_PAGE_SIZE < *count * sizeof(*dst) )
> -        {
> -            ret = FFA_RET_NO_MEMORY;
> -            goto out_rx_release;
> -        }
> +        ret = FFA_RET_NOT_SUPPORTED;
> +        goto out_rx_hyp_release;
> +    }
>
> -        for ( n = 0; n < *count; n++ )
> -        {
> -            dst[n].id = src[n].id;
> -            dst[n].execution_context = src[n].execution_context;
> -            dst[n].partition_properties = src[n].partition_properties;
> -        }
> +    if ( ctx->page_count * FFA_PAGE_SIZE < ffa_sp_count * dst_size )
> +    {
> +        ret = FFA_RET_NO_MEMORY;
> +        goto out_rx_hyp_release;
>      }
> -    else
> +
> +    if ( ffa_sp_count > 0 )
>      {
> -        size_t sz = *count * *fpi_size;
> +        uint32_t n;
> +        void *src_buf = ffa_rx;
>
> -        if ( ctx->page_count * FFA_PAGE_SIZE < sz )
> +        /* copy the secure partitions info */
> +        for ( n = 0; n < ffa_sp_count; n++ )
>          {
> -            ret = FFA_RET_NO_MEMORY;
> -            goto out_rx_release;
> +            memcpy(dst_buf, src_buf, dst_size);
> +            dst_buf += dst_size;
> +            src_buf += src_size;
>          }
> -
> -        memcpy(ctx->rx, ffa_rx, sz);
>      }
> +
>      ctx->rx_is_free = false;
> -out_rx_release:
> +
> +out_rx_hyp_release:
>      ffa_rx_release();
>  out_rx_buf_unlock:
>      spin_unlock(&ffa_rx_buffer_lock);
> -out:
> +out_rx_release:
>      spin_unlock(&ctx->rx_lock);
>
> -    return ret;
> +out:
> +    if ( ret )
> +        ffa_set_regs_error(regs, ret);
> +    else
> +        ffa_set_regs_success(regs, ffa_sp_count, dst_size);
>  }
>
>  static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id,
> @@ -221,19 +257,28 @@ static void uninit_subscribers(void)
>          XFREE(subscr_vm_destroyed);
>  }
>
> -static bool init_subscribers(struct ffa_partition_info_1_1 *fpi, uint16_t 
> count)
> +static bool init_subscribers(uint16_t count, uint32_t fpi_size)
>  {
>      uint16_t n;
>      uint16_t c_pos;
>      uint16_t d_pos;
> +    struct ffa_partition_info_1_1 *fpi;
> +
> +    if ( fpi_size < sizeof(struct ffa_partition_info_1_1) )
> +    {
> +        printk(XENLOG_ERR "ffa: partition info size invalid: %u\n", 
> fpi_size);
> +        return false;
> +    }
>
>      subscr_vm_created_count = 0;
>      subscr_vm_destroyed_count = 0;
>      for ( n = 0; n < count; n++ )
>      {
> -        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_CREATED )
> +        fpi = ffa_rx + n * fpi_size;
> +
> +        if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED )
>              subscr_vm_created_count++;
> -        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
> +        if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
>              subscr_vm_destroyed_count++;
>      }
>
> @@ -252,10 +297,12 @@ static bool init_subscribers(struct 
> ffa_partition_info_1_1 *fpi, uint16_t count)
>
>      for ( c_pos = 0, d_pos = 0, n = 0; n < count; n++ )
>      {
> -        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_CREATED )
> -            subscr_vm_created[c_pos++] = fpi[n].id;
> -        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
> -            subscr_vm_destroyed[d_pos++] = fpi[n].id;
> +        fpi = ffa_rx + n * fpi_size;
> +
> +        if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED )
> +            subscr_vm_created[c_pos++] = fpi->id;
> +        if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
> +            subscr_vm_destroyed[d_pos++] = fpi->id;
>      }
>
>      return true;
> @@ -275,7 +322,7 @@ bool ffa_partinfo_init(void)
>           !ffa_rx || !ffa_tx )
>          return false;
>
> -    e = ffa_partition_info_get(0, 0, 0, 0, 0, &count, &fpi_size);
> +    e = ffa_partition_info_get(NULL, 0, &count, &fpi_size);
>      if ( e )
>      {
>          printk(XENLOG_ERR "ffa: Failed to get list of SPs: %d\n", e);
> @@ -288,7 +335,7 @@ bool ffa_partinfo_init(void)
>          goto out;
>      }
>
> -    ret = init_subscribers(ffa_rx, count);
> +    ret = init_subscribers(count, fpi_size);
>
>  out:
>      ffa_rx_release();
> diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
> index 85eb61c13464..e5bc73f9039e 100644
> --- a/xen/arch/arm/tee/ffa_private.h
> +++ b/xen/arch/arm/tee/ffa_private.h
> @@ -316,9 +316,7 @@ int ffa_handle_mem_reclaim(uint64_t handle, uint32_t 
> flags);
>  bool ffa_partinfo_init(void);
>  int ffa_partinfo_domain_init(struct domain *d);
>  bool ffa_partinfo_domain_destroy(struct domain *d);
> -int32_t ffa_handle_partition_info_get(uint32_t w1, uint32_t w2, uint32_t w3,
> -                                      uint32_t w4, uint32_t w5, uint32_t 
> *count,
> -                                      uint32_t *fpi_size);
> +void ffa_handle_partition_info_get(struct cpu_user_regs *regs);
>
>  bool ffa_rxtx_init(void);
>  void ffa_rxtx_destroy(void);
> --
> 2.47.0
>



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.