All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jens Wiklander <jens.wiklander@linaro.org>
To: xen-devel@lists.xenproject.org
Cc: patches@linaro.org, Jens Wiklander <jens.wiklander@linaro.org>,
	Volodymyr Babchuk <volodymyr_babchuk@epam.com>,
	Stefano Stabellini <sstabellini@kernel.org>,
	Julien Grall <julien@xen.org>,
	Bertrand Marquis <bertrand.marquis@arm.com>,
	Michal Orzel <michal.orzel@amd.com>
Subject: [XEN PATCH 4/6] xen/arm: ffa: separate partition info get routines
Date: Mon, 25 Mar 2024 10:39:02 +0100	[thread overview]
Message-ID: <20240325093904.3466092-5-jens.wiklander@linaro.org> (raw)
In-Reply-To: <20240325093904.3466092-1-jens.wiklander@linaro.org>

Move partition info get routines into a separate file for easier
navigation in the source code.

Add ffa_partinfo_init(), ffa_partinfo_domain_init(), and
ffa_partinfo_domain_destroy() to handle the ffa_partinfo internal things
on initialization and teardown.

Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
---
 xen/arch/arm/tee/Makefile       |   1 +
 xen/arch/arm/tee/ffa.c          | 359 +-----------------------------
 xen/arch/arm/tee/ffa_partinfo.c | 373 ++++++++++++++++++++++++++++++++
 xen/arch/arm/tee/ffa_private.h  |  14 +-
 4 files changed, 398 insertions(+), 349 deletions(-)
 create mode 100644 xen/arch/arm/tee/ffa_partinfo.c

diff --git a/xen/arch/arm/tee/Makefile b/xen/arch/arm/tee/Makefile
index 0e683d23aa9d..be644fba8055 100644
--- a/xen/arch/arm/tee/Makefile
+++ b/xen/arch/arm/tee/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_FFA) += ffa.o
 obj-$(CONFIG_FFA) += ffa_shm.o
+obj-$(CONFIG_FFA) += ffa_partinfo.o
 obj-y += tee.o
 obj-$(CONFIG_OPTEE) += optee.o
diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c
index db36292dc52f..7a2803881420 100644
--- a/xen/arch/arm/tee/ffa.c
+++ b/xen/arch/arm/tee/ffa.c
@@ -70,20 +70,6 @@
  * structs ending with _1_1 are defined in FF-A-1.1-REL0.
  */
 
-/* Partition information descriptor */
-struct ffa_partition_info_1_0 {
-    uint16_t id;
-    uint16_t execution_context;
-    uint32_t partition_properties;
-};
-
-struct ffa_partition_info_1_1 {
-    uint16_t id;
-    uint16_t execution_context;
-    uint32_t partition_properties;
-    uint8_t uuid[16];
-};
-
 /* Endpoint RX/TX descriptor */
 struct ffa_endpoint_rxtx_descriptor_1_0 {
     uint16_t sender_id;
@@ -102,11 +88,6 @@ struct ffa_endpoint_rxtx_descriptor_1_1 {
 /* Negotiated FF-A version to use with the SPMC */
 static uint32_t __ro_after_init ffa_version;
 
-/* SPs subscribing to VM_CREATE and VM_DESTROYED events */
-static uint16_t *subscr_vm_created __read_mostly;
-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;
 
 /*
  * Our rx/tx buffers shared with the SPMC. FFA_RXTX_PAGE_COUNT is the
@@ -170,90 +151,6 @@ static int32_t ffa_rxtx_map(paddr_t tx_addr, paddr_t rx_addr,
     return ffa_simple_call(FFA_RXTX_MAP_64, tx_addr, rx_addr, page_count, 0);
 }
 
-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)
-{
-    const struct arm_smccc_1_2_regs arg = {
-        .a0 = FFA_PARTITION_INFO_GET,
-        .a1 = w1,
-        .a2 = w2,
-        .a3 = w3,
-        .a4 = w4,
-        .a5 = w5,
-    };
-    struct arm_smccc_1_2_regs resp;
-    uint32_t ret;
-
-    arm_smccc_1_2_smc(&arg, &resp);
-
-    ret = ffa_get_ret_code(&resp);
-    if ( !ret )
-    {
-        *count = resp.a2;
-        *fpi_size = resp.a3;
-    }
-
-    return ret;
-}
-
-static int32_t ffa_rx_release(void)
-{
-    return ffa_simple_call(FFA_RX_RELEASE, 0, 0, 0, 0);
-}
-
-static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id,
-                                      uint8_t msg)
-{
-    uint32_t exp_resp = FFA_MSG_FLAG_FRAMEWORK;
-    unsigned int retry_count = 0;
-    int32_t res;
-
-    if ( msg == FFA_MSG_SEND_VM_CREATED )
-        exp_resp |= FFA_MSG_RESP_VM_CREATED;
-    else if ( msg == FFA_MSG_SEND_VM_DESTROYED )
-        exp_resp |= FFA_MSG_RESP_VM_DESTROYED;
-    else
-        return FFA_RET_INVALID_PARAMETERS;
-
-    do {
-        const struct arm_smccc_1_2_regs arg = {
-            .a0 = FFA_MSG_SEND_DIRECT_REQ_32,
-            .a1 = sp_id,
-            .a2 = FFA_MSG_FLAG_FRAMEWORK | msg,
-            .a5 = vm_id,
-        };
-        struct arm_smccc_1_2_regs resp;
-
-        arm_smccc_1_2_smc(&arg, &resp);
-        if ( resp.a0 != FFA_MSG_SEND_DIRECT_RESP_32 || resp.a2 != exp_resp )
-        {
-            /*
-             * This is an invalid response, likely due to some error in the
-             * implementation of the ABI.
-             */
-            return FFA_RET_INVALID_PARAMETERS;
-        }
-        res = resp.a3;
-        if ( ++retry_count > 10 )
-        {
-            /*
-             * TODO
-             * FFA_RET_INTERRUPTED means that the SPMC has a pending
-             * non-secure interrupt, we need a way of delivering that
-             * non-secure interrupt.
-             * FFA_RET_RETRY is the SP telling us that it's temporarily
-             * blocked from handling the direct request, we need a generic
-             * way to deal with this.
-             * For now in both cases, give up after a few retries.
-             */
-            return res;
-        }
-    } while ( res == FFA_RET_INTERRUPTED || res == FFA_RET_RETRY );
-
-    return res;
-}
-
 static void handle_version(struct cpu_user_regs *regs)
 {
     struct domain *d = current->domain;
@@ -371,88 +268,6 @@ static uint32_t ffa_handle_rxtx_unmap(void)
     return FFA_RET_OK;
 }
 
-static 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)
-{
-    int32_t ret = FFA_RET_DENIED;
-    struct domain *d = current->domain;
-    struct ffa_ctx *ctx = d->arch.tee;
-
-    /*
-     * FF-A v1.0 has w5 MBZ while v1.1 allows
-     * FFA_PARTITION_INFO_GET_COUNT_FLAG to be non-zero.
-     *
-     * 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 &&
-         ctx->guest_vers == FFA_VERSION_1_1 )
-        return ffa_partition_info_get(w1, w2, w3, w4, w5, count, fpi_size);
-    if ( w5 )
-        return FFA_RET_INVALID_PARAMETERS;
-
-    if ( !ffa_rx )
-        return FFA_RET_DENIED;
-
-    if ( !spin_trylock(&ctx->rx_lock) )
-        return FFA_RET_BUSY;
-
-    if ( !ctx->page_count || !ctx->rx_is_free )
-        goto out;
-    spin_lock(&ffa_rx_buffer_lock);
-    ret = ffa_partition_info_get(w1, w2, w3, w4, w5, count, fpi_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 )
-    {
-        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;
-        }
-
-        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;
-        }
-    }
-    else
-    {
-        size_t sz = *count * *fpi_size;
-
-        if ( ctx->page_count * FFA_PAGE_SIZE < sz )
-        {
-            ret = FFA_RET_NO_MEMORY;
-            goto out_rx_release;
-        }
-
-        memcpy(ctx->rx, ffa_rx, sz);
-    }
-    ctx->rx_is_free = false;
-out_rx_release:
-    ffa_rx_release();
-out_rx_buf_unlock:
-    spin_unlock(&ffa_rx_buffer_lock);
-out:
-    spin_unlock(&ctx->rx_lock);
-
-    return ret;
-}
-
 static int32_t ffa_handle_rx_release(void)
 {
     int32_t ret = FFA_RET_DENIED;
@@ -604,46 +419,9 @@ static bool ffa_handle_call(struct cpu_user_regs *regs)
     }
 }
 
-static bool is_in_subscr_list(const uint16_t *subscr, uint16_t start,
-                              uint16_t end, uint16_t sp_id)
-{
-    unsigned int n;
-
-    for ( n = start; n < end; n++ )
-    {
-        if ( subscr[n] == sp_id )
-            return true;
-    }
-
-    return false;
-}
-
-static void vm_destroy_bitmap_init(struct ffa_ctx *ctx,
-                                   unsigned int create_signal_count)
-{
-    unsigned int n;
-
-    for ( n = 0; n < subscr_vm_destroyed_count; n++ )
-    {
-        /*
-         * Skip SPs subscribed to the VM created event that never was
-         * notified of the VM creation due to an error during
-         * ffa_domain_init().
-         */
-        if ( is_in_subscr_list(subscr_vm_created, create_signal_count,
-                               subscr_vm_created_count,
-                               subscr_vm_destroyed[n]) )
-            continue;
-
-        set_bit(n, ctx->vm_destroy_bitmap);
-    }
-}
-
 static int ffa_domain_init(struct domain *d)
 {
     struct ffa_ctx *ctx;
-    unsigned int n;
-    int32_t res;
 
     if ( !ffa_version )
         return -ENODEV;
@@ -654,8 +432,7 @@ static int ffa_domain_init(struct domain *d)
     if ( d->domain_id >= UINT16_MAX)
         return -ERANGE;
 
-    ctx = xzalloc_flex_struct(struct ffa_ctx, vm_destroy_bitmap,
-                              BITS_TO_LONGS(subscr_vm_destroyed_count));
+    ctx = xzalloc(struct ffa_ctx);
     if ( !ctx )
         return -ENOMEM;
 
@@ -663,66 +440,28 @@ static int ffa_domain_init(struct domain *d)
     ctx->teardown_d = d;
     INIT_LIST_HEAD(&ctx->shm_list);
 
-    for ( n = 0; n < subscr_vm_created_count; n++ )
-    {
-        res = ffa_direct_req_send_vm(subscr_vm_created[n], ffa_get_vm_id(d),
-                                     FFA_MSG_SEND_VM_CREATED);
-        if ( res )
-        {
-            printk(XENLOG_ERR "ffa: Failed to report creation of vm_id %u to  %u: res %d\n",
-                   ffa_get_vm_id(d), subscr_vm_created[n], res);
-            break;
-        }
-    }
-    vm_destroy_bitmap_init(ctx, n);
-    if ( n != subscr_vm_created_count )
+    /*
+     * ffa_domain_teardown() will be called if ffa_domain_init() returns an
+     * error, so no need for cleanup in this function.
+     */
+
+    if ( !ffa_partinfo_domain_init(d) )
         return -EIO;
 
     return 0;
 }
 
-static void send_vm_destroyed(struct domain *d)
-{
-    struct ffa_ctx *ctx = d->arch.tee;
-    unsigned int n;
-    int32_t res;
-
-    for ( n = 0; n < subscr_vm_destroyed_count; n++ )
-    {
-        if ( !test_bit(n, ctx->vm_destroy_bitmap) )
-            continue;
-
-        res = ffa_direct_req_send_vm(subscr_vm_destroyed[n], ffa_get_vm_id(d),
-                                     FFA_MSG_SEND_VM_DESTROYED);
-
-        if ( res )
-        {
-            printk(XENLOG_ERR "%pd: ffa: Failed to report destruction of vm_id %u to %u: res %d\n",
-                   d, ffa_get_vm_id(d), subscr_vm_destroyed[n], res);
-        }
-
-        /*
-         * For these two error codes the hypervisor is expected to resend
-         * the destruction message. For the rest it is expected that the
-         * error is permanent and that is doesn't help to resend the
-         * destruction message.
-         */
-        if ( res != FFA_RET_INTERRUPTED && res != FFA_RET_RETRY )
-            clear_bit(n, ctx->vm_destroy_bitmap);
-    }
-}
-
 static void ffa_domain_teardown_continue(struct ffa_ctx *ctx, bool first_time)
 {
     struct ffa_ctx *next_ctx = NULL;
     bool retry = false;
 
-    send_vm_destroyed(ctx->teardown_d);
+    if ( !ffa_partinfo_domain_destroy(ctx->teardown_d) )
+        retry = true;
     if ( !ffa_shm_domain_destroy(ctx->teardown_d) )
         retry = true;
 
-    if ( retry ||
-         !bitmap_empty(ctx->vm_destroy_bitmap, subscr_vm_destroyed_count) )
+    if ( retry )
     {
         printk(XENLOG_G_INFO "%pd: ffa: Remaining cleanup, retrying\n", ctx->teardown_d);
 
@@ -796,82 +535,6 @@ static int ffa_relinquish_resources(struct domain *d)
     return 0;
 }
 
-static void uninit_subscribers(void)
-{
-        subscr_vm_created_count = 0;
-        subscr_vm_destroyed_count = 0;
-        XFREE(subscr_vm_created);
-        XFREE(subscr_vm_destroyed);
-}
-
-static bool init_subscribers(struct ffa_partition_info_1_1 *fpi, uint16_t count)
-{
-    uint16_t n;
-    uint16_t c_pos;
-    uint16_t d_pos;
-
-    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 )
-            subscr_vm_created_count++;
-        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
-            subscr_vm_destroyed_count++;
-    }
-
-    if ( subscr_vm_created_count )
-        subscr_vm_created = xzalloc_array(uint16_t, subscr_vm_created_count);
-    if ( subscr_vm_destroyed_count )
-        subscr_vm_destroyed = xzalloc_array(uint16_t,
-                                            subscr_vm_destroyed_count);
-    if ( (subscr_vm_created_count && !subscr_vm_created) ||
-         (subscr_vm_destroyed_count && !subscr_vm_destroyed) )
-    {
-        printk(XENLOG_ERR "ffa: Failed to allocate subscription lists\n");
-        uninit_subscribers();
-        return false;
-    }
-
-    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;
-    }
-
-    return true;
-}
-
-static bool init_sps(void)
-{
-    bool ret = false;
-    uint32_t fpi_size;
-    uint32_t count;
-    int e;
-
-    e = ffa_partition_info_get(0, 0, 0, 0, 0, &count, &fpi_size);
-    if ( e )
-    {
-        printk(XENLOG_ERR "ffa: Failed to get list of SPs: %d\n", e);
-        goto out;
-    }
-
-    if ( count >= UINT16_MAX )
-    {
-        printk(XENLOG_ERR "ffa: Impossible number of SPs: %u\n", count);
-        goto out;
-    }
-
-    ret = init_subscribers(ffa_rx, count);
-
-out:
-    ffa_rx_release();
-
-    return ret;
-}
-
 static bool ffa_probe(void)
 {
     uint32_t vers;
@@ -949,7 +612,7 @@ static bool ffa_probe(void)
     }
     ffa_version = vers;
 
-    if ( !init_sps() )
+    if ( !ffa_partinfo_init() )
         goto err_free_ffa_tx;
 
     INIT_LIST_HEAD(&ffa_teardown_head);
diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinfo.c
new file mode 100644
index 000000000000..dc1059584828
--- /dev/null
+++ b/xen/arch/arm/tee/ffa_partinfo.c
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2024  Linaro Limited
+ */
+
+#include <xen/const.h>
+#include <xen/sizes.h>
+#include <xen/types.h>
+
+#include <asm/smccc.h>
+#include <asm/regs.h>
+
+#include "ffa_private.h"
+
+/* Partition information descriptor defined in FF-A-1.0-REL */
+struct ffa_partition_info_1_0 {
+    uint16_t id;
+    uint16_t execution_context;
+    uint32_t partition_properties;
+};
+
+/* Partition information descriptor defined in FF-A-1.1-REL0 */
+struct ffa_partition_info_1_1 {
+    uint16_t id;
+    uint16_t execution_context;
+    uint32_t partition_properties;
+    uint8_t uuid[16];
+};
+
+/* SPs subscribing to VM_CREATE and VM_DESTROYED events */
+static uint16_t *subscr_vm_created __read_mostly;
+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)
+{
+    const struct arm_smccc_1_2_regs arg = {
+        .a0 = FFA_PARTITION_INFO_GET,
+        .a1 = w1,
+        .a2 = w2,
+        .a3 = w3,
+        .a4 = w4,
+        .a5 = w5,
+    };
+    struct arm_smccc_1_2_regs resp;
+    uint32_t ret;
+
+    arm_smccc_1_2_smc(&arg, &resp);
+
+    ret = ffa_get_ret_code(&resp);
+    if ( !ret )
+    {
+        *count = resp.a2;
+        *fpi_size = resp.a3;
+    }
+
+    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)
+{
+    int32_t ret = FFA_RET_DENIED;
+    struct domain *d = current->domain;
+    struct ffa_ctx *ctx = d->arch.tee;
+
+    /*
+     * FF-A v1.0 has w5 MBZ while v1.1 allows
+     * FFA_PARTITION_INFO_GET_COUNT_FLAG to be non-zero.
+     *
+     * 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 &&
+         ctx->guest_vers == FFA_VERSION_1_1 )
+        return ffa_partition_info_get(w1, w2, w3, w4, w5, count, fpi_size);
+    if ( w5 )
+        return FFA_RET_INVALID_PARAMETERS;
+
+    if ( !ffa_rx )
+        return FFA_RET_DENIED;
+
+    if ( !spin_trylock(&ctx->rx_lock) )
+        return FFA_RET_BUSY;
+
+    if ( !ctx->page_count || !ctx->rx_is_free )
+        goto out;
+    spin_lock(&ffa_rx_buffer_lock);
+    ret = ffa_partition_info_get(w1, w2, w3, w4, w5, count, fpi_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 )
+    {
+        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;
+        }
+
+        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;
+        }
+    }
+    else
+    {
+        size_t sz = *count * *fpi_size;
+
+        if ( ctx->page_count * FFA_PAGE_SIZE < sz )
+        {
+            ret = FFA_RET_NO_MEMORY;
+            goto out_rx_release;
+        }
+
+        memcpy(ctx->rx, ffa_rx, sz);
+    }
+    ctx->rx_is_free = false;
+out_rx_release:
+    ffa_rx_release();
+out_rx_buf_unlock:
+    spin_unlock(&ffa_rx_buffer_lock);
+out:
+    spin_unlock(&ctx->rx_lock);
+
+    return ret;
+}
+
+static int32_t ffa_direct_req_send_vm(uint16_t sp_id, uint16_t vm_id,
+                                      uint8_t msg)
+{
+    uint32_t exp_resp = FFA_MSG_FLAG_FRAMEWORK;
+    unsigned int retry_count = 0;
+    int32_t res;
+
+    if ( msg == FFA_MSG_SEND_VM_CREATED )
+        exp_resp |= FFA_MSG_RESP_VM_CREATED;
+    else if ( msg == FFA_MSG_SEND_VM_DESTROYED )
+        exp_resp |= FFA_MSG_RESP_VM_DESTROYED;
+    else
+        return FFA_RET_INVALID_PARAMETERS;
+
+    do {
+        const struct arm_smccc_1_2_regs arg = {
+            .a0 = FFA_MSG_SEND_DIRECT_REQ_32,
+            .a1 = sp_id,
+            .a2 = FFA_MSG_FLAG_FRAMEWORK | msg,
+            .a5 = vm_id,
+        };
+        struct arm_smccc_1_2_regs resp;
+
+        arm_smccc_1_2_smc(&arg, &resp);
+        if ( resp.a0 != FFA_MSG_SEND_DIRECT_RESP_32 || resp.a2 != exp_resp )
+        {
+            /*
+             * This is an invalid response, likely due to some error in the
+             * implementation of the ABI.
+             */
+            return FFA_RET_INVALID_PARAMETERS;
+        }
+        res = resp.a3;
+        if ( ++retry_count > 10 )
+        {
+            /*
+             * TODO
+             * FFA_RET_INTERRUPTED means that the SPMC has a pending
+             * non-secure interrupt, we need a way of delivering that
+             * non-secure interrupt.
+             * FFA_RET_RETRY is the SP telling us that it's temporarily
+             * blocked from handling the direct request, we need a generic
+             * way to deal with this.
+             * For now in both cases, give up after a few retries.
+             */
+            return res;
+        }
+    } while ( res == FFA_RET_INTERRUPTED || res == FFA_RET_RETRY );
+
+    return res;
+}
+
+static void uninit_subscribers(void)
+{
+        subscr_vm_created_count = 0;
+        subscr_vm_destroyed_count = 0;
+        XFREE(subscr_vm_created);
+        XFREE(subscr_vm_destroyed);
+}
+
+static bool init_subscribers(struct ffa_partition_info_1_1 *fpi, uint16_t count)
+{
+    uint16_t n;
+    uint16_t c_pos;
+    uint16_t d_pos;
+
+    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 )
+            subscr_vm_created_count++;
+        if ( fpi[n].partition_properties & FFA_PART_PROP_NOTIF_DESTROYED )
+            subscr_vm_destroyed_count++;
+    }
+
+    if ( subscr_vm_created_count )
+        subscr_vm_created = xzalloc_array(uint16_t, subscr_vm_created_count);
+    if ( subscr_vm_destroyed_count )
+        subscr_vm_destroyed = xzalloc_array(uint16_t,
+                                            subscr_vm_destroyed_count);
+    if ( (subscr_vm_created_count && !subscr_vm_created) ||
+         (subscr_vm_destroyed_count && !subscr_vm_destroyed) )
+    {
+        printk(XENLOG_ERR "ffa: Failed to allocate subscription lists\n");
+        uninit_subscribers();
+        return false;
+    }
+
+    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;
+    }
+
+    return true;
+}
+
+
+
+bool ffa_partinfo_init(void)
+{
+    bool ret = false;
+    uint32_t fpi_size;
+    uint32_t count;
+    int e;
+
+    e = ffa_partition_info_get(0, 0, 0, 0, 0, &count, &fpi_size);
+    if ( e )
+    {
+        printk(XENLOG_ERR "ffa: Failed to get list of SPs: %d\n", e);
+        goto out;
+    }
+
+    if ( count >= UINT16_MAX )
+    {
+        printk(XENLOG_ERR "ffa: Impossible number of SPs: %u\n", count);
+        goto out;
+    }
+
+    ret = init_subscribers(ffa_rx, count);
+
+out:
+    ffa_rx_release();
+
+    return ret;
+}
+
+static bool is_in_subscr_list(const uint16_t *subscr, uint16_t start,
+                              uint16_t end, uint16_t sp_id)
+{
+    unsigned int n;
+
+    for ( n = start; n < end; n++ )
+    {
+        if ( subscr[n] == sp_id )
+            return true;
+    }
+
+    return false;
+}
+
+static void vm_destroy_bitmap_init(struct ffa_ctx *ctx,
+                                   unsigned int create_signal_count)
+{
+    unsigned int n;
+
+    for ( n = 0; n < subscr_vm_destroyed_count; n++ )
+    {
+        /*
+         * Skip SPs subscribed to the VM created event that never was
+         * notified of the VM creation due to an error during
+         * ffa_domain_init().
+         */
+        if ( is_in_subscr_list(subscr_vm_created, create_signal_count,
+                               subscr_vm_created_count,
+                               subscr_vm_destroyed[n]) )
+            continue;
+
+        set_bit(n, ctx->vm_destroy_bitmap);
+    }
+}
+
+bool ffa_partinfo_domain_init(struct domain *d)
+{
+    unsigned int count = BITS_TO_LONGS(subscr_vm_destroyed_count);
+    struct ffa_ctx *ctx = d->arch.tee;
+    unsigned int n;
+    int32_t res;
+
+    ctx->vm_destroy_bitmap = xzalloc_array(unsigned long, count);
+    if ( !ctx->vm_destroy_bitmap )
+        return false;
+
+    for ( n = 0; n < subscr_vm_created_count; n++ )
+    {
+        res = ffa_direct_req_send_vm(subscr_vm_created[n], ffa_get_vm_id(d),
+                                     FFA_MSG_SEND_VM_CREATED);
+        if ( res )
+        {
+            printk(XENLOG_ERR "ffa: Failed to report creation of vm_id %u to  %u: res %d\n",
+                   ffa_get_vm_id(d), subscr_vm_created[n], res);
+            break;
+        }
+    }
+    vm_destroy_bitmap_init(ctx, n);
+
+    return n == subscr_vm_created_count;
+}
+
+bool ffa_partinfo_domain_destroy(struct domain *d)
+{
+    struct ffa_ctx *ctx = d->arch.tee;
+    unsigned int n;
+    int32_t res;
+
+    if ( !ctx->vm_destroy_bitmap )
+        return true;
+
+    for ( n = 0; n < subscr_vm_destroyed_count; n++ )
+    {
+        if ( !test_bit(n, ctx->vm_destroy_bitmap) )
+            continue;
+
+        res = ffa_direct_req_send_vm(subscr_vm_destroyed[n], ffa_get_vm_id(d),
+                                     FFA_MSG_SEND_VM_DESTROYED);
+
+        if ( res )
+        {
+            printk(XENLOG_ERR "%pd: ffa: Failed to report destruction of vm_id %u to %u: res %d\n",
+                   d, ffa_get_vm_id(d), subscr_vm_destroyed[n], res);
+        }
+
+        /*
+         * For these two error codes the hypervisor is expected to resend
+         * the destruction message. For the rest it is expected that the
+         * error is permanent and that is doesn't help to resend the
+         * destruction message.
+         */
+        if ( res != FFA_RET_INTERRUPTED && res != FFA_RET_RETRY )
+            clear_bit(n, ctx->vm_destroy_bitmap);
+    }
+
+    if ( bitmap_empty(ctx->vm_destroy_bitmap, subscr_vm_destroyed_count) )
+        XFREE(ctx->vm_destroy_bitmap);
+
+    return !ctx->vm_destroy_bitmap;
+}
diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h
index f3e2f42e573e..6b32b69cfe90 100644
--- a/xen/arch/arm/tee/ffa_private.h
+++ b/xen/arch/arm/tee/ffa_private.h
@@ -244,7 +244,7 @@ struct ffa_ctx {
      * Used for ffa_domain_teardown() to keep track of which SPs should be
      * notified that this guest is being destroyed.
      */
-    unsigned long vm_destroy_bitmap[];
+    unsigned long *vm_destroy_bitmap;
 };
 
 extern void *ffa_rx;
@@ -256,6 +256,13 @@ bool ffa_shm_domain_destroy(struct domain *d);
 void ffa_handle_mem_share(struct cpu_user_regs *regs);
 int ffa_handle_mem_reclaim(uint64_t handle, uint32_t flags);
 
+bool ffa_partinfo_init(void);
+bool 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);
+
 
 static inline uint16_t ffa_get_vm_id(const struct domain *d)
 {
@@ -325,4 +332,9 @@ static inline int32_t ffa_simple_call(uint32_t fid, register_t a1,
     return ffa_get_ret_code(&resp);
 }
 
+static inline int32_t ffa_rx_release(void)
+{
+    return ffa_simple_call(FFA_RX_RELEASE, 0, 0, 0, 0);
+}
+
 #endif /*__FFA_PRIVATE_H__*/
-- 
2.34.1



  parent reply	other threads:[~2024-03-25  9:39 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-25  9:38 [XEN PATCH 0/6] FF-A mediator reorganisation Jens Wiklander
2024-03-25  9:38 ` [XEN PATCH 1/6] xen/arm: ffa: rename functions to use ffa_ prefix Jens Wiklander
2024-03-27 13:31   ` Bertrand Marquis
2024-03-25  9:39 ` [XEN PATCH 2/6] xen/arm: ffa: move common things to ffa_private.h Jens Wiklander
2024-03-27 13:32   ` Bertrand Marquis
2024-03-25  9:39 ` [XEN PATCH 3/6] xen/arm: ffa: separate memory sharing routines Jens Wiklander
2024-03-27 13:40   ` Bertrand Marquis
2024-03-28 17:58     ` Julien Grall
2024-04-02  7:25       ` Bertrand Marquis
2024-04-03 23:11       ` Stefano Stabellini
2024-03-25  9:39 ` Jens Wiklander [this message]
2024-03-27 13:42   ` [XEN PATCH 4/6] xen/arm: ffa: separate partition info get routines Bertrand Marquis
2024-03-25  9:39 ` [XEN PATCH 5/6] xen/arm: ffa: separate rxtx buffer routines Jens Wiklander
2024-03-27 13:43   ` Bertrand Marquis
2024-03-25  9:39 ` [XEN PATCH 6/6] xen/arm: ffa: support FFA_FEATURES Jens Wiklander
2024-03-27 13:45   ` Bertrand Marquis
2024-03-27 13:47 ` [XEN PATCH 0/6] FF-A mediator reorganisation Bertrand Marquis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240325093904.3466092-5-jens.wiklander@linaro.org \
    --to=jens.wiklander@linaro.org \
    --cc=bertrand.marquis@arm.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=patches@linaro.org \
    --cc=sstabellini@kernel.org \
    --cc=volodymyr_babchuk@epam.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.