1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** ThreadX Component */
17 /** */
18 /** Thread */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 #include "tx_api.h"
25
26 /* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined,
27 no secure stack functionality is needed. */
28 #if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)
29
30 #define TX_SOURCE_CODE
31
32 #include <cmsis_compiler.h> /* For intrinsic functions. */
33 #include "tx_secure_interface.h" /* Interface for NS code. */
34
35 /* Minimum size of secure stack. */
36 #ifndef TX_THREAD_SECURE_STACK_MINIMUM
37 #define TX_THREAD_SECURE_STACK_MINIMUM 256
38 #endif
39 /* Maximum size of secure stack. */
40 #ifndef TX_THREAD_SECURE_STACK_MAXIMUM
41 #define TX_THREAD_SECURE_STACK_MAXIMUM 1024
42 #endif
43
44 /* 8 bytes added to stack size to "seal" stack. */
45 #define TX_THREAD_STACK_SEAL_SIZE 8
46 #define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5
47
48 /* max number of Secure context */
49 #ifndef TX_MAX_SECURE_CONTEXTS
50 #define TX_MAX_SECURE_CONTEXTS 32
51 #endif
52 #define TX_INVALID_SECURE_CONTEXT_IDX (-1)
53
54 /* Secure stack info struct to hold stack start, stack limit,
55 current stack pointer, and pointer to owning thread.
56 This will be allocated for each thread with a secure stack. */
57 typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT
58 {
59 VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */
60 VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */
61 VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */
62 TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */
63 INT tx_next_free_index; /* Next free index of free secure context */
64 } TX_THREAD_SECURE_STACK_INFO;
65
66 /* Static secure contexts */
67 static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS];
68 /* Head of free secure context */
69 static INT tx_head_free_index = 0U;
70
71
72
73 /**************************************************************************/
74 /* */
75 /* FUNCTION RELEASE */
76 /* */
77 /* _tx_thread_secure_mode_stack_initialize Cortex-Mxx/IAR */
78 /* 6.1.10 */
79 /* AUTHOR */
80 /* */
81 /* Scott Larson, Microsoft Corporation */
82 /* */
83 /* DESCRIPTION */
84 /* */
85 /* This function initializes secure mode to use PSP stack. */
86 /* */
87 /* INPUT */
88 /* */
89 /* None */
90 /* */
91 /* OUTPUT */
92 /* */
93 /* status */
94 /* */
95 /* CALLS */
96 /* */
97 /* __get_CONTROL Intrinsic to get CONTROL */
98 /* __set_CONTROL Intrinsic to set CONTROL */
99 /* __set_PSPLIM Intrinsic to set PSP limit */
100 /* __set_PSP Intrinsic to set PSP */
101 /* */
102 /* CALLED BY */
103 /* */
104 /* _tx_initialize_kernel_enter */
105 /* */
106 /* RELEASE HISTORY */
107 /* */
108 /* DATE NAME DESCRIPTION */
109 /* */
110 /* 09-30-2020 Scott Larson Initial Version 6.1 */
111 /* 10-16-2020 Scott Larson Modified comment(s), */
112 /* resulting in version 6.1.1 */
113 /* 06-02-2021 Scott Larson Change name, execute in */
114 /* handler mode, */
115 /* resulting in version 6.1.7 */
116 /* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
117 /* secure stack allocation, */
118 /* resulting in version 6.1.10 */
119 /* */
120 /**************************************************************************/
121 __attribute__((cmse_nonsecure_entry))
_tx_thread_secure_mode_stack_initialize(void)122 UINT _tx_thread_secure_mode_stack_initialize(void)
123 {
124 UINT status;
125 INT index;
126
127 /* Make sure function is called from interrupt (threads should not call). */
128 if (__get_IPSR() == 0)
129 {
130 status = TX_CALLER_ERROR;
131 }
132 else
133 {
134 /* Set secure mode to use PSP. */
135 __set_CONTROL(__get_CONTROL() | 2);
136
137 /* Set process stack pointer and stack limit to 0 to throw exception when a thread
138 without a secure stack calls a secure function that tries to use secure stack. */
139 __set_PSPLIM(0);
140 __set_PSP(0);
141
142 for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++)
143 {
144
145 /* Check last index and mark next free to invalid index */
146 if(index == (TX_MAX_SECURE_CONTEXTS - 1))
147 {
148 tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
149 }
150 else
151 {
152 tx_thread_secure_context[index].tx_next_free_index = index + 1;
153 }
154 }
155
156 status = TX_SUCCESS;
157 }
158 return status;
159 }
160
161
162
163 /**************************************************************************/
164 /* */
165 /* FUNCTION RELEASE */
166 /* */
167 /* _tx_thread_secure_mode_stack_allocate Cortex-Mxx/IAR */
168 /* 6.1.11a */
169 /* AUTHOR */
170 /* */
171 /* Scott Larson, Microsoft Corporation */
172 /* */
173 /* DESCRIPTION */
174 /* */
175 /* This function allocates a thread's secure stack. */
176 /* */
177 /* INPUT */
178 /* */
179 /* thread_ptr Thread control block pointer */
180 /* stack_size Size of stack to allocates */
181 /* */
182 /* OUTPUT */
183 /* */
184 /* TX_THREAD_ERROR Invalid thread pointer */
185 /* TX_SIZE_ERROR Invalid stack size */
186 /* TX_CALLER_ERROR Invalid caller of function */
187 /* status Actual completion status */
188 /* */
189 /* CALLS */
190 /* */
191 /* __get_IPSR Intrinsic to get IPSR */
192 /* malloc Compiler's malloc function */
193 /* __set_PSPLIM Intrinsic to set PSP limit */
194 /* __set_PSP Intrinsic to set PSP */
195 /* __TZ_get_PSPLIM_NS Intrinsic to get NS PSP */
196 /* */
197 /* CALLED BY */
198 /* */
199 /* SVC Handler */
200 /* */
201 /* RELEASE HISTORY */
202 /* */
203 /* DATE NAME DESCRIPTION */
204 /* */
205 /* 09-30-2020 Scott Larson Initial Version 6.1 */
206 /* 10-16-2020 Scott Larson Modified comment(s), */
207 /* added stack sealing, */
208 /* resulting in version 6.1.1 */
209 /* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
210 /* secure stack allocation, */
211 /* resulting in version 6.1.10 */
212 /* 05-02-2022 Scott Larson Modified comment(s), added */
213 /* TX_INTERRUPT_SAVE_AREA, */
214 /* resulting in version 6.1.11a*/
215 /* */
216 /**************************************************************************/
217 __attribute__((cmse_nonsecure_entry))
_tx_thread_secure_mode_stack_allocate(TX_THREAD * thread_ptr,ULONG stack_size)218 UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size)
219 {
220 TX_INTERRUPT_SAVE_AREA
221 UINT status;
222 TX_THREAD_SECURE_STACK_INFO *info_ptr;
223 UCHAR *stack_mem;
224 INT secure_context_index;
225
226 status = TX_SUCCESS;
227
228 /* Make sure function is called from interrupt (threads should not call). */
229 if (__get_IPSR() == 0)
230 {
231 status = TX_CALLER_ERROR;
232 }
233 else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM)
234 {
235 status = TX_SIZE_ERROR;
236 }
237
238 /* Check if thread already has secure stack allocated. */
239 else if (thread_ptr -> tx_thread_secure_stack_context != 0)
240 {
241 status = TX_THREAD_ERROR;
242 }
243
244 else
245 {
246 TX_DISABLE
247
248 /* Allocate free index for secure stack info. */
249 if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX)
250 {
251 secure_context_index = tx_head_free_index;
252 tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index;
253 tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX;
254 }
255 else
256 {
257 secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX;
258 }
259
260 TX_RESTORE
261
262 if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX)
263 {
264 info_ptr = &tx_thread_secure_context[secure_context_index];
265
266 /* If stack info allocated, allocate a stack & seal. */
267 stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE);
268
269 if(stack_mem != TX_NULL)
270 {
271 /* Secure stack has been allocated, save in the stack info struct. */
272 info_ptr -> tx_thread_secure_stack_limit = stack_mem;
273 info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size;
274 info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start;
275 info_ptr -> tx_thread_ptr = thread_ptr;
276
277 /* Seal bottom of stack. */
278 *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE;
279
280 /* Save secure context id (i.e non-zero base index) in thread. */
281 thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1);
282
283 /* Check if this thread is running by looking at its stack start and PSPLIM_NS */
284 if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == __TZ_get_PSPLIM_NS())
285 {
286 /* If this thread is running, set Secure PSP and PSPLIM. */
287 __set_PSPLIM((ULONG)(info_ptr -> tx_thread_secure_stack_limit));
288 __set_PSP((ULONG)(info_ptr -> tx_thread_secure_stack_ptr));
289 }
290 }
291
292 else
293 {
294 TX_DISABLE
295
296 /* Stack not allocated, free the info struct. */
297 tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
298 tx_head_free_index = secure_context_index;
299 TX_RESTORE
300
301 status = TX_NO_MEMORY;
302 }
303 }
304
305 else
306 {
307 status = TX_NO_MEMORY;
308 }
309 }
310
311 return(status);
312 }
313
314
315
316 /**************************************************************************/
317 /* */
318 /* FUNCTION RELEASE */
319 /* */
320 /* _tx_thread_secure_mode_stack_free Cortex-Mxx/IAR */
321 /* 6.1.11a */
322 /* AUTHOR */
323 /* */
324 /* Scott Larson, Microsoft Corporation */
325 /* */
326 /* DESCRIPTION */
327 /* */
328 /* This function frees a thread's secure stack. */
329 /* */
330 /* INPUT */
331 /* */
332 /* thread_ptr Thread control block pointer */
333 /* */
334 /* OUTPUT */
335 /* */
336 /* TX_THREAD_ERROR Invalid thread pointer */
337 /* TX_CALLER_ERROR Invalid caller of function */
338 /* status Actual completion status */
339 /* */
340 /* CALLS */
341 /* */
342 /* __get_IPSR Intrinsic to get IPSR */
343 /* free Compiler's free() function */
344 /* */
345 /* CALLED BY */
346 /* */
347 /* SVC Handler */
348 /* */
349 /* RELEASE HISTORY */
350 /* */
351 /* DATE NAME DESCRIPTION */
352 /* */
353 /* 09-30-2020 Scott Larson Initial Version 6.1 */
354 /* 10-16-2020 Scott Larson Modified comment(s), */
355 /* resulting in version 6.1.1 */
356 /* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
357 /* secure stack allocation, */
358 /* resulting in version 6.1.10 */
359 /* 05-02-2022 Scott Larson Modified comment(s), added */
360 /* TX_INTERRUPT_SAVE_AREA, */
361 /* resulting in version 6.1.11a*/
362 /* */
363 /**************************************************************************/
364 __attribute__((cmse_nonsecure_entry))
_tx_thread_secure_mode_stack_free(TX_THREAD * thread_ptr)365 UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr)
366 {
367 TX_INTERRUPT_SAVE_AREA
368 UINT status;
369 TX_THREAD_SECURE_STACK_INFO *info_ptr;
370 INT secure_context_index;
371
372 status = TX_SUCCESS;
373
374 /* Pickup stack info id from thread. */
375 secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
376
377 /* Make sure function is called from interrupt (threads should not call). */
378 if (__get_IPSR() == 0)
379 {
380 status = TX_CALLER_ERROR;
381 }
382
383 /* Check if secure context index is in valid range. */
384 else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
385 {
386 status = TX_THREAD_ERROR;
387 }
388 else
389 {
390
391 /* Pickup stack info from static array of secure contexts. */
392 info_ptr = &tx_thread_secure_context[secure_context_index];
393
394 /* Check that this secure context is for this thread. */
395 if (info_ptr -> tx_thread_ptr != thread_ptr)
396 {
397 status = TX_THREAD_ERROR;
398 }
399
400 else
401 {
402
403 /* Free secure stack. */
404 free(info_ptr -> tx_thread_secure_stack_limit);
405
406 TX_DISABLE
407
408 /* Free info struct. */
409 tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index;
410 tx_head_free_index = secure_context_index;
411 TX_RESTORE
412
413 /* Clear secure context from thread. */
414 thread_ptr -> tx_thread_secure_stack_context = 0;
415 }
416 }
417
418 return(status);
419 }
420
421
422
423 /**************************************************************************/
424 /* */
425 /* FUNCTION RELEASE */
426 /* */
427 /* _tx_thread_secure_stack_context_save Cortex-Mxx/IAR */
428 /* 6.1.10 */
429 /* AUTHOR */
430 /* */
431 /* Scott Larson, Microsoft Corporation */
432 /* */
433 /* DESCRIPTION */
434 /* */
435 /* This function saves context of the secure stack. */
436 /* */
437 /* INPUT */
438 /* */
439 /* thread_ptr Thread control block pointer */
440 /* */
441 /* OUTPUT */
442 /* */
443 /* None */
444 /* */
445 /* CALLS */
446 /* */
447 /* __get_IPSR Intrinsic to get IPSR */
448 /* __get_PSP Intrinsic to get PSP */
449 /* __set_PSPLIM Intrinsic to set PSP limit */
450 /* __set_PSP Intrinsic to set PSP */
451 /* */
452 /* CALLED BY */
453 /* */
454 /* PendSV Handler */
455 /* */
456 /* RELEASE HISTORY */
457 /* */
458 /* DATE NAME DESCRIPTION */
459 /* */
460 /* 09-30-2020 Scott Larson Initial Version 6.1 */
461 /* 10-16-2020 Scott Larson Modified comment(s), */
462 /* resulting in version 6.1.1 */
463 /* 06-02-2021 Scott Larson Fix stack pointer save, */
464 /* resulting in version 6.1.7 */
465 /* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
466 /* secure stack allocation, */
467 /* resulting in version 6.1.10 */
468 /* */
469 /**************************************************************************/
470 __attribute__((cmse_nonsecure_entry))
_tx_thread_secure_stack_context_save(TX_THREAD * thread_ptr)471 void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr)
472 {
473 TX_THREAD_SECURE_STACK_INFO *info_ptr;
474 ULONG sp;
475 INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
476
477 /* This function should be called from scheduler only. */
478 if (__get_IPSR() == 0)
479 {
480 return;
481 }
482
483 /* Check if secure context index is in valid range. */
484 else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
485 {
486 return;
487 }
488
489 /* Pickup the secure context pointer. */
490 info_ptr = &tx_thread_secure_context[secure_context_index];
491
492 /* Check that this secure context is for this thread. */
493 if (info_ptr -> tx_thread_ptr != thread_ptr)
494 {
495 return;
496 }
497
498 /* Check that stack pointer is in range */
499 sp = __get_PSP();
500 if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) ||
501 (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start))
502 {
503 return;
504 }
505
506 /* Save stack pointer. */
507 info_ptr -> tx_thread_secure_stack_ptr = (VOID *) sp;
508
509 /* Set process stack pointer and stack limit to 0 to throw exception when a thread
510 without a secure stack calls a secure function that tries to use secure stack. */
511 __set_PSPLIM(0);
512 __set_PSP(0);
513
514 return;
515 }
516
517
518
519 /**************************************************************************/
520 /* */
521 /* FUNCTION RELEASE */
522 /* */
523 /* _tx_thread_secure_stack_context_restore Cortex-Mxx/IAR */
524 /* 6.1.10 */
525 /* AUTHOR */
526 /* */
527 /* Scott Larson, Microsoft Corporation */
528 /* */
529 /* DESCRIPTION */
530 /* */
531 /* This function restores context of the secure stack. */
532 /* */
533 /* INPUT */
534 /* */
535 /* thread_ptr Thread control block pointer */
536 /* */
537 /* OUTPUT */
538 /* */
539 /* None */
540 /* */
541 /* CALLS */
542 /* */
543 /* __get_IPSR Intrinsic to get IPSR */
544 /* __set_PSPLIM Intrinsic to set PSP limit */
545 /* __set_PSP Intrinsic to set PSP */
546 /* */
547 /* CALLED BY */
548 /* */
549 /* PendSV Handler */
550 /* */
551 /* RELEASE HISTORY */
552 /* */
553 /* DATE NAME DESCRIPTION */
554 /* */
555 /* 09-30-2020 Scott Larson Initial Version 6.1 */
556 /* 10-16-2020 Scott Larson Modified comment(s), */
557 /* resulting in version 6.1.1 */
558 /* 01-31-2022 Himanshu Gupta Modified comments(s), updated */
559 /* secure stack allocation, */
560 /* resulting in version 6.1.10 */
561 /* */
562 /**************************************************************************/
563 __attribute__((cmse_nonsecure_entry))
_tx_thread_secure_stack_context_restore(TX_THREAD * thread_ptr)564 void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr)
565 {
566 TX_THREAD_SECURE_STACK_INFO *info_ptr;
567 INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1;
568
569 /* This function should be called from scheduler only. */
570 if (__get_IPSR() == 0)
571 {
572 return;
573 }
574
575 /* Check if secure context index is in valid range. */
576 else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS)
577 {
578 return;
579 }
580
581 /* Pickup the secure context pointer. */
582 info_ptr = &tx_thread_secure_context[secure_context_index];
583
584 /* Check that this secure context is for this thread. */
585 if (info_ptr -> tx_thread_ptr != thread_ptr)
586 {
587 return;
588 }
589
590 /* Set stack pointer and limit. */
591 __set_PSPLIM((ULONG)info_ptr -> tx_thread_secure_stack_limit);
592 __set_PSP ((ULONG)info_ptr -> tx_thread_secure_stack_ptr);
593
594 return;
595 }
596
597 #endif
598