1 /****************************************************************************** 2 * @file tz_context.c 3 * @brief Context Management for Armv8-M TrustZone - Sample implementation 4 * @version V1.1.1 5 * @date 10. January 2018 6 ******************************************************************************/ 7 /* 8 * Copyright (c) 2016-2018 Arm Limited. All rights reserved. 9 * 10 * SPDX-License-Identifier: Apache-2.0 11 * 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 15 * 16 * www.apache.org/licenses/LICENSE-2.0 17 * 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. 23 */ 24 25 #include "RTE_Components.h" 26 #include CMSIS_device_header 27 #include "tz_context.h" 28 29 /// Number of process slots (threads may call secure library code) 30 #ifndef TZ_PROCESS_STACK_SLOTS 31 #define TZ_PROCESS_STACK_SLOTS 8U 32 #endif 33 34 /// Stack size of the secure library code 35 #ifndef TZ_PROCESS_STACK_SIZE 36 #define TZ_PROCESS_STACK_SIZE 256U 37 #endif 38 39 typedef struct { 40 uint32_t sp_top; // stack space top 41 uint32_t sp_limit; // stack space limit 42 uint32_t sp; // current stack pointer 43 } stack_info_t; 44 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; 48 49 50 /// Initialize secure context memory system 51 /// \return execution status (1: success, 0: error) 52 __attribute__((cmse_nonsecure_entry)) TZ_InitContextSystem_S(void)53uint32_t TZ_InitContextSystem_S (void) { 54 uint32_t n; 55 56 if (__get_IPSR() == 0U) { 57 return 0U; // Thread Mode 58 } 59 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; 65 } 66 *((uint32_t *)ProcessStackMemory[--n]) = 0xFFFFFFFFU; 67 68 ProcessStackFreeSlot = 0U; 69 70 // Default process stack pointer and stack limit 71 __set_PSPLIM((uint32_t)ProcessStackMemory); 72 __set_PSP ((uint32_t)ProcessStackMemory); 73 74 // Privileged Thread Mode using PSP 75 __set_CONTROL(0x02U); 76 77 return 1U; // Success 78 } 79 80 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)) TZ_AllocModuleContext_S(TZ_ModuleId_t module)86TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module) { 87 uint32_t slot; 88 89 (void)module; // Ignore (fixed Stack size) 90 91 if (__get_IPSR() == 0U) { 92 return 0U; // Thread Mode 93 } 94 95 if (ProcessStackFreeSlot == 0xFFFFFFFFU) { 96 return 0U; // No slot available 97 } 98 99 slot = ProcessStackFreeSlot; 100 ProcessStackFreeSlot = *((uint32_t *)ProcessStackMemory[slot]); 101 102 ProcessStackInfo[slot].sp = ProcessStackInfo[slot].sp_top; 103 104 return (slot + 1U); 105 } 106 107 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)) TZ_FreeModuleContext_S(TZ_MemoryId_t id)112uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id) { 113 uint32_t slot; 114 115 if (__get_IPSR() == 0U) { 116 return 0U; // Thread Mode 117 } 118 119 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) { 120 return 0U; // Invalid ID 121 } 122 123 slot = id - 1U; 124 125 if (ProcessStackInfo[slot].sp == 0U) { 126 return 0U; // Inactive slot 127 } 128 ProcessStackInfo[slot].sp = 0U; 129 130 *((uint32_t *)ProcessStackMemory[slot]) = ProcessStackFreeSlot; 131 ProcessStackFreeSlot = slot; 132 133 return 1U; // Success 134 } 135 136 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)) TZ_LoadContext_S(TZ_MemoryId_t id)141uint32_t TZ_LoadContext_S (TZ_MemoryId_t id) { 142 uint32_t slot; 143 144 if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) { 145 return 0U; // Thread Mode or using Main Stack for threads 146 } 147 148 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) { 149 return 0U; // Invalid ID 150 } 151 152 slot = id - 1U; 153 154 if (ProcessStackInfo[slot].sp == 0U) { 155 return 0U; // Inactive slot 156 } 157 158 // Setup process stack pointer and stack limit 159 __set_PSPLIM(ProcessStackInfo[slot].sp_limit); 160 __set_PSP (ProcessStackInfo[slot].sp); 161 162 return 1U; // Success 163 } 164 165 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)) TZ_StoreContext_S(TZ_MemoryId_t id)170uint32_t TZ_StoreContext_S (TZ_MemoryId_t id) { 171 uint32_t slot; 172 uint32_t sp; 173 174 if ((__get_IPSR() == 0U) || ((__get_CONTROL() & 2U) == 0U)) { 175 return 0U; // Thread Mode or using Main Stack for threads 176 } 177 178 if ((id == 0U) || (id > TZ_PROCESS_STACK_SLOTS)) { 179 return 0U; // Invalid ID 180 } 181 182 slot = id - 1U; 183 184 if (ProcessStackInfo[slot].sp == 0U) { 185 return 0U; // Inactive slot 186 } 187 188 sp = __get_PSP(); 189 if ((sp < ProcessStackInfo[slot].sp_limit) || 190 (sp > ProcessStackInfo[slot].sp_top)) { 191 return 0U; // SP out of range 192 } 193 ProcessStackInfo[slot].sp = sp; 194 195 // Default process stack pointer and stack limit 196 __set_PSPLIM((uint32_t)ProcessStackMemory); 197 __set_PSP ((uint32_t)ProcessStackMemory); 198 199 return 1U; // Success 200 } 201