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