aboutsummaryrefslogtreecommitdiff
path: root/interface/src/tfm_ns_mailbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'interface/src/tfm_ns_mailbox.c')
-rw-r--r--interface/src/tfm_ns_mailbox.c150
1 files changed, 85 insertions, 65 deletions
diff --git a/interface/src/tfm_ns_mailbox.c b/interface/src/tfm_ns_mailbox.c
index 60758b2d7d..4e44fae8d6 100644
--- a/interface/src/tfm_ns_mailbox.c
+++ b/interface/src/tfm_ns_mailbox.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -8,12 +8,15 @@
#include <string.h>
#include "cmsis_compiler.h"
+#include "os_wrapper/common.h"
+#include "tfm_multi_core_api.h"
#include "tfm_ns_mailbox.h"
-#include "tfm_plat_ns.h"
/* The pointer to NSPE mailbox queue */
static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL;
+static int32_t mailbox_wait_reply(mailbox_msg_handle_t handle);
+
static inline void clear_queue_slot_empty(uint8_t idx)
{
if (idx < NUM_MAILBOX_QUEUE_SLOT) {
@@ -35,8 +38,8 @@ static inline void set_queue_slot_pend(uint8_t idx)
}
}
-static inline int32_t get_mailbox_msg_handle(uint8_t idx,
- mailbox_msg_handle_t *handle)
+static 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;
@@ -66,6 +69,15 @@ static inline void clear_queue_slot_replied(uint8_t idx)
}
}
+static inline bool is_queue_slot_replied(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ return mailbox_queue_ptr->replied_slots & (1UL << idx);
+ }
+
+ return false;
+}
+
static inline void set_queue_slot_woken(uint8_t idx)
{
if (idx < NUM_MAILBOX_QUEUE_SLOT) {
@@ -89,7 +101,7 @@ static inline void clear_queue_slot_woken(uint8_t idx)
}
}
-static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue)
+static uint8_t acquire_empty_slot(struct ns_mailbox_queue_t *queue)
{
uint8_t idx;
mailbox_queue_status_t status;
@@ -193,23 +205,15 @@ void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res)
}
#endif
-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)
+static int32_t mailbox_tx_client_req(uint32_t call_type,
+ const struct psa_client_params_t *params,
+ int32_t client_id,
+ mailbox_msg_handle_t *handle)
{
uint8_t idx;
struct mailbox_msg_t *msg_ptr;
- mailbox_msg_handle_t handle;
const void *task_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;
@@ -233,7 +237,7 @@ mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type,
task_handle = tfm_ns_mailbox_get_task_handle();
set_msg_owner(idx, task_handle);
- get_mailbox_msg_handle(idx, &handle);
+ get_mailbox_msg_handle(idx, handle);
tfm_ns_mailbox_hal_enter_critical();
set_queue_slot_pend(idx);
@@ -241,19 +245,15 @@ mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type,
tfm_ns_mailbox_hal_notify_peer();
- return handle;
+ return MAILBOX_SUCCESS;
}
-int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle,
+static int32_t 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;
}
@@ -269,7 +269,6 @@ int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle,
set_msg_owner(idx, NULL);
tfm_ns_mailbox_hal_enter_critical();
- clear_queue_slot_replied(idx);
clear_queue_slot_woken(idx);
/*
* Make sure that the empty flag is set after all the other status flags are
@@ -281,44 +280,59 @@ int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle,
return MAILBOX_SUCCESS;
}
-bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle)
+int32_t tfm_ns_mailbox_client_call(uint32_t call_type,
+ const struct psa_client_params_t *params,
+ int32_t client_id,
+ int32_t *reply)
{
- uint8_t idx;
+ mailbox_msg_handle_t handle = MAILBOX_MSG_NULL_HANDLE;
+ int32_t reply_buf = 0x0;
int32_t ret;
- mailbox_queue_status_t status;
if (!mailbox_queue_ptr) {
- return false;
+ return MAILBOX_INIT_ERROR;
}
- if (handle == MAILBOX_MSG_NULL_HANDLE) {
- return false;
+ if (!params || !reply) {
+ return MAILBOX_INVAL_PARAMS;
}
- ret = get_mailbox_msg_idx(handle, &idx);
+ if (tfm_ns_multi_core_lock_acquire() != OS_WRAPPER_SUCCESS) {
+ return MAILBOX_QUEUE_FULL;
+ }
+
+ /* It requires SVCall if NS mailbox is put in privileged mode. */
+ ret = mailbox_tx_client_req(call_type, params, client_id, &handle);
if (ret != MAILBOX_SUCCESS) {
- return false;
+ goto exit;
}
- tfm_ns_mailbox_hal_enter_critical();
- status = mailbox_queue_ptr->replied_slots;
- tfm_ns_mailbox_hal_exit_critical();
+ mailbox_wait_reply(handle);
- if (status & (1 << idx)) {
- return true;
+ /* It requires SVCall if NS mailbox is put in privileged mode. */
+ ret = mailbox_rx_client_reply(handle, &reply_buf);
+ if (ret == MAILBOX_SUCCESS) {
+ *reply = reply_buf;
}
- return false;
+exit:
+ if (tfm_ns_multi_core_lock_release() != OS_WRAPPER_SUCCESS) {
+ return MAILBOX_GENERIC_ERROR;
+ }
+
+ return ret;
}
-mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void)
+#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL
+int32_t tfm_ns_mailbox_wake_reply_owner_isr(void)
{
uint8_t idx;
+ int32_t ret;
mailbox_msg_handle_t handle;
mailbox_queue_status_t replied_status;
if (!mailbox_queue_ptr) {
- return MAILBOX_MSG_NULL_HANDLE;
+ return MAILBOX_INIT_ERROR;
}
tfm_ns_mailbox_hal_enter_critical_isr();
@@ -326,7 +340,7 @@ mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void)
tfm_ns_mailbox_hal_exit_critical_isr();
if (!replied_status) {
- return MAILBOX_MSG_NULL_HANDLE;
+ return MAILBOX_NO_PEND_EVENT;
}
for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) {
@@ -337,29 +351,26 @@ mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void)
set_queue_slot_woken(idx);
tfm_ns_mailbox_hal_exit_critical_isr();
- if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) {
- return handle;
- }
+ break;
}
}
- return MAILBOX_MSG_NULL_HANDLE;
-}
-
-const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle)
-{
- uint8_t idx;
-
- if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) {
- return NULL;
+ /* In theory, it won't occur. Just in case */
+ if (idx == NUM_MAILBOX_QUEUE_SLOT) {
+ return MAILBOX_NO_PEND_EVENT;
}
- if (idx < NUM_MAILBOX_QUEUE_SLOT) {
- return mailbox_queue_ptr->queue[idx].owner;
+ ret = get_mailbox_msg_handle(idx, &handle);
+ if (ret != MAILBOX_SUCCESS) {
+ return ret;
}
- return NULL;
+ tfm_ns_mailbox_hal_wake_task_isr(mailbox_queue_ptr->queue[idx].owner,
+ handle);
+
+ return MAILBOX_SUCCESS;
}
+#endif
int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue)
{
@@ -394,16 +405,11 @@ int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue)
return ret;
}
-#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL
-int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle)
+static int32_t mailbox_wait_reply(mailbox_msg_handle_t handle)
{
uint8_t idx;
int32_t ret;
- if (!mailbox_queue_ptr) {
- return MAILBOX_INVAL_PARAMS;
- }
-
if (handle == MAILBOX_MSG_NULL_HANDLE) {
return MAILBOX_INVAL_PARAMS;
}
@@ -422,13 +428,27 @@ int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle)
* woken up by reply event, rather than other events.
*/
tfm_ns_mailbox_hal_enter_critical();
+ /*
+ * It requires SVCall to access NS mailbox flags if NS mailbox is put
+ * in privileged mode.
+ * An alternative is to let NS thread allocate its own is_woken flag.
+ * But a spinlock-like mechanism is still required.
+ */
+#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL
if (is_queue_slot_woken(idx)) {
- tfm_ns_mailbox_hal_exit_critical();
+ clear_queue_slot_woken(idx);
break;
}
+#else
+ if (is_queue_slot_replied(idx)) {
+ clear_queue_slot_replied(idx);
+ break;
+ }
+#endif
tfm_ns_mailbox_hal_exit_critical();
}
+ tfm_ns_mailbox_hal_exit_critical();
+
return MAILBOX_SUCCESS;
}
-#endif