SPM: Add runtime SFN backend

A backend for implementing 'SFN'. This runtime backend is selected
if:
- All partitions included in the current build are 'SFN' partitions.
- Isolation level 1.

The configuration is generated by tooling, and output to the
generated file 'config_impl.h'.

Change-Id: I819c78c7a912f86174d102d389a2714ae17e5062
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/interface/include/config_impl.h.template b/interface/include/config_impl.h.template
index 5af682a..7557d57 100644
--- a/interface/include/config_impl.h.template
+++ b/interface/include/config_impl.h.template
@@ -51,9 +51,14 @@
  * CONFIG_TFM_NS_AGENT_TZ_STK_SIZE_SHIFT_FACTOR for reference, and allow
  * modification of the factor based on application situation. The stack size
  * value is aligned to 8 bytes.
+ * The minimum value is 0x400 to satisfy the SPM functional requirement.
+ * Manifest tool will assure this.
  */
+    {% if total_stk.size|int < 2048 %}
+        {% set total_stk.size = 2048 %}
+    {% endif %}
 #define CONFIG_TFM_NS_AGENT_TZ_STK_SIZE_SHIFT_FACTOR             1
-#define {{"%-56s"|format("CONFIG_TFM_NS_AGENT_TZ_STACK_SIZE")}} \
+#define {{"%-56s"|format("CONFIG_TFM_NS_AGENT_TZ_STACK_SIZE")}}  \
     ((({{"0x%x"|format(total_stk.size)}} >> CONFIG_TFM_NS_AGENT_TZ_STK_SIZE_SHIFT_FACTOR) + 0x7) & (~0x7))
 
 {% elif sfn_partition_num > 0 and ipc_partition_num > 0 %}
diff --git a/interface/include/psa_interface_redirect.h b/interface/include/psa_interface_redirect.h
index 409f49a..9eca26f 100644
--- a/interface/include/psa_interface_redirect.h
+++ b/interface/include/psa_interface_redirect.h
@@ -62,6 +62,23 @@
 #define psa_unmap_outvec         psa_unmap_outvec_thread
 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
 
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+
+#define psa_framework_version    psa_framework_version_sfn
+#define psa_version              psa_version_sfn
+#define psa_connect              psa_connect_sfn
+#define tfm_psa_call_pack        psa_call_pack_sfn
+#define psa_close                psa_close_sfn
+#define psa_wait                 psa_wait_sfn
+#define psa_read                 psa_read_sfn
+#define psa_skip                 psa_skip_sfn
+#define psa_write                psa_write_sfn
+#define psa_panic                psa_panic_sfn
+
+#else
+
+#error "NO ABI is chosen, check configurations."
+
 #endif
 
 #endif /* __PSA_INTERFACE_REDIRECT_H__ */
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 14f6145..aed0f5b 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -101,6 +101,7 @@
 set_source_files_properties(
     ${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_svc.c
     ${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_thread.c
+    ${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
     PROPERTIES
     COMPILE_FLAGS $<$<C_COMPILER_ID:GNU>:-Wno-unused-parameter>
     COMPILE_FLAGS $<$<C_COMPILER_ID:ARMClang>:-Wno-unused-parameter>
@@ -112,6 +113,7 @@
     INTERFACE
         $<$<BOOL:${TFM_PSA_API}>:${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_svc.c>
         $<$<BOOL:${TFM_PSA_API}>:${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_thread.c>
+        $<$<BOOL:${TFM_PSA_API}>:${CMAKE_SOURCE_DIR}/secure_fw/spm/cmsis_psa/psa_interface_sfn.c>
 )
 
 target_compile_definitions(tfm_secure_api
diff --git a/secure_fw/partitions/ns_agent/tfm_psa_api_veneers.c b/secure_fw/partitions/ns_agent/tfm_psa_api_veneers.c
index 1de8b1d..c715516 100644
--- a/secure_fw/partitions/ns_agent/tfm_psa_api_veneers.c
+++ b/secure_fw/partitions/ns_agent/tfm_psa_api_veneers.c
@@ -65,6 +65,11 @@
         "   pop    {r0-r3}                                    \n"
         "   pop    {r2, r3}                                   \n"
         "   mov    lr, r3                                     \n"
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+        "   push   {r4, lr}                                   \n"
+        "   bl     psa_framework_version_sfn                  \n"
+        "   pop    {r3, r4}                                   \n"
+        "   mov    lr, r4                                     \n"
 #else
         "   svc    "M2S(TFM_SVC_PSA_FRAMEWORK_VERSION)"       \n"
 #endif
@@ -102,6 +107,11 @@
         "   pop    {r0-r3}                                    \n"
         "   pop    {r2, r3}                                   \n"
         "   mov    lr, r3                                     \n"
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+        "   push   {r4, lr}                                   \n"
+        "   bl     psa_version_sfn                            \n"
+        "   pop    {r3, r4}                                   \n"
+        "   mov    lr, r4                                     \n"
 #else
         "   svc    "M2S(TFM_SVC_PSA_VERSION)"                 \n"
 #endif
@@ -139,6 +149,11 @@
         "   pop    {r0-r3}                                    \n"
         "   pop    {r2, r3}                                   \n"
         "   mov    lr, r3                                     \n"
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+        "   push   {r4, lr}                                   \n"
+        "   bl     psa_connect_sfn                            \n"
+        "   pop    {r3, r4}                                   \n"
+        "   mov    lr, r4                                     \n"
 #else
         "   svc    "M2S(TFM_SVC_PSA_CONNECT)"                 \n"
 #endif
@@ -181,6 +196,11 @@
         "   pop    {r0-r3}                                    \n"
         "   pop    {r2, r3}                                   \n"
         "   mov    lr, r3                                     \n"
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+        "   push   {r4, lr}                                   \n"
+        "   bl     psa_call_pack_sfn                          \n"
+        "   pop    {r3, r4}                                   \n"
+        "   mov    lr, r4                                     \n"
 #else
         "   svc    "M2S(TFM_SVC_PSA_CALL)"                    \n"
 #endif
@@ -218,6 +238,11 @@
         "   pop    {r0-r3}                                    \n"
         "   pop    {r2, r3}                                   \n"
         "   mov    lr, r3                                     \n"
+#elif defined(CONFIG_TFM_PSA_API_SFN_CALL)
+        "   push   {r4, lr}                                   \n"
+        "   bl     psa_close_sfn                              \n"
+        "   pop    {r3, r4}                                   \n"
+        "   mov    lr, r4                                     \n"
 #else
         "   svc    "M2S(TFM_SVC_PSA_CLOSE)"                   \n"
 #endif
diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
index eccc807..3686ad1 100755
--- a/secure_fw/spm/CMakeLists.txt
+++ b/secure_fw/spm/CMakeLists.txt
@@ -53,7 +53,7 @@
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/spm_thread_call.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/static_load.c>
         $<$<BOOL:${TFM_PSA_API}>:ffm/psa_api.c>
-        $<$<BOOL:${TFM_PSA_API}>:ffm/backend_ipc.c>
+        $<$<BOOL:${TFM_PSA_API}>:ffm/backend.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/tfm_core_svcalls_ipc.c>
         $<$<AND:$<BOOL:${TFM_PSA_API}>,$<NOT:$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>>>:cmsis_psa/tfm_nspm_ipc.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/tfm_pools.c>
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
new file mode 100644
index 0000000..5e566cf
--- /dev/null
+++ b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "current.h"
+#include "tfm_psa_call_pack.h"
+#include "ffm/backend.h"
+#include "ffm/psa_api.h"
+#include "psa/client.h"
+
+#ifdef CONFIG_TFM_PSA_API_SFN_CALL
+
+uint32_t psa_framework_version_sfn(void)
+{
+    return tfm_spm_client_psa_framework_version();
+}
+
+uint32_t psa_version_sfn(uint32_t sid)
+{
+    return tfm_spm_client_psa_version(sid);
+}
+
+psa_handle_t psa_connect_sfn(uint32_t sid, uint32_t version)
+{
+    struct partition_t *p_client, *p_target;
+    psa_status_t stat;
+
+    p_client = GET_CURRENT_COMPONENT();
+
+    stat = tfm_spm_client_psa_connect(sid, version);
+
+    p_target = GET_CURRENT_COMPONENT();
+    if (p_client == p_target) {
+        /* There should be errors if the 'current' is not switched. */
+        TFM_CORE_ASSERT(stat < PSA_SUCCESS);
+
+        return stat;
+    }
+
+    return (psa_handle_t)tfm_spm_partition_psa_reply(
+                                p_target->p_msg->msg.handle, stat);
+}
+
+psa_status_t psa_call_pack_sfn(psa_handle_t handle, uint32_t ctrl_param,
+                               const psa_invec *in_vec, psa_outvec *out_vec)
+{
+    struct partition_t *p_client, *p_target;
+    psa_status_t stat;
+
+    p_client = GET_CURRENT_COMPONENT();
+
+    stat = tfm_spm_client_psa_call(handle, ctrl_param, in_vec, out_vec);
+
+    p_target = GET_CURRENT_COMPONENT();
+    if (p_client == p_target) {
+        /* There should be errors if the 'current' is not switched. */
+        TFM_CORE_ASSERT(stat < PSA_SUCCESS);
+        return stat;
+    }
+
+    return (psa_status_t)tfm_spm_partition_psa_reply(
+                                p_target->p_msg->msg.handle, stat);
+}
+
+void psa_close_sfn(psa_handle_t handle)
+{
+    struct partition_t *p_client, *p_target;
+
+    p_client = GET_CURRENT_COMPONENT();
+
+    tfm_spm_client_psa_close(handle);
+
+    p_target = GET_CURRENT_COMPONENT();
+    if (p_client == p_target) {
+        /* There should be problems if the 'current' is not switched. */
+        return;
+    }
+
+    (void)tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle, PSA_SUCCESS);
+}
+
+psa_signal_t psa_wait_sfn(psa_signal_t signal_mask, uint32_t timeout)
+{
+    /*
+     * TODO:
+     *   Need to trigger scheduler here, when 'psa_wait'
+     *   is needed (interrupt case, e.g.).
+     */
+    return tfm_spm_partition_psa_wait(signal_mask, timeout);
+}
+
+size_t psa_read_sfn(psa_handle_t msg_handle, uint32_t invec_idx,
+                    void *buffer, size_t num_bytes)
+{
+    return tfm_spm_partition_psa_read(msg_handle, invec_idx,
+                                       buffer, num_bytes);
+}
+
+size_t psa_skip_sfn(psa_handle_t msg_handle, uint32_t invec_idx,
+                    size_t num_bytes)
+{
+    return tfm_spm_partition_psa_skip(msg_handle, invec_idx, num_bytes);
+}
+
+void psa_write_sfn(psa_handle_t msg_handle, uint32_t outvec_idx,
+                   const void *buffer, size_t num_bytes)
+{
+    tfm_spm_partition_psa_write(msg_handle, outvec_idx, buffer, num_bytes);
+}
+
+void psa_panic_sfn(void)
+{
+    tfm_spm_partition_psa_panic();
+}
+
+#endif /* CONFIG_TFM_PSA_API_SFN_CALL */
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 8198389..7db60ba 100755
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -9,6 +9,7 @@
 #include <stdbool.h>
 #include "bitops.h"
 #include "critical_section.h"
+#include "current.h"
 #include "fih.h"
 #include "psa/client.h"
 #include "psa/service.h"
@@ -141,7 +142,7 @@
         return NULL;
     }
 
-    p_handle->service = service;
+    p_handle->internal_msg.service = service;
     p_handle->status = TFM_HANDLE_STATUS_IDLE;
     p_handle->client_id = client_id;
 
@@ -310,7 +311,7 @@
 
 struct partition_t *tfm_spm_get_running_partition(void)
 {
-    return GET_THRD_OWNER(CURRENT_THREAD);
+    return GET_CURRENT_COMPONENT();
 }
 
 int32_t tfm_spm_check_client_version(struct service_t *service,
@@ -439,11 +440,12 @@
     TFM_CORE_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
 
     /* Clear message buffer before using it */
-    spm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
+    spm_memset(&msg->msg, 0, sizeof(psa_msg_t));
 
     THRD_SYNC_INIT(&msg->ack_evnt);
     msg->magic = TFM_MSG_MAGIC;
     msg->service = service;
+    msg->p_client = GET_CURRENT_COMPONENT();
     msg->caller_outvec = caller_outvec;
     msg->msg.client_id = client_id;
 
@@ -647,7 +649,6 @@
         }
 #endif /* TFM_FIH_PROFILE_ON */
 
-        /* TODO: Replace this 'BACKEND_IPC' after SFN get involved. */
         backend_instance.comp_init_assuredly(partition, service_setting);
     }
 
@@ -722,8 +723,11 @@
      * FixeMe: abstract these part into dedicated functions to avoid
      * accessing thread context in psa layer
      */
-    /* If it is a NS request via RPC, the owner of this message is not set */
-    if (!is_tfm_rpc_msg(msg)) {
+    /*
+     * If it is a NS request via RPC, the owner of this message is not set.
+     * Or if it is a SFN message, it does not have owner thread state either.
+     */
+    if ((!is_tfm_rpc_msg(msg)) && (msg->sfn_magic != TFM_MSG_MAGIC_SFN)) {
         TFM_CORE_ASSERT(msg->ack_evnt.owner->state == THRD_STATE_BLOCK);
     }
 
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h
index 908ae90..a2edf7b 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.h
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.h
@@ -59,6 +59,7 @@
 #define SPM_INVALID_PARTITION_IDX     (~0U)
 
 #define TFM_MSG_MAGIC                   0x15154343
+#define TFM_MSG_MAGIC_SFN               0x21216565
 
 /* Get partition by thread or context data */
 #define GET_THRD_OWNER(x)        TO_CONTAINER(x, struct partition_t, thrd)
@@ -67,8 +68,12 @@
 /* Message struct to collect parameter from client */
 struct tfm_msg_body_t {
     int32_t magic;
-    struct service_t *service;         /* RoT service pointer            */
-    struct sync_obj_t ack_evnt;        /* Event for ack response         */
+    struct partition_t *p_client;      /* Caller partition              */
+    struct service_t *service;         /* RoT service pointer           */
+    union {
+        struct sync_obj_t ack_evnt;    /* IPC - Ack response event       */
+        uint32_t sfn_magic;            /* SFN - Indicate a SFN message   */
+    };
     psa_msg_t msg;                     /* PSA message body               */
     psa_invec invec[PSA_MAX_IOVEC];    /* Put in/out vectors in msg body */
     psa_outvec outvec[PSA_MAX_IOVEC];
@@ -95,10 +100,16 @@
     void                               *p_boundaries;
     void                               *p_interrupts;
     void                               *p_metadata;
-    struct thread_t                    thrd;
+    union {
+        struct thread_t                thrd;            /* IPC model */
+        uint32_t                       state;           /* SFN model */
+    };
     struct sync_obj_t                  waitobj;
     struct context_ctrl_t              ctx_ctrl;
-    struct bi_list_node_t              msg_list;
+    union {
+        struct bi_list_node_t          msg_list;        /* IPC model */
+        struct tfm_msg_body_t          *p_msg;          /* SFN model */
+    };
     uint32_t                           signals_allowed;
     uint32_t                           signals_waiting;
     uint32_t                           signals_asserted;
@@ -130,7 +141,6 @@
                                          *  - non secure client endpoint id.
                                          */
     struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
-    struct service_t *service;          /* RoT service pointer                */
     struct bi_list_node_t list;         /* list node                          */
 };
 
diff --git a/secure_fw/spm/cmsis_psa/thread.h b/secure_fw/spm/cmsis_psa/thread.h
index ad1aad9..342d538 100644
--- a/secure_fw/spm/cmsis_psa/thread.h
+++ b/secure_fw/spm/cmsis_psa/thread.h
@@ -30,7 +30,7 @@
 #define THRD_ERR_GENERIC          1
 
 /* Thread entry function type */
-typedef void *(*thrd_fn_t)(void *);
+typedef void (*thrd_fn_t)(void *);
 
 /* Thread context */
 struct thread_t {
diff --git a/secure_fw/spm/ffm/backend.c b/secure_fw/spm/ffm/backend.c
new file mode 100644
index 0000000..9df5de7
--- /dev/null
+++ b/secure_fw/spm/ffm/backend.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "config_impl.h"
+
+#if CONFIG_TFM_SPM_BACKEND_SFN == 1
+#include "backend_sfn.c"
+#elif CONFIG_TFM_SPM_BACKEND_IPC == 1
+#include "backend_ipc.c"
+#else
+#error "Invalid configuration."
+#endif
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index ee1a4c2..c544f73 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -41,7 +41,7 @@
 
 /*
  * Send message and wake up the SP who is waiting on message queue, block the
- * current thread and triggere scheduler.
+ * current thread and trigger scheduler.
  */
 static psa_status_t ipc_messaging(struct service_t *service,
                                   struct tfm_msg_body_t *msg)
@@ -80,13 +80,20 @@
     return PSA_SUCCESS;
 }
 
-static void ipc_replying(struct tfm_msg_body_t *p_msg, psa_status_t status)
+static int32_t ipc_replying(struct tfm_msg_body_t *p_msg, int32_t status)
 {
     if (is_tfm_rpc_msg(p_msg)) {
         tfm_rpc_client_call_reply(p_msg, status);
     } else {
         thrd_wake_up(&p_msg->ack_evnt, status);
     }
+
+    /*
+     * 'psa_reply' exists in IPC model only and returns 'void'. Return
+     * 'PSA_SUCCESS' here always since SPM does not forward the status
+     * to the caller.
+     */
+    return PSA_SUCCESS;
 }
 
 /* Parameters are treated as assuredly */
diff --git a/secure_fw/spm/ffm/backend_sfn.c b/secure_fw/spm/ffm/backend_sfn.c
new file mode 100644
index 0000000..14736e9
--- /dev/null
+++ b/secure_fw/spm/ffm/backend_sfn.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "compiler_ext_defs.h"
+#include "current.h"
+#include "tfm_spm_hal.h"
+#include "ffm/backend.h"
+#include "load/partition_defs.h"
+#include "load/service_defs.h"
+#include "load/spm_load_api.h"
+#include "psa/error.h"
+#include "psa/service.h"
+#include "spm_ipc.h"
+
+/* SFN Partition state */
+#define SFN_PARTITION_STATE_NOT_INITED        0
+#define SFN_PARTITION_STATE_INITED            1
+
+typedef psa_status_t (*service_fn_t)(psa_msg_t *msg);
+typedef psa_status_t (*sfn_init_fn_t)(void);
+
+/* Declare the global component list */
+struct partition_head_t partition_listhead;
+
+/* TODO: To be checked with the RPC design. */
+static uintptr_t spm_stack_limit;
+static uintptr_t spm_stack_base;
+
+/*
+ * Send message and wake up the SP who is waiting on message queue, block the
+ * current component state and activate the next component.
+ */
+static psa_status_t sfn_messaging(struct service_t *service,
+                                  struct tfm_msg_body_t *msg)
+{
+    struct partition_t *p_target;
+    psa_status_t status;
+
+    if (!msg || !service || !service->p_ldinf || !service->partition) {
+        tfm_core_panic();
+    }
+
+    msg->sfn_magic = TFM_MSG_MAGIC_SFN;
+    p_target = service->partition;
+    p_target->p_msg = msg;
+
+    SET_CURRENT_COMPONENT(p_target);
+
+    if (p_target->state == SFN_PARTITION_STATE_NOT_INITED) {
+        if (p_target->p_ldinf->entry != 0) {
+            status = ((sfn_init_fn_t)p_target->p_ldinf->entry)();
+            /* Negative value indicates errors. */
+            if (status < PSA_SUCCESS) {
+                tfm_core_panic();
+            }
+        }
+        p_target->state = SFN_PARTITION_STATE_INITED;
+    }
+
+    status = ((service_fn_t)service->p_ldinf->sfn)(&msg->msg);
+
+    return status;
+}
+
+static int32_t sfn_replying(struct tfm_msg_body_t *p_msg, int32_t status)
+{
+    SET_CURRENT_COMPONENT(p_msg->p_client);
+
+    /*
+     * Returning a value here is necessary, because 'psa_reply' is absent
+     * for SFN clients, the 'reply' method is performed by SPM internally
+     * when SFN case, to forward the 'status' to the caller.
+     *
+     * For example:
+     *   'status' MAY contain a 'psa_handle_t' returned by SPM 'connect' and
+     *   SPM needs to 'reply' it back to the caller. Treat 'psa_handle_t' value
+     *   as SPM specific return value and represnent it as 'psa_status_t'.
+     */
+    return status;
+}
+
+/* Parameters are treated as assuredly */
+void sfn_comp_init_assuredly(struct partition_t *p_pt, uint32_t service_set)
+{
+    const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
+
+    p_pt->p_msg = NULL;
+    p_pt->state = SFN_PARTITION_STATE_NOT_INITED;
+
+    THRD_SYNC_INIT(&p_pt->waitobj);
+
+    /*
+     * Built-in partitions still have thread instances: NS Agent (TZ) and
+     * IDLE partition, and NS Agent (TZ) needs to be specific cared here.
+     */
+    if (p_pldi->flags & PARTITION_MODEL_IPC) {
+        THRD_INIT(&p_pt->thrd, &p_pt->ctx_ctrl,
+                  TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_pldi->flags)));
+
+        thrd_start(&p_pt->thrd,
+               POSITION_TO_ENTRY(p_pldi->entry, thrd_fn_t),
+               (void *)tfm_spm_hal_get_ns_entry_point(),
+               LOAD_ALLOCED_STACK_ADDR(p_pldi),
+               LOAD_ALLOCED_STACK_ADDR(p_pldi) + p_pldi->stack_size);
+
+        /* SPM reuses the ns agent stack, use once only at initialization. */
+        if (p_pldi->pid == TFM_SP_NON_SECURE_ID) {
+            spm_stack_limit = p_pt->ctx_ctrl.sp_limit;
+            spm_stack_base = p_pt->ctx_ctrl.sp;
+        }
+    }
+
+    (void)service_set;
+}
+
+static void spm_thread_fn(void *p)
+{
+    struct partition_t *p_part, *p_curr;
+
+    p_curr = GET_CURRENT_COMPONENT();
+    /* Call partition initialization routine one by one. */
+    UNI_LIST_FOR_EACH(p_part, PARTITION_LIST_ADDR) {
+        if (p_part->p_ldinf->flags & PARTITION_MODEL_IPC) {
+            continue;
+        }
+
+        if (p_part->state == SFN_PARTITION_STATE_INITED) {
+            continue;
+        }
+
+        SET_CURRENT_COMPONENT(p_part);
+
+        if (p_part->p_ldinf->entry != 0) {
+            if (((sfn_init_fn_t)p_part->p_ldinf->entry)() < PSA_SUCCESS) {
+                tfm_core_panic();
+            }
+        }
+
+        p_part->state = SFN_PARTITION_STATE_INITED;
+    }
+
+    SET_CURRENT_COMPONENT(p_curr);
+
+    thrd_set_state(CURRENT_THREAD, THRD_STATE_DETACH);
+
+    tfm_arch_trigger_pendsv();
+}
+
+uint32_t sfn_system_run(void)
+{
+    struct thread_t *p_thrd = (struct thread_t *)spm_stack_limit;
+    struct context_ctrl_t *p_ctxctrl = (struct context_ctrl_t *)(p_thrd + 1);
+    uintptr_t sp_limit = (((uintptr_t)(p_ctxctrl + 1)) + 7) & ~0x7;
+    uintptr_t sp_base = spm_stack_base;
+
+    THRD_INIT(p_thrd, p_ctxctrl, THRD_PRIOR_HIGHEST);
+    thrd_start(p_thrd, spm_thread_fn, NULL, sp_limit, sp_base);
+
+    return thrd_start_scheduler(&CURRENT_THREAD);
+}
+
+const struct backend_ops_t backend_instance = {
+    .comp_init_assuredly = sfn_comp_init_assuredly,
+    .system_run          = sfn_system_run,
+    .messaging           = sfn_messaging,
+    .replying            = sfn_replying
+};
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index af35a2d..561f9ef 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -16,6 +16,7 @@
 #include "load/partition_defs.h"
 #include "load/service_defs.h"
 #include "load/interrupt_defs.h"
+#include "ffm/psa_api.h"
 #include "utilities.h"
 #include "ffm/backend.h"
 #include "ffm/psa_api.h"
@@ -287,7 +288,7 @@
             return PSA_ERROR_PROGRAMMER_ERROR;
         }
 
-        service = conn_handle->service;
+        service = conn_handle->internal_msg.service;
     }
 
     if (!service) {
@@ -407,7 +408,7 @@
         TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
     }
 
-    service = conn_handle->service;
+    service = conn_handle->internal_msg.service;
     if (!service) {
         /* FixMe: Need to implement one mechanism to resolve this failure. */
         tfm_core_panic();
@@ -469,8 +470,7 @@
     if (timeout == PSA_BLOCK &&
         (partition->signals_asserted & signal_mask) == 0) {
         partition->signals_waiting = signal_mask;
-        thrd_wait_on(&partition->waitobj,
-                     &(tfm_spm_get_running_partition()->thrd));
+        thrd_wait_on(&partition->waitobj, CURRENT_THREAD);
     }
 
     return partition->signals_asserted & signal_mask;
@@ -765,7 +765,8 @@
     msg->outvec[outvec_idx].len += num_bytes;
 }
 
-void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status)
+int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
+                                    psa_status_t status)
 {
     struct service_t *service = NULL;
     struct tfm_msg_body_t *msg = NULL;
@@ -878,7 +879,7 @@
         conn_handle->status = TFM_HANDLE_STATUS_IDLE;
     }
 
-    backend_instance.replying(msg, ret);
+    return backend_instance.replying(msg, ret);
 }
 
 void tfm_spm_partition_psa_notify(int32_t partition_id)
@@ -930,7 +931,7 @@
 
     if (irq_info->flih_func) {
         /* This API is for SLIH IRQs only */
-        psa_panic();
+        tfm_core_panic();
     }
 
     /* It is a fatal error if passed signal is not currently asserted */
diff --git a/secure_fw/spm/include/current.h b/secure_fw/spm/include/current.h
new file mode 100644
index 0000000..e69473d
--- /dev/null
+++ b/secure_fw/spm/include/current.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __CURRENT_H__
+#define __CURRENT_H__
+
+#include "thread.h"
+#include "spm_ipc.h"
+
+/* Get current component */
+#define GET_CURRENT_COMPONENT()  GET_CTX_OWNER(CURRENT_THREAD->p_context_ctrl)
+/* Set current component */
+#define SET_CURRENT_COMPONENT(p) THRD_UPDATE_CUR_CTXCTRL(&(p)->ctx_ctrl)
+
+#endif /* __CURRENT_H__ */
diff --git a/secure_fw/spm/include/ffm/backend.h b/secure_fw/spm/include/ffm/backend.h
index 7b7ea00..5efeac0 100644
--- a/secure_fw/spm/include/ffm/backend.h
+++ b/secure_fw/spm/include/ffm/backend.h
@@ -37,9 +37,9 @@
 
     /*
      * Runtime model-specific message replying.
-     * Return the acked status.
+     * Return the connection handle or the acked status code.
      */
-    void (*replying)(struct tfm_msg_body_t *p_msg, psa_status_t status);
+    int32_t (*replying)(struct tfm_msg_body_t *p_msg, int32_t status);
 };
 
 /* RUNTIME MODEL BACKENDS DECLARATION */
diff --git a/secure_fw/spm/include/ffm/psa_api.h b/secure_fw/spm/include/ffm/psa_api.h
index 6ea3c46..1c78e46 100644
--- a/secure_fw/spm/include/ffm/psa_api.h
+++ b/secure_fw/spm/include/ffm/psa_api.h
@@ -247,14 +247,16 @@
  * \param[in] status            Message result value to be reported to the
  *                              client.
  *
- * \retval void                 Success.
+ * \retval Positive integer     Success, the connection handle.
+ * \retval PSA_SUCCESS          Success
  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
  *                              following are true:
  * \arg                         msg_handle is invalid.
  * \arg                         An invalid status code is specified for the
  *                              type of message.
  */
-void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status);
+int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
+                                    psa_status_t status);
 
 /**
  * \brief Function body of \ref psa_norify.
diff --git a/tools/templates/partition_load_info.template b/tools/templates/partition_load_info.template
index ff7d44f..a4a9fae 100644
--- a/tools/templates/partition_load_info.template
+++ b/tools/templates/partition_load_info.template
@@ -124,7 +124,7 @@
 {% elif manifest.entry_init %}
         .entry                      = ENTRY_TO_POSITION({{manifest.entry_init}}),
 {% else %}
-        .entry                      = NULL,
+        .entry                      = 0,
 {% endif %}
         .stack_size                 = {{manifest.stack_size}},
         .heap_size                  = 0,