]> begriffs open source - cmsis-freertos/blob - Source/portable/ARMv8M/secure/context/secure_context.c
Updated pack to FreeRTOS 10.4.4
[cmsis-freertos] / Source / portable / ARMv8M / secure / context / secure_context.c
1 /*
2  * FreeRTOS Kernel V10.4.4
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Secure context includes. */
30 #include "secure_context.h"
31
32 /* Secure heap includes. */
33 #include "secure_heap.h"
34
35 /* Secure port macros. */
36 #include "secure_port_macros.h"
37
38 /**
39  * @brief CONTROL value for privileged tasks.
40  *
41  * Bit[0] - 0 --> Thread mode is privileged.
42  * Bit[1] - 1 --> Thread mode uses PSP.
43  */
44 #define securecontextCONTROL_VALUE_PRIVILEGED      0x02
45
46 /**
47  * @brief CONTROL value for un-privileged tasks.
48  *
49  * Bit[0] - 1 --> Thread mode is un-privileged.
50  * Bit[1] - 1 --> Thread mode uses PSP.
51  */
52 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03
53 /*-----------------------------------------------------------*/
54
55 /**
56  * @brief Structure to represent secure context.
57  *
58  * @note Since stack grows down, pucStackStart is the highest address while
59  * pucStackLimit is the first addess of the allocated memory.
60  */
61 typedef struct SecureContext
62 {
63     uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
64     uint8_t * pucStackLimit;          /**< Last location of the stack memory (PSPLIM). */
65     uint8_t * pucStackStart;          /**< First location of the stack memory. */
66 } SecureContext_t;
67 /*-----------------------------------------------------------*/
68
69 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
70 {
71     uint32_t ulIPSR;
72
73     /* Read the Interrupt Program Status Register (IPSR) value. */
74     secureportREAD_IPSR( ulIPSR );
75
76     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
77      * when the processor is running in the Thread Mode. */
78     if( ulIPSR != 0 )
79     {
80         /* No stack for thread mode until a task's context is loaded. */
81         secureportSET_PSPLIM( securecontextNO_STACK );
82         secureportSET_PSP( securecontextNO_STACK );
83
84         #if ( configENABLE_MPU == 1 )
85             {
86                 /* Configure thread mode to use PSP and to be unprivileged. */
87                 secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
88             }
89         #else /* configENABLE_MPU */
90             {
91                 /* Configure thread mode to use PSP and to be privileged.. */
92                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
93             }
94         #endif /* configENABLE_MPU */
95     }
96 }
97 /*-----------------------------------------------------------*/
98
99 #if ( configENABLE_MPU == 1 )
100     secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
101                                                                                        uint32_t ulIsTaskPrivileged )
102 #else /* configENABLE_MPU */
103     secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
104 #endif /* configENABLE_MPU */
105 {
106     uint8_t * pucStackMemory = NULL;
107     uint32_t ulIPSR;
108     SecureContextHandle_t xSecureContextHandle = NULL;
109
110     #if ( configENABLE_MPU == 1 )
111         uint32_t * pulCurrentStackPointer = NULL;
112     #endif /* configENABLE_MPU */
113
114     /* Read the Interrupt Program Status Register (IPSR) value. */
115     secureportREAD_IPSR( ulIPSR );
116
117     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
118      * when the processor is running in the Thread Mode. */
119     if( ulIPSR != 0 )
120     {
121         /* Allocate the context structure. */
122         xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
123
124         if( xSecureContextHandle != NULL )
125         {
126             /* Allocate the stack space. */
127             pucStackMemory = pvPortMalloc( ulSecureStackSize );
128
129             if( pucStackMemory != NULL )
130             {
131                 /* Since stack grows down, the starting point will be the last
132                  * location. Note that this location is next to the last
133                  * allocated byte because the hardware decrements the stack
134                  * pointer before writing i.e. if stack pointer is 0x2, a push
135                  * operation will decrement the stack pointer to 0x1 and then
136                  * write at 0x1. */
137                 xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
138
139                 /* The stack cannot go beyond this location. This value is
140                  * programmed in the PSPLIM register on context switch.*/
141                 xSecureContextHandle->pucStackLimit = pucStackMemory;
142
143                 #if ( configENABLE_MPU == 1 )
144                     {
145                         /* Store the correct CONTROL value for the task on the stack.
146                          * This value is programmed in the CONTROL register on
147                          * context switch. */
148                         pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
149                         pulCurrentStackPointer--;
150
151                         if( ulIsTaskPrivileged )
152                         {
153                             *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
154                         }
155                         else
156                         {
157                             *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
158                         }
159
160                         /* Store the current stack pointer. This value is programmed in
161                          * the PSP register on context switch. */
162                         xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
163                     }
164                 #else /* configENABLE_MPU */
165                     {
166                         /* Current SP is set to the starting of the stack. This
167                          * value programmed in the PSP register on context switch. */
168                         xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
169                     }
170                 #endif /* configENABLE_MPU */
171             }
172             else
173             {
174                 /* Free the context to avoid memory leak and make sure to return
175                  * NULL to indicate failure. */
176                 vPortFree( xSecureContextHandle );
177                 xSecureContextHandle = NULL;
178             }
179         }
180     }
181
182     return xSecureContextHandle;
183 }
184 /*-----------------------------------------------------------*/
185
186 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
187 {
188     uint32_t ulIPSR;
189
190     /* Read the Interrupt Program Status Register (IPSR) value. */
191     secureportREAD_IPSR( ulIPSR );
192
193     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero
194      * when the processor is running in the Thread Mode. */
195     if( ulIPSR != 0 )
196     {
197         /* Ensure that valid parameters are passed. */
198         secureportASSERT( xSecureContextHandle != NULL );
199
200         /* Free the stack space. */
201         vPortFree( xSecureContextHandle->pucStackLimit );
202
203         /* Free the context itself. */
204         vPortFree( xSecureContextHandle );
205     }
206 }
207 /*-----------------------------------------------------------*/