diff options
author | David Hu <david.hu@arm.com> | 2019-11-12 18:43:34 +0800 |
---|---|---|
committer | David Hu <david.hu@arm.com> | 2020-02-14 11:05:29 +0800 |
commit | 3684ee71ca38c0d6a184cc34223f00f4036ccb6f (patch) | |
tree | d43c47e1c7a5aa87593a84df0f7a68456c8c5c7f | |
parent | c617ba146297fb3733d455da5f922adb5f833a1b (diff) | |
download | trusted-firmware-m-3684ee71ca38c0d6a184cc34223f00f4036ccb6f.tar.gz |
Dualcpu: Add NS mailbox functions to handle reply in IRQ handler
Add tfm_ns_mailbox_fetch_reply_msg_isr() to fetch the handle of the
first replied mailbox message from NSPE mailbox queue in platform
inter-processor communication interrupt handler.
NS OS can get the handle of the waiting caller task by calling
tfm_ns_mailbox_get_msg_owner() and wake-up the caller task
according to the handle value.
Change-Id: Id86e0b23819cf8963831006fd037142d9efb4d9f
Signed-off-by: David Hu <david.hu@arm.com>
-rw-r--r-- | interface/include/tfm_mailbox.h | 11 | ||||
-rw-r--r-- | interface/include/tfm_ns_mailbox.h | 26 | ||||
-rw-r--r-- | interface/src/tfm_ns_mailbox.c | 64 |
3 files changed, 97 insertions, 4 deletions
diff --git a/interface/include/tfm_mailbox.h b/interface/include/tfm_mailbox.h index bb23b7a097..76759aa360 100644 --- a/interface/include/tfm_mailbox.h +++ b/interface/include/tfm_mailbox.h @@ -15,6 +15,7 @@ #ifndef __TFM_MAILBOX_H__ #define __TFM_MAILBOX_H__ +#include <stdbool.h> #include <stdint.h> #include <stddef.h> #include "psa/client.h" @@ -108,9 +109,13 @@ struct mailbox_reply_t { struct ns_mailbox_slot_t { struct mailbox_msg_t msg; struct mailbox_reply_t reply; - const void *owner; /* Handle of the owner task of this - * slot - */ + const void *owner; /* Handle of the owner task of this + * slot + */ + bool is_woken; /* Indicate that owner task has been + * or should be woken up, after the + * replied is received. + */ }; typedef uint32_t mailbox_queue_status_t; diff --git a/interface/include/tfm_ns_mailbox.h b/interface/include/tfm_ns_mailbox.h index 3340735260..49c4ca6043 100644 --- a/interface/include/tfm_ns_mailbox.h +++ b/interface/include/tfm_ns_mailbox.h @@ -88,6 +88,32 @@ static inline const void *tfm_ns_mailbox_get_task_handle(void) #endif /** + * \brief Fetch the handle to the first replied mailbox message in the NSPE + * mailbox queue. + * This function is intended to be called inside platform specific + * notification IRQ handler. + * + * \note The replied status of the fetched mailbox message will be cleaned after + * the message is fetched. When this function is called again, it fetches + * the next replied mailbox message from the NSPE mailbox queue. + * + * \return Return the handle to the first replied mailbox message in the + * queue. + * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. + */ +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); + +/** + * \brief Return the handle of owner task of a mailbox message according to the + * \ref mailbox_msg_handle_t + * + * \param[in] handle The handle of mailbox message. + * + * \return Return the handle value of the owner task. + */ +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); + +/** * \brief Platform specific NSPE mailbox initialization. * Invoked by \ref tfm_ns_mailbox_init(). * diff --git a/interface/src/tfm_ns_mailbox.c b/interface/src/tfm_ns_mailbox.c index 9ab3004769..98193e8c80 100644 --- a/interface/src/tfm_ns_mailbox.c +++ b/interface/src/tfm_ns_mailbox.c @@ -64,6 +64,13 @@ static inline void clear_queue_slot_replied(uint8_t idx) } } +static inline void set_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = true; + } +} + static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) { uint8_t idx; @@ -170,8 +177,13 @@ int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, set_msg_owner(idx, NULL); tfm_ns_mailbox_hal_enter_critical(); - set_queue_slot_empty(idx); 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 + * re-initialized. + */ + set_queue_slot_empty(idx); tfm_ns_mailbox_hal_exit_critical(); return MAILBOX_SUCCESS; @@ -207,6 +219,56 @@ bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) return false; } +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) +{ + uint8_t idx; + mailbox_msg_handle_t handle; + mailbox_queue_status_t replied_status; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + tfm_ns_mailbox_hal_enter_critical_isr(); + replied_status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (!replied_status) { + return MAILBOX_MSG_NULL_HANDLE; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + /* Find the first replied message in queue */ + if (replied_status & (0x1UL << idx)) { + tfm_ns_mailbox_hal_enter_critical_isr(); + clear_queue_slot_replied(idx); + set_queue_slot_woken(idx); + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { + return handle; + } + } + } + + 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; + } + + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].owner; + } + + return NULL; +} + int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) { int32_t ret; |