1 /******************************************************************************
3 * @brief Context Management for Armv8-M TrustZone - Sample implementation
5 * @date 10. January 2018
6 ******************************************************************************/
8 * Copyright (c) 2016-2018 Arm Limited. All rights reserved.
10 * SPDX-License-Identifier: Apache-2.0
12 * Licensed under the Apache License, Version 2.0 (the License); you may
13 * not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
16 * www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
25 #include "RTE_Components.h"
26 #include CMSIS_device_header
27 #include "tz_context.h"
29 /// Number of process slots (threads may call secure library code)
30 #ifndef TZ_PROCESS_STACK_SLOTS
31 #define TZ_PROCESS_STACK_SLOTS 8U
34 /// Stack size of the secure library code
35 #ifndef TZ_PROCESS_STACK_SIZE
36 #define TZ_PROCESS_STACK_SIZE 256U
40 uint32_t sp_top; // stack space top
41 uint32_t sp_limit; // stack space limit
42 uint32_t sp; // current stack pointer
45 static stack_info_t ProcessStackInfo [TZ_PROCESS_STACK_SLOTS];
46 static uint64_t ProcessStackMemory[TZ_PROCESS_STACK_SLOTS][TZ_PROCESS_STACK_SIZE/8U];
47 static uint32_t ProcessStackFreeSlot = 0xFFFFFFFFU;
50 /// Initialize secure context memory system
51 /// \return execution status (1: success, 0: error)
52 __attribute__((cmse_nonsecure_entry))
53 uint32_t TZ_InitContextSystem_S (void) {
56 if (__get_IPSR() == 0U) {
57 return 0U; // Thread Mode
60 for (n = 0U; n < TZ_PROCESS_STACK_SLOTS; n++) {
61 ProcessStackInfo[n].sp = 0U;
62 ProcessStackInfo[n].sp_limit = (uint32_t)&ProcessStackMemory[n];
63 ProcessStackInfo[n].sp_top = (uint32_t)&ProcessStackMemory[n] + TZ_PROCESS_STACK_SIZE;
64 *((uint32_t *)ProcessStackMemory[n]) = n + 1U;
66 *((uint32_t *)ProcessStackMemory[--n]) = 0xFFFFFFFFU;
68 ProcessStackFreeSlot = 0U;
70 // Default process stack pointer and stack limit
71 __set_PSPLIM((uint32_t)ProcessStackMemory);
72 __set_PSP ((uint32_t)ProcessStackMemory);
74 // Privileged Thread Mode using PSP
81 /// Allocate context memory for calling secure software modules in TrustZone
82 /// \param[in] module identifies software modules called from non-secure mode
83 /// \return value != 0 id TrustZone memory slot identifier
84 /// \return value 0 no memory available or internal error
85 __attribute__((cmse_nonsecure_entry))
86 TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module) {
89 (void)module; // Ignore (fixed Stack size)
91 if (__get_IPSR() == 0U) {
92 return 0U; // Thread Mode
95 if (ProcessStackFreeSlot == 0xFFFFFFFFU) {
96 return 0U; // No slot available
99 slot = ProcessStackFreeSlot;
100 ProcessStackFreeSlot = *((uint32_t *)ProcessStackMemory[slot]);
102 ProcessStackInfo[slot].sp = ProcessStackInfo[slot].sp_top;
108 /// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
109 /// \param[in] id TrustZone memory slot identifier
110 /// \return execution status (1: success, 0: error)
111 __attribute__((cmse_nonsecure_entry))
112 uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id) {
115 if (__get_IPSR() == 0U) {
116 return 0U; // Thread Mode
119 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
120 return 0U; // Invalid ID
125 if (ProcessStackInfo[slot].sp == 0U) {
126 return 0U; // Inactive slot
128 ProcessStackInfo[slot].sp = 0U;
130 *((uint32_t *)ProcessStackMemory[slot]) = ProcessStackFreeSlot;
131 ProcessStackFreeSlot = slot;
133 return 1U; // Success
137 /// Load secure context (called on RTOS thread context switch)
138 /// \param[in] id TrustZone memory slot identifier
139 /// \return execution status (1: success, 0: error)
140 __attribute__((cmse_nonsecure_entry))
141 uint32_t TZ_LoadContext_S (TZ_MemoryId_t id) {
144 if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
145 return 0U; // Thread Mode or using Main Stack for threads
148 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
149 return 0U; // Invalid ID
154 if (ProcessStackInfo[slot].sp == 0U) {
155 return 0U; // Inactive slot
158 // Setup process stack pointer and stack limit
159 __set_PSPLIM(ProcessStackInfo[slot].sp_limit);
160 __set_PSP (ProcessStackInfo[slot].sp);
162 return 1U; // Success
166 /// Store secure context (called on RTOS thread context switch)
167 /// \param[in] id TrustZone memory slot identifier
168 /// \return execution status (1: success, 0: error)
169 __attribute__((cmse_nonsecure_entry))
170 uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) {
174 if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) {
175 return 0U; // Thread Mode or using Main Stack for threads
178 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) {
179 return 0U; // Invalid ID
184 if (ProcessStackInfo[slot].sp == 0U) {
185 return 0U; // Inactive slot
189 if ((sp < ProcessStackInfo[slot].sp_limit) ||
190 (sp > ProcessStackInfo[slot].sp_top)) {
191 return 0U; // SP out of range
193 ProcessStackInfo[slot].sp = sp;
195 // Default process stack pointer and stack limit
196 __set_PSPLIM((uint32_t)ProcessStackMemory);
197 __set_PSP ((uint32_t)ProcessStackMemory);
199 return 1U; // Success