Core: Update IPC implementation framework

Initial IPC patches showcases API usage with a rough design. To follow
PSA FF specification, an updated framework needs to take place instead
of previous design.
The modification details are:
- Remove legacy version files which unused anymore: psa_api.c,
  tfm_queue.c, tfm_queue.h, tfm_thread.c and tfm_thread.h.
- Add psa client and service implement on secure side in thread mode.
- Add syscalls for psa client and service, empty now and to be
  implemented.
- Those files in 'core' folder which needed by ipc will be added in
  'ipc' folder. So there is no ipc file to be built in 'library' mode.

Change-Id: I5ab5ea2774dfb70b24f4bfd0499129ae48b2b3de
Signed-off-by: Edison Ai <edison.ai@arm.com>
Co-authored-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 3154027..1f99ad1 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+# Copyright (c) 2017-2018, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -28,11 +28,12 @@
 endif()
 
 include(${SECURE_FW_DIR}/spm/CMakeLists.inc)
-include(${SECURE_FW_DIR}/core/CMakeLists.inc)
 include(${SECURE_FW_DIR}/ns_callable/CMakeLists.inc)
-# Involve IPC sources only PSA APIs are there
+#Involve all IPC related sources in ipc's CMakeLists.inc, and switch core between IPC and Library.
 if(TFM_PSA_API)
 	include(${SECURE_FW_DIR}/core/ipc/CMakeLists.inc)
+else()
+	include(${SECURE_FW_DIR}/core/CMakeLists.inc)
 endif()
 
 set(BUILD_CMSIS_CORE On)
diff --git a/secure_fw/core/CMakeLists.inc b/secure_fw/core/CMakeLists.inc
index 31216d1..0b290d5 100644
--- a/secure_fw/core/CMakeLists.inc
+++ b/secure_fw/core/CMakeLists.inc
@@ -39,12 +39,6 @@
 		"${SS_CORE_DIR}/tfm_boot_data.c"
 	)
 
-if (NOT DEFINED TFM_PSA_API)
-	message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ")
-elseif (TFM_PSA_API)
-	list(APPEND SS_CORE_C_SRC "${SS_CORE_DIR}/tfm_psa_api_client.c")
-endif()
-
 #Append all our source files to global lists.
 list(APPEND ALL_SRC_C ${SS_CORE_C_SRC})
 unset(SS_CORE_C_SRC)
diff --git a/secure_fw/core/ipc/CMakeLists.inc b/secure_fw/core/ipc/CMakeLists.inc
index 4753fdb..87437ae 100644
--- a/secure_fw/core/ipc/CMakeLists.inc
+++ b/secure_fw/core/ipc/CMakeLists.inc
@@ -33,9 +33,16 @@
 if (NOT DEFINED TFM_PSA_API)
 	message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ")
 elseif (TFM_PSA_API)
-	set (SS_IPC_C_SRC "${SS_IPC_DIR}/tfm_thread.c"
-			"${SS_IPC_DIR}/tfm_queue.c"
-			"${SS_IPC_DIR}/psa_api.c"
+	set (SS_IPC_C_SRC "${SS_IPC_DIR}/tfm_svcalls.c"
+			"${SS_IPC_DIR}/psa_service.c"
+			"${SS_IPC_DIR}/psa_client.c"
+			"${SS_IPC_DIR}/../tfm_core.c"
+			"${SS_IPC_DIR}/../tfm_secure_api.c"
+			"${SS_IPC_DIR}/../tfm_spm_services.c"
+			"${SS_IPC_DIR}/../tfm_handler.c"
+			"${SS_IPC_DIR}/../tfm_psa_api_client.c"
+			"${SS_IPC_DIR}/../tfm_nspm.c"
+			"${SS_IPC_DIR}/../tfm_boot_data.c"
 			)
 endif()
 
@@ -49,6 +56,7 @@
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE)
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE)
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc/include ABSOLUTE)
 
 if(NOT DEFINED PLATFORM_CMAKE_FILE)
 	message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.")
diff --git a/secure_fw/core/ipc/include/tfm_svcalls.h b/secure_fw/core/ipc/include/tfm_svcalls.h
new file mode 100644
index 0000000..c64ce74
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_svcalls.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_SVCALLS_H__
+#define __TFM_SVCALLS_H__
+
+/* Svcall for PSA Client APIs */
+
+/**
+ * \brief SVC handler for \ref psa_framework_version.
+ *
+ * \return version              The version of the PSA Framework implementation
+ *                              that is providing the runtime services to the
+ *                              caller.
+ */
+uint32_t tfm_svcall_psa_framework_version(void);
+
+/**
+ * \brief SVC handler for \ref psa_version.
+ *
+ * \param[in] args              Include all input arguments: sid.
+ * \param[in] ns_caller         If 'non-zero', call from non-secure client.
+ *                              Or from secure client.
+ *
+ * \retval PSA_VERSION_NONE     The RoT Service is not implemented, or the
+ *                              caller is not permitted to access the service.
+ * \retval > 0                  The minor version of the implemented RoT
+ *                              Service.
+ */
+uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for \ref psa_connect.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              sid, minor_version.
+ * \param[in] ns_caller         If 'non-zero', call from non-secure client.
+ *                              Or from secure client.
+ *
+ * \retval > 0                  A handle for the connection.
+ * \retval PSA_CONNECTION_REFUSED The SPM or RoT Service has refused the
+ *                              connection.
+ * \retval PSA_CONNECTION_BUSY  The SPM or RoT Service cannot make the
+ *                              connection at the moment.
+ * \retval "Does not return"    The RoT Service ID and version are not
+ *                              supported, or the caller is not permitted to
+ *                              access the service.
+ */
+psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for \ref psa_call.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              handle, in_vec, in_len, out_vec, out_len.
+ * \param[in] ns_caller         If 'non-zero', call from non-secure client.
+ *                              Or from secure client.
+ *
+ * \retval >=0                  RoT Service-specific status value.
+ * \retval <0                   RoT Service-specific error code.
+ * \retval PSA_DROP_CONNECTION  The connection has been dropped by the RoT
+ *                              Service. This indicates that either this or
+ *                              a previous message was invalid.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           An invalid handle was passed.
+ * \arg                           The connection is already handling a request.
+ * \arg                           An invalid memory reference was provided.
+ * \arg                           in_len + out_len > PSA_MAX_IOVEC.
+ * \arg                           The message is unrecognized by the RoT
+ *                                Service or incorrectly formatted.
+ */
+psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for \ref psa_close.
+ *
+ * \param[in] args              Include all input arguments: handle.
+ * \param[in] ns_caller         If 'non-zero', call from non-secure client.
+ *                              Or from secure client.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           An invalid handle was provided that is not
+ *                                the null handle.
+ * \arg                           The connection is handling a request.
+ */
+void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for IPC functions
+ *
+ * \param[in] svc_num           SVC number
+ * \param[in] ctx               Argument context
+ *
+ * \returns                     Return values from those who has,
+ *                              or PSA_SUCCESS.
+ */
+int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx);
+
+#endif
diff --git a/secure_fw/core/ipc/psa_api.c b/secure_fw/core/ipc/psa_api.c
deleted file mode 100644
index 5c5f593..0000000
--- a/secure_fw/core/ipc/psa_api.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-#include <inttypes.h>
-#include <stdio.h>
-#include "psa_client.h"
-#include "psa_service.h"
-#include "tfm_thread.h"
-#include "tfm_queue.h"
-#include "secure_utilities.h"
-
-/* Service APIs */
-
-/* FixMe: Initial prototype. */
-psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
-{
-    uint32_t msg_signals = 0;
-
-    while (1) {
-        msg_signals = tfm_queue_get_msg_signal();
-
-        if (msg_signals == 0 && timeout == PSA_BLOCK) {
-            tfm_thread_schedule();
-        } else {
-            break;
-        }
-    }
-    return msg_signals;
-}
-
-psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
-{
-    if (msg) {
-        tfm_queue_get_msg_body(msg);
-    }
-    return PSA_SUCCESS;
-}
-
-void psa_reply(psa_handle_t msg_handle, psa_status_t status)
-{
-    struct tfm_msg_queue_item *q_msg = (struct tfm_msg_queue_item *)msg_handle;
-
-    q_msg->msg.handle = (psa_handle_t)0;
-}
-
-size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
-                    void *buffer, size_t num_bytes)
-{
-    size_t bytes;
-    struct tfm_msg_queue_item *q_msg = (struct tfm_msg_queue_item *)msg_handle;
-
-    if (invec_idx >= PSA_MAX_IOVEC) {
-        return 0;
-    }
-
-    bytes = num_bytes > q_msg->invec[invec_idx].len ?
-                        q_msg->invec[invec_idx].len : num_bytes;
-
-    memcpy_m(buffer, q_msg->invec[invec_idx].base, bytes);
-
-    return bytes;
-}
-
-void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
-                    const void *buffer, size_t num_bytes)
-{
-    size_t bytes;
-    struct tfm_msg_queue_item *q_msg = (struct tfm_msg_queue_item *)msg_handle;
-
-    if (outvec_idx >= PSA_MAX_IOVEC) {
-        return;
-    }
-
-    bytes = num_bytes > q_msg->outvec[outvec_idx].len ?
-                        q_msg->outvec[outvec_idx].len : num_bytes;
-
-    memcpy_m(q_msg->outvec[outvec_idx].base, (void *)buffer, bytes);
-}
diff --git a/secure_fw/core/ipc/psa_client.c b/secure_fw/core/ipc/psa_client.c
new file mode 100644
index 0000000..f8fe605
--- /dev/null
+++ b/secure_fw/core/ipc/psa_client.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_svc.h"
+#include "psa_client.h"
+
+__attribute__((naked))
+uint32_t psa_framework_version(void)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION));
+}
+
+__attribute__((naked))
+uint32_t psa_version(uint32_t sid)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_VERSION));
+}
+
+__attribute__((naked))
+psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_CONNECT));
+}
+
+__attribute__((naked))
+psa_status_t psa_call(psa_handle_t handle,
+                      const psa_invec *in_vec,
+                      size_t in_len,
+                      psa_outvec *out_vec,
+                      size_t out_len)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_CALL));
+}
+
+__attribute__((naked))
+void psa_close(psa_handle_t handle)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_CLOSE));
+}
diff --git a/secure_fw/core/ipc/psa_service.c b/secure_fw/core/ipc/psa_service.c
new file mode 100644
index 0000000..4871971
--- /dev/null
+++ b/secure_fw/core/ipc/psa_service.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_svc.h"
+#include "psa_client.h"
+#include "psa_service.h"
+
+__attribute__((naked))
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
+
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_WAIT));
+}
+
+__attribute__((naked))
+psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_GET));
+}
+
+__attribute__((naked))
+void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_SET_RHANDLE));
+}
+
+__attribute__((naked))
+size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
+                void *buffer, size_t num_bytes)
+
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_READ));
+}
+
+__attribute__((naked))
+size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_SKIP));
+}
+
+__attribute__((naked))
+void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
+               const void *buffer, size_t num_bytes)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_WRITE));
+}
+
+__attribute__((naked))
+void psa_reply(psa_handle_t msg_handle, psa_status_t retval)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_REPLY));
+}
+
+__attribute__((naked))
+void psa_notify(int32_t partition_id)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_NOTIFY));
+}
+
+__attribute__((naked))
+void psa_clear(void)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_CLEAR));
+}
+
+__attribute__((naked))
+void psa_eoi(psa_signal_t irq_signal)
+{
+    __ASM("SVC %0           \n"
+          "BX LR            \n"
+          : : "I" (TFM_SVC_PSA_EOI));
+}
diff --git a/secure_fw/core/ipc/tfm_queue.c b/secure_fw/core/ipc/tfm_queue.c
deleted file mode 100644
index 7143801..0000000
--- a/secure_fw/core/ipc/tfm_queue.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-#include <inttypes.h>
-#include <stdio.h>
-#include "psa_client.h"
-#include "psa_service.h"
-#include "tfm_queue.h"
-#include "secure_utilities.h"
-
-/*
- * Message queue
- */
-static struct tfm_msg_queue_item msg_queue[TFM_MSG_QUEUE_DEPTH];
-static struct tfm_msg_queue_item *q_used, *q_avail;
-
-#define QUEUE_EMPTY() (q_used->msg.handle == (psa_handle_t)0)
-#define QUEUE_FULL() (q_avail->msg.handle != (psa_handle_t)0)
-
-void tfm_queue_init(void)
-{
-    struct tfm_msg_queue_item *p_item = msg_queue;
-    uint32_t i;
-
-    for (i = 0; i < TFM_MSG_QUEUE_DEPTH; i++) {
-        p_item[i].msg.handle = (psa_handle_t)0;
-        p_item[i].next = &p_item[(i + 1) % TFM_MSG_QUEUE_DEPTH];
-        p_item[i].prev = &p_item[(i + TFM_MSG_QUEUE_DEPTH - 1) %
-                                 TFM_MSG_QUEUE_DEPTH];
-    }
-
-    q_used = p_item;
-    q_avail = p_item;
-}
-
-uint32_t tfm_queue_get_msg_signal(void)
-{
-    if (QUEUE_EMPTY()) {
-        return 0;
-    }
-
-    return q_used->signal;
-}
-
-psa_status_t tfm_queue_put_msg(psa_signal_t signal, uint32_t type,
-                               psa_invec *invec, size_t in_len,
-                               psa_outvec *outvec, size_t out_len)
-{
-    uint32_t i;
-
-    /* FixMe: need to be clarified */
-    if (QUEUE_FULL()) {
-        return TFM_QUEUE_ERROR_GENERIC;
-    }
-
-    if ((!invec && in_len != 0) || (!outvec && out_len != 0)) {
-        ERROR_MSG("parameters error.\r\n");
-        return TFM_QUEUE_ERROR_GENERIC;
-    }
-
-    /* copy contents */
-    q_avail->signal = signal;
-
-    q_avail->msg.type = type;
-
-    q_avail->invec = invec;
-    q_avail->outvec = outvec;
-
-    for (i = 0; i < in_len; i++) {
-        q_avail->msg.in_size[i] = invec[i].len;
-    }
-
-    for (i = 0; i < out_len; i++) {
-        q_avail->msg.out_size[i] = outvec[i].len;
-    }
-
-    q_avail->msg.handle = (psa_handle_t)q_avail;
-
-    q_avail = q_avail->next;
-
-    return TFM_QUEUE_SUCCESS;
-}
-
-/* Utils */
-void *memcpy_m(void *dst, const void *src, uint32_t size)
-{
-    uint8_t *dst_8 = (uint8_t *)dst;
-    uint8_t *src_8 = (uint8_t *)src;
-
-    while (size--) {
-        *dst_8++ = *src_8++;
-    }
-
-    return dst;
-}
-
-void tfm_queue_get_msg_body(psa_msg_t *msg)
-{
-    memcpy_m(msg, &q_used->msg, sizeof(*msg));
-    q_used = q_used->next;
-}
diff --git a/secure_fw/core/ipc/tfm_queue.h b/secure_fw/core/ipc/tfm_queue.h
deleted file mode 100644
index afa530d..0000000
--- a/secure_fw/core/ipc/tfm_queue.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-#ifndef __TFM_QUEUE_H__
-#define __TFM_QUEUE_H__
-
-#define TFM_MSG_QUEUE_DEPTH    5
-
-struct tfm_msg_queue_item {
-    psa_msg_t msg;
-    uint32_t signal;
-    /* Put in/out vectors in msg body */
-    psa_invec *invec;
-    psa_outvec *outvec;
-    /* List opearators */
-    struct tfm_msg_queue_item *prev;
-    struct tfm_msg_queue_item *next;
-};
-
-/* internal error codes */
-#define TFM_QUEUE_SUCCESS           0
-#define TFM_QUEUE_ERROR_GENERIC     (INT32_MIN)
-
-void tfm_queue_init(void);
-uint32_t tfm_queue_get_msg_signal(void);
-psa_status_t tfm_queue_put_msg(psa_signal_t signal, uint32_t type,
-                               psa_invec *invec, size_t in_len,
-                               psa_outvec *outvec, size_t out_len);
-void tfm_queue_get_msg_body(psa_msg_t *msg);
-void *memcpy_m(void *dst, const void *src, uint32_t size);
-
-#endif
diff --git a/secure_fw/core/ipc/tfm_svcalls.c b/secure_fw/core/ipc/tfm_svcalls.c
new file mode 100644
index 0000000..9f46cc0
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_svcalls.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_svc.h"
+#include "tfm_svcalls.h"
+
+/************************* SVC handler for PSA Client APIs *******************/
+
+uint32_t tfm_svcall_psa_framework_version(void)
+{
+    return PSA_FRAMEWORK_VERSION;
+}
+
+uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller)
+{
+    return PSA_VERSION_NONE;
+}
+
+psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller)
+{
+    return PSA_NULL_HANDLE;
+}
+
+psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller)
+{
+    return PSA_SUCCESS;
+}
+
+void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller)
+{
+}
+
+/*********************** SVC handler for PSA Service APIs ********************/
+
+/**
+ * \brief SVC handler for \ref psa_wait.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              signal_mask, timeout.
+ *
+ * \retval >0                   At least one signal is asserted.
+ * \retval 0                    No signals are asserted. This is only seen when
+ *                              a polling timeout is used.
+ */
+static psa_signal_t tfm_svcall_psa_wait(uint32_t *args)
+{
+    return 0;
+}
+
+/**
+ * \brief SVC handler for \ref psa_get.
+ *
+ * \param[in] args              Include all input arguments: signal, msg.
+ *
+ * \retval PSA_SUCCESS          Success, *msg will contain the delivered
+ *                              message.
+ * \retval PSA_ERR_NOMSG        Message could not be delivered.
+ * \retval "Does not return"    The call is invalid because one or more of the
+ *                              following are true:
+ * \arg                           signal has more than a single bit set.
+ * \arg                           signal does not correspond to a RoT Service.
+ * \arg                           The RoT Service signal is not currently
+ *                                asserted.
+ * \arg                           The msg pointer provided is not a valid memory
+ *                                reference.
+ */
+static psa_status_t tfm_svcall_psa_get(uint32_t *args)
+{
+    return PSA_SUCCESS;
+}
+
+/**
+ * \brief SVC handler for \ref psa_set_rhandle.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              msg_handle, rhandle.
+ *
+ * \retval void                 Success, rhandle will be provided with all
+ *                              subsequent messages delivered on this
+ *                              connection.
+ * \retval "Does not return"    msg_handle is invalid.
+ */
+static void tfm_svcall_psa_set_rhandle(uint32_t *args)
+{
+}
+
+/**
+ * \brief SVC handler for \ref psa_read.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              msg_handle, invec_idx, buffer, num_bytes.
+ *
+ * \retval >0                   Number of bytes copied.
+ * \retval 0                    There was no remaining data in this input
+ *                              vector.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           invec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ * \arg                           the memory reference for buffer is invalid or
+ *                                not writable.
+ */
+static size_t tfm_svcall_psa_read(uint32_t *args)
+{
+    return 0;
+}
+
+/**
+ * \brief SVC handler for \ref psa_skip.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              msg_handle, invec_idx, num_bytes.
+ *
+ * \retval >0                   Number of bytes skipped.
+ * \retval 0                    There was no remaining data in this input
+ *                              vector.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           invec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ */
+static size_t tfm_svcall_psa_skip(uint32_t *args)
+{
+    return 0;
+}
+
+/**
+ * \brief SVC handler for \ref psa_write.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              msg_handle, outvec_idx, buffer, num_bytes.
+ *
+ * \retval void                 Success
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           outvec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ * \arg                           The memory reference for buffer is invalid.
+ * \arg                           The call attempts to write data past the end
+ *                                of the client output vector.
+ */
+static void tfm_svcall_psa_write(uint32_t *args)
+{
+}
+
+/**
+ * \brief SVC handler for \ref psa_reply.
+ *
+ * \param[in] args              Include all input arguments:
+ *                              msg_handle, status.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    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.
+ */
+static void tfm_svcall_psa_reply(uint32_t *args)
+{
+}
+
+/**
+ * \brief SVC handler for \ref psa_notify.
+ *
+ * \param[in] args              Include all input arguments: partition_id.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    partition_id does not correspond to a Secure
+ *                              Partition.
+ */
+static void tfm_svcall_psa_notify(uint32_t *args)
+{
+}
+
+/**
+ * \brief SVC handler for \ref psa_clear.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The Secure Partition's doorbell signal is not
+ *                              currently asserted.
+ */
+static void tfm_svcall_psa_clear(uint32_t *args)
+{
+}
+
+/**
+ * \brief SVC handler for \ref psa_eoi.
+ *
+ * \param[in] args              Include all input arguments: irq_signal.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           irq_signal is not an interrupt signal.
+ * \arg                           irq_signal indicates more than one signal.
+ * \arg                           irq_signal is not currently asserted.
+ */
+static void tfm_svcall_psa_eoi(uint32_t *args)
+{
+}
+
+int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx)
+{
+    switch (svc_num) {
+    case TFM_SVC_PSA_FRAMEWORK_VERSION:
+        return tfm_svcall_psa_framework_version();
+    case TFM_SVC_PSA_VERSION:
+        return tfm_svcall_psa_version(ctx, 0);
+    case TFM_SVC_PSA_CONNECT:
+        return tfm_svcall_psa_connect(ctx, 0);
+    case TFM_SVC_PSA_CALL:
+        return tfm_svcall_psa_call(ctx, 0);
+    case TFM_SVC_PSA_CLOSE:
+        tfm_svcall_psa_close(ctx, 0);
+        break;
+    case TFM_SVC_PSA_WAIT:
+        return tfm_svcall_psa_wait(ctx);
+    case TFM_SVC_PSA_GET:
+        return tfm_svcall_psa_get(ctx);
+    case TFM_SVC_PSA_SET_RHANDLE:
+        tfm_svcall_psa_set_rhandle(ctx);
+        break;
+    case TFM_SVC_PSA_READ:
+        return tfm_svcall_psa_read(ctx);
+    case TFM_SVC_PSA_SKIP:
+        return tfm_svcall_psa_skip(ctx);
+    case TFM_SVC_PSA_WRITE:
+        tfm_svcall_psa_write(ctx);
+        break;
+    case TFM_SVC_PSA_REPLY:
+        tfm_svcall_psa_reply(ctx);
+        break;
+    case TFM_SVC_PSA_NOTIFY:
+        tfm_svcall_psa_notify(ctx);
+        break;
+    case TFM_SVC_PSA_CLEAR:
+        tfm_svcall_psa_clear(ctx);
+        break;
+    case TFM_SVC_PSA_EOI:
+        tfm_svcall_psa_eoi(ctx);
+        break;
+    default:
+        break;
+    }
+    return PSA_SUCCESS;
+}
diff --git a/secure_fw/core/ipc/tfm_thread.c b/secure_fw/core/ipc/tfm_thread.c
deleted file mode 100644
index 58bca8e..0000000
--- a/secure_fw/core/ipc/tfm_thread.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-#include <inttypes.h>
-#include <stdio.h>
-#include "tfm_thread.h"
-
-/*
- * Thread functionality:
- * 1. PSA compliant APIs
- * 2. No priority, no interrupt and tickless
- * 3. Passive context switch in m-series thread mode
- *
- * Steps:
- * 1. Provide a `two threads` context switch first <we are here>;
- * 2. Support multiple thread scheduling and waiting objects;
- * 3. Full thread management;
- */
-
-#if defined(__ARM_ARCH_8M_MAIN__)
-/* FIXME: this function needs to be moved into cpu specfic source! */
-__attribute__((naked)) static void _context_switch(void *curr, void *next)
-{
-    /*
-     * r0 = curr : place to save current context
-     * r1 = next : next context to be loaded and executed
-     */
-    __asm(
-        "stmia r0, {r4-r11, lr}     \n"
-        "ldmia r1, {r4-r11, lr}     \n"
-        "mrs r2, msp                \n"
-        "str r2, [r0, %0]           \n"
-        "mrs r2, msplim             \n"
-        "str r2, [r0, %1]           \n"
-        "ldr r2, [r1, %0]           \n"
-        "msr msp, r2                \n"
-        "ldr r2, [r1, %1]           \n"
-        "msr msplim, r2             \n"
-        "mov r0, #0                 \n" /* clear r0-r3, r12 for security */
-        "mov r1, #0                 \n"
-        "mov r2, #0                 \n"
-        "mov r3, #0                 \n"
-        "mov r12, #0                \n"
-        "bx lr                      \n"
-        ::"I"(SP_POS), "I"(SP_LIMIT_POS)
-    );
-}
-#elif defined(__ARM_ARCH_8M_BASE__)
-__attribute__((naked)) static void _context_switch(void *curr, void *next)
-{
-}
-#else
-#error "Unsupported ARM Architecture."
-#endif
-
-/* Main thread is the first executing conext */
-static struct tfm_thread_info main_thrd;
-static struct tfm_thread_info *p_current;
-
-/*
- * FIXME: this global needs to be replaced with thread list
- * when multiple thread is supported
- */
-extern struct tfm_thread_info test_thrd;
-
-static void _thread_wrapper(void)
-{
-    /*
-     * Use local variable to save client thread conext in case
-     * lost tracking of wrapper client due to global changed.
-     */
-    struct tfm_thread_info *p_thrd_info = p_current;
-    /*
-     * Wrapper runs in client thread context and wait for thread
-     * function return. A return indicates thread is finished.
-     */
-    p_thrd_info->status = TFM_THRD_ACTIVATED;
-    p_thrd_info->retval = p_thrd_info->p_fn(p_thrd_info->param);
-    p_thrd_info->status = TFM_THRD_EXITED;
-
-    /* This thread context is done; switch back to main thread */
-    _context_switch(&p_thrd_info->ctx, &main_thrd.ctx);
-}
-
-/*
- * Schedule current has no scheduling for current;
- * direct switch to another thread.
- */
-void tfm_thread_schedule()
-{
-    struct tfm_thread_info *p_background = p_current;
-
-    if (p_current == &main_thrd) {
-        p_current = &test_thrd;
-    } else {
-        p_current = &main_thrd;
-    }
-
-    if (p_current->status != TFM_THRD_EXITED) {
-        _context_switch(&p_background->ctx, &p_current->ctx);
-    }
-}
-
-int32_t tfm_thread_init()
-{
-    /*
-     * Mark current main thread activated; ignore other info items
-     * since they do not make sense here
-     */
-    main_thrd.status = TFM_THRD_ACTIVATED;
-    p_current = &main_thrd;
-
-    /*
-     * FIXME: change client thread context with thread management
-     * logics later after multiple thread is supported.
-     */
-    test_thrd.ctx.sp = (uint32_t)test_thrd.sp;
-    test_thrd.ctx.sp_limit = (uint32_t)test_thrd.sp_limit;
-    test_thrd.ctx.lr = (uint32_t)_thread_wrapper;
-
-    return 0;
-}
diff --git a/secure_fw/core/ipc/tfm_thread.h b/secure_fw/core/ipc/tfm_thread.h
deleted file mode 100644
index 99534c4..0000000
--- a/secure_fw/core/ipc/tfm_thread.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-#ifndef __TFM_THREAD_H__
-#define __TFM_THREAD_H__
-
-/* FIXME: CPU specific settings, needs to be moved into CPU headers ! */
-struct _ctx {
-    uint32_t r4;
-    uint32_t r5;
-    uint32_t r6;
-    uint32_t r7;
-    uint32_t r8;
-    uint32_t r9;
-    uint32_t r10;
-    uint32_t r11;
-    uint32_t lr;
-    uint32_t sp;
-    uint32_t sp_limit;
-};
-
-#define SP_POS          0x24
-#define SP_LIMIT_POS    0x28
-
-/* thread types */
-#define TFM_THRD_CREATED    0
-#define TFM_THRD_ACTIVATED  1
-#define TFM_THRD_EXITED     2
-
-typedef void *(*thrd_func_t)(void *);
-
-struct tfm_thread_info {
-    uint32_t status;        /* THRD_ACTIVATED or THRD_EXITED */
-    thrd_func_t p_fn;       /* entry function */
-    uint8_t *sp;            /* stack pointer */
-    uint8_t *sp_limit;      /* stack limit */
-    void *param;            /* entry param */
-    void *retval;           /* return value */
-    struct _ctx ctx;
-};
-
-/* init thread module */
-int32_t tfm_thread_init(void);
-void tfm_thread_schedule(void);
-
-/* No dynamic allocation is there; all thread context are static allocated */
-#define REGISTER_TFM_THREAD(thrd_func, param, stack_size)               \
-    static uint8_t stack_test[stack_size] __attribute__((aligned(4))); \
-    struct tfm_thread_info test_thrd = {TFM_THRD_CREATED,               \
-                              thrd_func,                                \
-                              stack_test + stack_size,                  \
-                              stack_test,                               \
-                              (param),                                  \
-                              NULL}
-#endif
diff --git a/secure_fw/core/tfm_core.c b/secure_fw/core/tfm_core.c
index d9f2199..81eeccd 100644
--- a/secure_fw/core/tfm_core.c
+++ b/secure_fw/core/tfm_core.c
@@ -15,12 +15,6 @@
 #include "secure_utilities.h"
 #include "secure_fw/spm/spm_api.h"
 #include "secure_fw/include/tfm_spm_services_api.h"
-#ifdef TFM_PSA_API
-#include "psa_client.h"
-#include "psa_service.h"
-#include "tfm_thread.h"
-#include "tfm_queue.h"
-#endif
 
 /*
  * Avoids the semihosting issue
@@ -176,11 +170,6 @@
     LOG_MSG("Jumping to non-secure code...");
 #endif
 
-#ifdef TFM_PSA_API
-    tfm_queue_init();
-    tfm_thread_init();
-#endif
-
     /* We close the TFM_SP_CORE_ID partition, because its only purpose is
      * to be able to pass the state checks for the tests started from secure.
      */
diff --git a/secure_fw/core/tfm_handler.c b/secure_fw/core/tfm_handler.c
index 2b7ce44..58e0123 100644
--- a/secure_fw/core/tfm_handler.c
+++ b/secure_fw/core/tfm_handler.c
@@ -16,6 +16,10 @@
 #include "region_defs.h"
 #include "tfm_api.h"
 #include "tfm_internal.h"
+#ifdef TFM_PSA_API
+#include <stdbool.h>
+#include "tfm_svcalls.h"
+#endif
 
 /* This SVC handler is called when a secure partition requests access to a
  * buffer area
@@ -185,6 +189,25 @@
     case TFM_SVC_GET_BOOT_DATA:
         tfm_core_get_boot_data_handler(svc_args);
         break;
+#ifdef TFM_PSA_API
+    case TFM_SVC_PSA_FRAMEWORK_VERSION:
+    case TFM_SVC_PSA_VERSION:
+    case TFM_SVC_PSA_CONNECT:
+    case TFM_SVC_PSA_CALL:
+    case TFM_SVC_PSA_CLOSE:
+    case TFM_SVC_PSA_WAIT:
+    case TFM_SVC_PSA_GET:
+    case TFM_SVC_PSA_SET_RHANDLE:
+    case TFM_SVC_PSA_READ:
+    case TFM_SVC_PSA_SKIP:
+    case TFM_SVC_PSA_WRITE:
+    case TFM_SVC_PSA_REPLY:
+    case TFM_SVC_PSA_NOTIFY:
+    case TFM_SVC_PSA_CLEAR:
+    case TFM_SVC_PSA_EOI:
+        svc_args[0] = SVC_Handler_IPC(svc_number, svc_args);
+        break;
+#endif
     default:
         LOG_MSG("Unknown SVC number requested!");
         break;
diff --git a/secure_fw/core/tfm_psa_api_client.c b/secure_fw/core/tfm_psa_api_client.c
index fb93829..af6089e 100644
--- a/secure_fw/core/tfm_psa_api_client.c
+++ b/secure_fw/core/tfm_psa_api_client.c
@@ -8,11 +8,9 @@
 #include <stdio.h>
 #include "psa_client.h"
 #include "psa_service.h"
-#include "tfm_thread.h"
 #include "secure_utilities.h"
 #include "tfm_secure_api.h"
 #include "tfm_api.h"
-#include "tfm_queue.h"
 
 /* FixMe: check if this is really needed */
 extern int32_t tfm_secure_lock;
@@ -101,18 +99,7 @@
      * In case of library model, this function always returns a valid handle.
      * In thread model, it needs to perform the procedures outlined in PSA IPC
      */
-    uint32_t version = minor_version;
-    uint32_t ret;
-    psa_invec in_vecs = {&version, sizeof(version)};
-
-    /* FixMe: just use '1' as sid for example */
-    ret = tfm_queue_put_msg(1, PSA_IPC_CONNECT, &in_vecs, 1, NULL, 0);
-    if (ret != TFM_QUEUE_SUCCESS)
-        return TFM_ERROR_GENERIC;
-    tfm_thread_schedule();
-
-    /* FixMe: just return a fix handle*/
-    return 1;
+     return PSA_SUCCESS;
 }
 
 __tfm_secure_gateway_attributes__
@@ -130,14 +117,7 @@
     /* In case of library model, call the function referenced by the handle
      * In thread model, it needs to perform the procedures outlined in PSA IPC
      */
-    uint32_t ret;
-    ret = tfm_queue_put_msg(1, PSA_IPC_CALL, (psa_invec *)in_vecs->base,
-                            in_vecs->len, (psa_outvec *)out_vecs->base,
-                            out_vecs->len);
-    if (ret != TFM_QUEUE_SUCCESS)
-        return TFM_ERROR_GENERIC;
-    tfm_thread_schedule();
-    return TFM_SUCCESS;
+    return PSA_SUCCESS;
 }
 
 __tfm_secure_gateway_attributes__
@@ -153,12 +133,7 @@
 {
     /* perform sanity check */
     /* Close connection referenced by handle */
-    uint32_t ret;
-    ret = tfm_queue_put_msg(1, PSA_IPC_DISCONNECT, NULL, 0, NULL, 0);
-    if (ret != TFM_QUEUE_SUCCESS)
-        return TFM_ERROR_GENERIC;
-    tfm_thread_schedule();
-    return TFM_SUCCESS;
+    return PSA_SUCCESS;
 }
 
 __tfm_secure_gateway_attributes__
diff --git a/secure_fw/core/tfm_svc.h b/secure_fw/core/tfm_svc.h
index 4fa241a..286a210 100644
--- a/secure_fw/core/tfm_svc.h
+++ b/secure_fw/core/tfm_svc.h
@@ -22,6 +22,23 @@
     TFM_SVC_GET_BOOT_DATA,
 #ifdef TFM_PSA_API
     TFM_SVC_IPC_REQUEST,
+    /* PSA Client SVC */
+    TFM_SVC_PSA_FRAMEWORK_VERSION,
+    TFM_SVC_PSA_VERSION,
+    TFM_SVC_PSA_CONNECT,
+    TFM_SVC_PSA_CALL,
+    TFM_SVC_PSA_CLOSE,
+    /* PSA Service SVC */
+    TFM_SVC_PSA_WAIT,
+    TFM_SVC_PSA_GET,
+    TFM_SVC_PSA_SET_RHANDLE,
+    TFM_SVC_PSA_READ,
+    TFM_SVC_PSA_SKIP,
+    TFM_SVC_PSA_WRITE,
+    TFM_SVC_PSA_REPLY,
+    TFM_SVC_PSA_NOTIFY,
+    TFM_SVC_PSA_CLEAR,
+    TFM_SVC_PSA_EOI,
 #endif
 } tfm_svc_number_t;
 
diff --git a/test/test_services/tfm_ipc_test/ipc_test_service.c b/test/test_services/tfm_ipc_test/ipc_test_service.c
index 5d0af44..85ca0fb 100644
--- a/test/test_services/tfm_ipc_test/ipc_test_service.c
+++ b/test/test_services/tfm_ipc_test/ipc_test_service.c
@@ -9,7 +9,6 @@
 #include <stdio.h>
 #include "psa_client.h"
 #include "psa_service.h"
-#include "secure_fw/core/ipc/tfm_thread.h"
 #include "secure_fw/core/secure_utilities.h"
 #include "secure_fw/core/tfm_secure_api.h"
 #include "tfm_api.h"
@@ -58,7 +57,7 @@
 }
 
 /* Test thread */
-static void *ipc_test_partition_main(void *param)
+void *ipc_test_partition_main(void *param)
 {
     uint32_t signals = 0;
     psa_msg_t msg;
@@ -98,5 +97,3 @@
 
     return NULL;
 }
-
-REGISTER_TFM_THREAD(ipc_test_partition_main, (void *)0x1, 1024);