SPM: Add STATUS_NEED_SCHEDULE to manage scheduler
THRD_EXPECTING_SCHEDULE() calls thrd_next() to decide whether
scheduling is required and when it is required, PendSV will
call thrd_next() again in ipc_schedule(). This duplicated
call of thrd_next() can be avoided by returning a status of
STATUS_NEED_SCHDULABLE from backend in these locations:
- SVC_Handler
- SPM cross API
- Interrupt handler
Signed-off-by: Jianliang Shen <jianliang.shen@arm.com>
Change-Id: I3f1fccbb045938624089e856b5a98c3365c76fcc
diff --git a/secure_fw/spm/cmsis_psa/internal_status_code.h b/secure_fw/spm/cmsis_psa/internal_status_code.h
index d9665cf..fbb0b63 100644
--- a/secure_fw/spm/cmsis_psa/internal_status_code.h
+++ b/secure_fw/spm/cmsis_psa/internal_status_code.h
@@ -16,4 +16,6 @@
#define SPM_ERROR_MEMORY_CHECK ((psa_status_t)-252)
#define SPM_ERROR_GENERIC ((psa_status_t)-253)
+#define STATUS_NEED_SCHEDULE ((psa_status_t)-254)
+
#endif /* __INTERNAL_STATUS_CODE_H__ */
diff --git a/secure_fw/spm/cmsis_psa/spm_cross_call.c b/secure_fw/spm/cmsis_psa/spm_cross_call.c
index 4e4aa40..8778730 100644
--- a/secure_fw/spm/cmsis_psa/spm_cross_call.c
+++ b/secure_fw/spm/cmsis_psa/spm_cross_call.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -13,6 +13,7 @@
#include "tfm_arch.h"
#include "ffm/backend.h"
#include "ffm/psa_api.h"
+#include "internal_status_code.h"
typedef psa_status_t (*target_fn_t)(uint32_t a0, uint32_t a1,
uint32_t a2, uint32_t a3);
@@ -53,7 +54,7 @@
}
/* Interrupt is masked, PendSV will not happen immediately. */
- if (THRD_EXPECTING_SCHEDULE()) {
+ if (status == STATUS_NEED_SCHEDULE) {
tfm_arch_trigger_pendsv();
}
}
diff --git a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
index 5f9ce65..e11fcf7 100644
--- a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
+++ b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
@@ -24,6 +24,7 @@
#include "load/partition_defs.h"
#include "psa/client.h"
#include "tfm_hal_platform.h"
+#include "internal_status_code.h"
/* MSP bottom (higher address) */
REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
@@ -61,7 +62,7 @@
break;
#if CONFIG_TFM_DOORBELL_API == 1
case TFM_SVC_PSA_NOTIFY:
- tfm_spm_partition_psa_notify((int32_t)ctx[0]);
+ return tfm_spm_partition_psa_notify((int32_t)ctx[0]);
break;
case TFM_SVC_PSA_CLEAR:
tfm_spm_partition_psa_clear();
@@ -201,7 +202,7 @@
tfm_core_panic();
}
svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, exc_return);
- if (THRD_EXPECTING_SCHEDULE()) {
+ if (svc_args[0] == STATUS_NEED_SCHEDULE) {
tfm_arch_trigger_pendsv();
}
#else
diff --git a/secure_fw/spm/cmsis_psa/thread.h b/secure_fw/spm/cmsis_psa/thread.h
index 2250a31..c7f53db 100644
--- a/secure_fw/spm/cmsis_psa/thread.h
+++ b/secure_fw/spm/cmsis_psa/thread.h
@@ -93,14 +93,6 @@
CURRENT_THREAD->p_context_ctrl = (void *)(x)
/*
- * Check if a schedule is under expectation by measuring on a given thread.
- *
- * Return :
- * `true` if schedule is under expectation. `false` if not.
- */
-#define THRD_EXPECTING_SCHEDULE() (!(thrd_next() == CURRENT_THREAD))
-
-/*
* Init the global query state callback function pointer.
*
* Parameters :
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index fe6e2c3..07b01f5 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -26,6 +26,7 @@
#include "load/service_defs.h"
#include "load/spm_load_api.h"
#include "psa/error.h"
+#include "internal_status_code.h"
/* Declare the global component list */
struct partition_head_t partition_listhead;
@@ -151,6 +152,7 @@
{
struct partition_t *p_owner = NULL;
psa_signal_t signal = 0;
+ psa_status_t ret = PSA_SUCCESS;
if (!handle || !service || !service->p_ldinf || !service->partition) {
return PSA_ERROR_PROGRAMMER_ERROR;
@@ -162,7 +164,7 @@
UNI_LIST_INSERT_AFTER(p_owner, handle, p_handles);
/* Messages put. Update signals */
- backend_assert_signal(p_owner, signal);
+ ret = backend_assert_signal(p_owner, signal);
/*
* If it is a NS request via RPC, it is unnecessary to block current
@@ -170,12 +172,14 @@
*/
if (!is_tfm_rpc_msg(handle)) {
- backend_wait_signals(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+ ret = backend_wait_signals(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+ } else {
+ ret = PSA_SUCCESS;
}
handle->status = TFM_HANDLE_STATUS_ACTIVE;
- return PSA_SUCCESS;
+ return ret;
}
psa_status_t backend_replying(struct connection_t *handle, int32_t status)
@@ -184,7 +188,7 @@
tfm_rpc_client_call_reply(handle, status);
} else {
handle->p_client->reply_value = (uintptr_t)status;
- backend_assert_signal(handle->p_client, TFM_IPC_REPLY_SIGNAL);
+ return backend_assert_signal(handle->p_client, TFM_IPC_REPLY_SIGNAL);
}
/*
@@ -263,10 +267,10 @@
return control;
}
-psa_signal_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
+psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
{
struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
- psa_signal_t ret_signal;
+ psa_status_t ret = PSA_SUCCESS;
if (!p_pt) {
tfm_core_panic();
@@ -274,19 +278,21 @@
CRITICAL_SECTION_ENTER(cs_signal);
- ret_signal = p_pt->signals_asserted & signals;
- if (ret_signal == 0) {
+ ret = p_pt->signals_asserted & signals;
+ if (ret == 0) {
p_pt->signals_waiting = signals;
+ ret = STATUS_NEED_SCHEDULE;
}
CRITICAL_SECTION_LEAVE(cs_signal);
- return ret_signal;
+ return ret;
}
-uint32_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
+psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
{
struct critical_section_t cs_signal = CRITICAL_SECTION_STATIC_INIT;
+ psa_status_t ret = PSA_SUCCESS;
if (!p_pt) {
tfm_core_panic();
@@ -294,9 +300,13 @@
CRITICAL_SECTION_ENTER(cs_signal);
p_pt->signals_asserted |= signal;
+
+ if (p_pt->signals_asserted & p_pt->signals_waiting) {
+ ret = STATUS_NEED_SCHEDULE;
+ }
CRITICAL_SECTION_LEAVE(cs_signal);
- return PSA_SUCCESS;
+ return ret;
}
uint64_t ipc_schedule(void)
diff --git a/secure_fw/spm/ffm/backend_sfn.c b/secure_fw/spm/ffm/backend_sfn.c
index 81e60f5..c9d9d6d 100644
--- a/secure_fw/spm/ffm/backend_sfn.c
+++ b/secure_fw/spm/ffm/backend_sfn.c
@@ -148,7 +148,7 @@
return EXC_RETURN_THREAD_PSP;
}
-psa_signal_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
+psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals)
{
while (!(p_pt->signals_asserted & signals))
;
@@ -156,7 +156,7 @@
return p_pt->signals_asserted & signals;
}
-uint32_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
+psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal)
{
p_pt->signals_asserted |= signal;
diff --git a/secure_fw/spm/ffm/interrupt.c b/secure_fw/spm/ffm/interrupt.c
index 7ec611e..0b5e043 100644
--- a/secure_fw/spm/ffm/interrupt.c
+++ b/secure_fw/spm/ffm/interrupt.c
@@ -21,6 +21,7 @@
#include "load/spm_load_api.h"
#include "ffm/backend.h"
+#include "internal_status_code.h"
extern uintptr_t spm_boundary;
@@ -142,6 +143,7 @@
{
psa_flih_result_t flih_result;
struct partition_t *p_part;
+ psa_status_t ret = 0;
if (!p_pt || !p_ildi) {
tfm_core_panic();
@@ -175,10 +177,10 @@
}
if (flih_result == PSA_FLIH_SIGNAL) {
- backend_assert_signal(p_pt, p_ildi->signal);
+ ret = backend_assert_signal(p_pt, p_ildi->signal);
/* In SFN backend, there is only one thread, no thread switch. */
#if CONFIG_TFM_SPM_BACKEND_SFN != 1
- if (THRD_EXPECTING_SCHEDULE()) {
+ if (ret == STATUS_NEED_SCHEDULE) {
tfm_arch_trigger_pendsv();
}
#endif
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index 1f1c715..7a46c04 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -530,11 +530,11 @@
}
#if CONFIG_TFM_DOORBELL_API == 1
-void tfm_spm_partition_psa_notify(int32_t partition_id)
+psa_status_t tfm_spm_partition_psa_notify(int32_t partition_id)
{
struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
- backend_assert_signal(p_pt, PSA_DOORBELL);
+ return backend_assert_signal(p_pt, PSA_DOORBELL);
}
void tfm_spm_partition_psa_clear(void)
diff --git a/secure_fw/spm/include/ffm/backend.h b/secure_fw/spm/include/ffm/backend.h
index 03f2f14..d15fdc2 100644
--- a/secure_fw/spm/include/ffm/backend.h
+++ b/secure_fw/spm/include/ffm/backend.h
@@ -55,12 +55,12 @@
/**
* \brief Set the wait signal pattern in current partition.
*/
-psa_signal_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals);
+psa_status_t backend_wait_signals(struct partition_t *p_pt, psa_signal_t signals);
/**
* \brief Set the asserted signal pattern in current partition.
*/
-uint32_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal);
+psa_status_t backend_assert_signal(struct partition_t *p_pt, psa_signal_t signal);
/* The component list, and a MACRO indicate this is not a common global. */
extern struct partition_head_t partition_listhead;
diff --git a/secure_fw/spm/include/ffm/psa_api.h b/secure_fw/spm/include/ffm/psa_api.h
index 868c178..152ba17 100644
--- a/secure_fw/spm/include/ffm/psa_api.h
+++ b/secure_fw/spm/include/ffm/psa_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -267,11 +267,12 @@
*
* \param[in] partition_id Secure Partition ID of the target partition.
*
- * \retval void Success.
+ * \retval PSA_SUCCESS Success.
+ * \retval PSA_NEED_SCHEDULE Require schedule thread.
* \retval "PROGRAMMER ERROR" partition_id does not correspond to a Secure
* Partition.
*/
-void tfm_spm_partition_psa_notify(int32_t partition_id);
+psa_status_t tfm_spm_partition_psa_notify(int32_t partition_id);
/**
* \brief Function body of \ref psa_clear.