zephyr/modules/trusted-firmware-m/interface/interface.c
Øyvind Rønningstad 382bbacb0a tfm: Put saving of FPU context into its own file so it can be reused
Also, this eases readability.

The new API can be used any time all FP registers must be manually
saved and restored for an operation.

Signed-off-by: Øyvind Rønningstad <oyvind.ronningstad@nordicsemi.no>
2021-06-07 15:23:22 +02:00

98 lines
2.2 KiB
C

/*
* Copyright (c) 2019,2020 Linaro Limited
* Copyright (c) 2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <init.h>
#include <kernel.h>
#include <arch/arm/aarch32/cortex_m/cmsis.h>
#include <arch/arm/aarch32/cortex_m/fpu.h>
#include <tfm_ns_interface.h>
/**
* @file @brief Zephyr's TF-M NS interface implementation
*
*/
/* Global mutex to be used by the TF-M NS dispatcher, preventing
* the Non-Secure application from initiating multiple parallel
* TF-M secure calls.
*/
K_MUTEX_DEFINE(tfm_mutex);
int32_t tfm_ns_interface_dispatch(veneer_fn fn,
uint32_t arg0, uint32_t arg1,
uint32_t arg2, uint32_t arg3)
{
int32_t result;
/* TF-M request protected by NS lock */
if (k_mutex_lock(&tfm_mutex, K_FOREVER) != 0) {
return (int32_t)TFM_ERROR_GENERIC;
}
#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.
*/
k_sched_lock();
#endif
#if defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
struct fpu_ctx_full context_buffer;
z_arm_save_fp_context(&context_buffer);
#endif
result = fn(arg0, arg1, arg2, arg3);
#if defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
z_arm_restore_fp_context(&context_buffer);
#endif
#if !defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
/* Unlock the scheduler, to allow the thread to be preempted. */
k_sched_unlock();
#endif
k_mutex_unlock(&tfm_mutex);
return result;
}
enum tfm_status_e tfm_ns_interface_init(void)
{
/*
* The static K_MUTEX_DEFINE handles mutex initialization,
* so this function may be implemented as no-op.
*/
return TFM_SUCCESS;
}
#if defined(TFM_PSA_API)
#include "psa_manifest/sid.h"
#endif /* TFM_PSA_API */
static int ns_interface_init(const struct device *arg)
{
ARG_UNUSED(arg);
__ASSERT(tfm_ns_interface_init() == TFM_SUCCESS,
"TF-M NS interface init failed");
return 0;
}
/* Initialize the TFM NS interface */
SYS_INIT(ns_interface_init, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);