1 /*
2 * Copyright (c) 2019,2020 Linaro Limited
3 * Copyright (c) 2021 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <device.h>
9 #include <init.h>
10 #include <kernel.h>
11 #include <arch/arm/aarch32/cortex_m/cmsis.h>
12 #include <arch/arm/aarch32/cortex_m/fpu.h>
13
14 #include <tfm_ns_interface.h>
15
16 /**
17 * @file @brief Zephyr's TF-M NS interface implementation
18 *
19 */
20
21
22 /* Global mutex to be used by the TF-M NS dispatcher, preventing
23 * the Non-Secure application from initiating multiple parallel
24 * TF-M secure calls.
25 */
26 K_MUTEX_DEFINE(tfm_mutex);
27
tfm_ns_interface_dispatch(veneer_fn fn,uint32_t arg0,uint32_t arg1,uint32_t arg2,uint32_t arg3)28 int32_t tfm_ns_interface_dispatch(veneer_fn fn,
29 uint32_t arg0, uint32_t arg1,
30 uint32_t arg2, uint32_t arg3)
31 {
32 int32_t result;
33
34 /* TF-M request protected by NS lock */
35 if (k_mutex_lock(&tfm_mutex, K_FOREVER) != 0) {
36 return (int32_t)TFM_ERROR_GENERIC;
37 }
38
39 #if !defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
40 /*
41 * Prevent the thread from being preempted, while executing a Secure
42 * function. This is required to prevent system crashes that could
43 * occur, if a thead context switch is triggered in the middle of a
44 * Secure call.
45 */
46 k_sched_lock();
47 #endif
48
49 #if defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
50 struct fpu_ctx_full context_buffer;
51
52 z_arm_save_fp_context(&context_buffer);
53 #endif
54
55 result = fn(arg0, arg1, arg2, arg3);
56
57 #if defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
58 z_arm_restore_fp_context(&context_buffer);
59 #endif
60
61 #if !defined(CONFIG_ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS)
62 /* Unlock the scheduler, to allow the thread to be preempted. */
63 k_sched_unlock();
64 #endif
65
66 k_mutex_unlock(&tfm_mutex);
67
68 return result;
69 }
70
tfm_ns_interface_init(void)71 enum tfm_status_e tfm_ns_interface_init(void)
72 {
73 /*
74 * The static K_MUTEX_DEFINE handles mutex initialization,
75 * so this function may be implemented as no-op.
76 */
77 return TFM_SUCCESS;
78 }
79
80
81 #if defined(TFM_PSA_API)
82 #include "psa_manifest/sid.h"
83 #endif /* TFM_PSA_API */
84
ns_interface_init(const struct device * arg)85 static int ns_interface_init(const struct device *arg)
86 {
87 ARG_UNUSED(arg);
88
89 __ASSERT(tfm_ns_interface_init() == TFM_SUCCESS,
90 "TF-M NS interface init failed");
91
92 return 0;
93 }
94
95 /* Initialize the TFM NS interface */
96 SYS_INIT(ns_interface_init, POST_KERNEL,
97 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
98