Twincpu: Add NSPE mailbox implementation
Add reference example of NSPE mailbox implementation
Change-Id: I6b658459faaddbbc643761a93714a78df6fdbb38
Signed-off-by: David Hu <david.hu@arm.com>
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 0dff1e9..2e6154e 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -106,7 +106,11 @@
endif()
if (TFM_PSA_API)
- list(APPEND NS_APP_SRC "${INTERFACE_DIR}/src/tfm_psa_ns_api.c")
+ if (DEFINED TFM_MULTI_CORE_TOPOLOGY AND TFM_MULTI_CORE_TOPOLOGY)
+ list(APPEND NS_APP_SRC "${INTERFACE_DIR}/src/tfm_ns_mailbox.c")
+ else()
+ list(APPEND NS_APP_SRC "${INTERFACE_DIR}/src/tfm_psa_ns_api.c")
+ endif()
endif()
set(BUILD_CMSIS_CORE On)
diff --git a/interface/src/tfm_ns_mailbox.c b/interface/src/tfm_ns_mailbox.c
new file mode 100644
index 0000000..23e450e
--- /dev/null
+++ b/interface/src/tfm_ns_mailbox.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+#include "tfm_ns_mailbox.h"
+
+/* The pointer to NSPE mailbox queue */
+static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL;
+
+static inline void clear_queue_slot_empty(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ mailbox_queue_ptr->empty_slots &= ~(1 << idx);
+ }
+}
+
+static inline void set_queue_slot_empty(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ mailbox_queue_ptr->empty_slots |= (1 << idx);
+ }
+}
+
+static inline void set_queue_slot_pend(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ mailbox_queue_ptr->pend_slots |= (1 << idx);
+ }
+}
+
+static inline int32_t get_mailbox_msg_handle(uint8_t idx,
+ mailbox_msg_handle_t *handle)
+{
+ if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ *handle = (mailbox_msg_handle_t)(idx + 1);
+
+ return MAILBOX_SUCCESS;
+}
+
+static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle,
+ uint8_t *idx)
+{
+ if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ *idx = (uint8_t)(handle - 1);
+
+ return MAILBOX_SUCCESS;
+}
+
+static inline void clear_queue_slot_replied(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ mailbox_queue_ptr->replied_slots &= ~(1 << idx);
+ }
+}
+
+static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue)
+{
+ uint8_t idx;
+ mailbox_queue_status_t status;
+
+ tfm_ns_mailbox_hal_enter_critical();
+ status = queue->empty_slots;
+
+ if (!status) {
+ /* No empty slot */
+ tfm_ns_mailbox_hal_exit_critical();
+ return NUM_MAILBOX_QUEUE_SLOT;
+ }
+
+ for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) {
+ if (status & (1 << idx)) {
+ break;
+ }
+ }
+
+ clear_queue_slot_empty(idx);
+
+ tfm_ns_mailbox_hal_exit_critical();
+
+ return idx;
+}
+
+mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type,
+ const struct psa_client_params_t *params,
+ int32_t client_id)
+{
+ uint8_t idx;
+ struct mailbox_msg_t *msg_ptr;
+ mailbox_msg_handle_t handle;
+
+ if (!mailbox_queue_ptr) {
+ return MAILBOX_MSG_NULL_HANDLE;
+ }
+
+ if (!params) {
+ return MAILBOX_MSG_NULL_HANDLE;
+ }
+
+ idx = acquire_empty_slot(mailbox_queue_ptr);
+ if (idx >= NUM_MAILBOX_QUEUE_SLOT) {
+ return MAILBOX_QUEUE_FULL;
+ }
+
+ /* Fill the mailbox message */
+ msg_ptr = &mailbox_queue_ptr->queue[idx].msg;
+
+ msg_ptr->call_type = call_type;
+ memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params));
+ msg_ptr->client_id = client_id;
+
+ get_mailbox_msg_handle(idx, &handle);
+
+ tfm_ns_mailbox_hal_enter_critical();
+ set_queue_slot_pend(idx);
+ tfm_ns_mailbox_hal_exit_critical();
+
+ tfm_ns_mailbox_hal_notify_peer();
+
+ return handle;
+}
+
+int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle,
+ int32_t *reply)
+{
+ uint8_t idx;
+ int32_t ret;
+
+ if (!mailbox_queue_ptr) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ ret = get_mailbox_msg_idx(handle, &idx);
+ if (ret != MAILBOX_SUCCESS) {
+ return ret;
+ }
+
+ *reply = mailbox_queue_ptr->queue[idx].reply.return_val;
+
+ tfm_ns_mailbox_hal_enter_critical();
+ set_queue_slot_empty(idx);
+ clear_queue_slot_replied(idx);
+ tfm_ns_mailbox_hal_exit_critical();
+
+ return MAILBOX_SUCCESS;
+}
+
+bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle)
+{
+ uint8_t idx;
+ int32_t ret;
+ mailbox_queue_status_t status;
+
+ if (!mailbox_queue_ptr) {
+ return false;
+ }
+
+ if (handle == MAILBOX_MSG_NULL_HANDLE) {
+ return false;
+ }
+
+ ret = get_mailbox_msg_idx(handle, &idx);
+ if (ret != MAILBOX_SUCCESS) {
+ return false;
+ }
+
+ tfm_ns_mailbox_hal_enter_critical();
+ status = mailbox_queue_ptr->replied_slots;
+ tfm_ns_mailbox_hal_exit_critical();
+
+ if (status & (1 << idx)) {
+ return true;
+ }
+
+ return false;
+}
+
+int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue)
+{
+ int32_t ret;
+
+ if (!queue) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ /*
+ * Further verification of mailbox queue address may be required according
+ * to non-secure memory assignment.
+ */
+
+ memset(queue, 0, sizeof(*queue));
+
+ /* Initialize empty bitmask */
+ queue->empty_slots = (mailbox_queue_status_t)((1 << NUM_MAILBOX_QUEUE_SLOT)
+ - 1);
+
+ mailbox_queue_ptr = queue;
+
+ /* Platform specific initialization. */
+ ret = tfm_ns_mailbox_hal_init(queue);
+
+ return ret;
+}
diff --git a/secure_fw/core/ipc/tfm_spe_mailbox.c b/secure_fw/core/ipc/tfm_spe_mailbox.c
index 3b947a6..0175381 100644
--- a/secure_fw/core/ipc/tfm_spe_mailbox.c
+++ b/secure_fw/core/ipc/tfm_spe_mailbox.c
@@ -190,17 +190,17 @@
TFM_ASSERT(ns_queue != NULL);
- tfm_mailbox_enter_critical();
+ tfm_ns_mailbox_hal_enter_critical();
/* Check if NSPE mailbox did assert a PSA client call request */
if (!ns_queue->pend_slots) {
- tfm_mailbox_exit_critical();
+ tfm_ns_mailbox_hal_exit_critical();
return MAILBOX_NO_PEND_EVENT;
}
pend_slots = get_nspe_queue_pend_status(ns_queue);
- tfm_mailbox_exit_critical();
+ tfm_ns_mailbox_hal_exit_critical();
for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) {
mask_bits = (1 << idx);
@@ -267,7 +267,7 @@
*/
}
- tfm_mailbox_enter_critical();
+ tfm_ns_mailbox_hal_enter_critical();
/* Clean the NSPE mailbox pending status. */
clear_nspe_queue_pend_status(ns_queue, pend_slots);
@@ -275,10 +275,10 @@
/* Set the NSPE mailbox replied status */
set_nspe_queue_replied_status(ns_queue, reply_slots);
- tfm_mailbox_exit_critical();
+ tfm_ns_mailbox_hal_exit_critical();
if (reply_slots) {
- tfm_mailbox_notify_peer();
+ tfm_ns_mailbox_hal_notify_peer();
}
return MAILBOX_SUCCESS;
@@ -313,12 +313,12 @@
mailbox_direct_reply(idx, (uint32_t)reply);
- tfm_mailbox_enter_critical();
+ tfm_ns_mailbox_hal_enter_critical();
/* Set the NSPE mailbox replied status */
set_nspe_queue_replied_status(ns_queue, (1 << idx));
- tfm_mailbox_exit_critical();
+ tfm_ns_mailbox_hal_exit_critical();
tfm_mailbox_notify_peer();
@@ -350,7 +350,7 @@
.reply = mailbox_reply,
};
-int32_t tfm_mailbox_init(void)
+int32_t tfm_ns_mailbox_init(void)
{
int32_t ret;
@@ -370,7 +370,7 @@
* Initialize Inter-Processor Communication and achieve the base address of
* NSPE mailbox queue
*/
- ret = tfm_mailbox_hal_init(&spe_mailbox_queue);
+ ret = tfm_ns_mailbox_hal_init(&spe_mailbox_queue);
if (ret != MAILBOX_SUCCESS) {
tfm_rpc_unregister_ops();