modules: tf-m: Fix thread preemption toggling

Fixes an issue where thread preemption was not being disabled
correctly, failing to taking into account MetaIRQ, which can be
used to preempt any cooperative thread.

The updated code sets the current thread to `K_HIGHEST_THREAD_PRIO`
before calling the secure function, and restores the thread priority
level once secure execution has terminated, allowing the thread
to be preempted once again.

Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
This commit is contained in:
Kevin Townsend 2023-03-06 02:33:05 +01:00 committed by Carles Cufí
parent 7b364c7f9a
commit 67c1a6bc20

View file

@ -31,6 +31,7 @@ int32_t tfm_ns_interface_dispatch(veneer_fn fn,
{
int32_t result;
bool is_pre_kernel = k_is_pre_kernel();
int tfm_ns_saved_prio;
if (!is_pre_kernel) {
/* TF-M request protected by NS lock */
@ -41,10 +42,15 @@ int32_t tfm_ns_interface_dispatch(veneer_fn fn,
#if !defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
/* Prevent the thread from being preempted, while executing a
* Secure function. This is required to prevent system crashes
* that could occur, if a thead context switch is triggered in
* the middle of a Secure call.
* that could occur, if a thread context switch is triggered in
* the middle of a Secure call. Note that the code below takes
* into account MetaIRQ, which can preempt cooperative threads
* of any priority.
*/
k_sched_lock();
tfm_ns_saved_prio = k_thread_priority_get(k_current_get());
k_thread_priority_set(k_current_get(), K_HIGHEST_THREAD_PRIO);
#else
ARG_UNUSED(tfm_ns_saved_prio);
#endif
}
@ -58,8 +64,8 @@ int32_t tfm_ns_interface_dispatch(veneer_fn fn,
if (!is_pre_kernel) {
#if !defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
/* Unlock the scheduler, to allow the thread to be preempted. */
k_sched_unlock();
/* Restore thread priority, to allow the thread to be preempted. */
k_thread_priority_set(k_current_get(), tfm_ns_saved_prio);
#endif
k_mutex_unlock(&tfm_mutex);