]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/ARMv8M/secure/context/secure_context.c
First Official Release of ARMV8M Support. This release removes Pre-Release from all...
[freertos] / FreeRTOS / Source / portable / ARMv8M / secure / context / secure_context.c
diff --git a/FreeRTOS/Source/portable/ARMv8M/secure/context/secure_context.c b/FreeRTOS/Source/portable/ARMv8M/secure/context/secure_context.c
new file mode 100644 (file)
index 0000000..b1a8316
--- /dev/null
@@ -0,0 +1,204 @@
+/*\r
+ * FreeRTOS Kernel V10.2.0\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* Secure context includes. */\r
+#include "secure_context.h"\r
+\r
+/* Secure heap includes. */\r
+#include "secure_heap.h"\r
+\r
+/* Secure port macros. */\r
+#include "secure_port_macros.h"\r
+\r
+/**\r
+ * @brief CONTROL value for privileged tasks.\r
+ *\r
+ * Bit[0] - 0 --> Thread mode is privileged.\r
+ * Bit[1] - 1 --> Thread mode uses PSP.\r
+ */\r
+#define securecontextCONTROL_VALUE_PRIVILEGED       0x02\r
+\r
+/**\r
+ * @brief CONTROL value for un-privileged tasks.\r
+ *\r
+ * Bit[0] - 1 --> Thread mode is un-privileged.\r
+ * Bit[1] - 1 --> Thread mode uses PSP.\r
+ */\r
+#define securecontextCONTROL_VALUE_UNPRIVILEGED     0x03\r
+/*-----------------------------------------------------------*/\r
+\r
+/**\r
+ * @brief Structure to represent secure context.\r
+ *\r
+ * @note Since stack grows down, pucStackStart is the highest address while\r
+ * pucStackLimit is the first addess of the allocated memory.\r
+ */\r
+typedef struct SecureContext\r
+{\r
+    uint8_t *pucCurrentStackPointer;    /**< Current value of stack pointer (PSP). */\r
+    uint8_t *pucStackLimit;             /**< Last location of the stack memory (PSPLIM). */\r
+    uint8_t *pucStackStart;             /**< First location of the stack memory. */\r
+} SecureContext_t;\r
+/*-----------------------------------------------------------*/\r
+\r
+secureportNON_SECURE_CALLABLE void SecureContext_Init( void )\r
+{\r
+    uint32_t ulIPSR;\r
+\r
+    /* Read the Interrupt Program Status Register (IPSR) value. */\r
+    secureportREAD_IPSR( ulIPSR );\r
+\r
+    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
+     * when the processor is running in the Thread Mode. */\r
+    if( ulIPSR != 0 )\r
+    {\r
+        /* No stack for thread mode until a task's context is loaded. */\r
+        secureportSET_PSPLIM( securecontextNO_STACK );\r
+        secureportSET_PSP( securecontextNO_STACK );\r
+\r
+        #if( configENABLE_MPU == 1 )\r
+        {\r
+            /* Configure thread mode to use PSP and to be unprivileged. */\r
+            secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );\r
+        }\r
+        #else /* configENABLE_MPU */\r
+        {\r
+            /* Configure thread mode to use PSP and to be privileged.. */\r
+            secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );\r
+        }\r
+        #endif /* configENABLE_MPU */\r
+    }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configENABLE_MPU == 1 )\r
+    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )\r
+#else /* configENABLE_MPU */\r
+    secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )\r
+#endif /* configENABLE_MPU */\r
+{\r
+    uint8_t *pucStackMemory = NULL;\r
+    uint32_t ulIPSR;\r
+    SecureContextHandle_t xSecureContextHandle = NULL;\r
+    #if( configENABLE_MPU == 1 )\r
+        uint32_t *pulCurrentStackPointer = NULL;\r
+    #endif /* configENABLE_MPU */\r
+\r
+    /* Read the Interrupt Program Status Register (IPSR) value. */\r
+    secureportREAD_IPSR( ulIPSR );\r
+\r
+    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
+     * when the processor is running in the Thread Mode. */\r
+    if( ulIPSR != 0 )\r
+    {\r
+        /* Allocate the context structure. */\r
+        xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );\r
+\r
+        if( xSecureContextHandle != NULL )\r
+        {\r
+            /* Allocate the stack space. */\r
+            pucStackMemory = pvPortMalloc( ulSecureStackSize );\r
+\r
+            if( pucStackMemory != NULL )\r
+            {\r
+                /* Since stack grows down, the starting point will be the last\r
+                 * location. Note that this location is next to the last\r
+                 * allocated byte because the hardware decrements the stack\r
+                 * pointer before writing i.e. if stack pointer is 0x2, a push\r
+                 * operation will decrement the stack pointer to 0x1 and then\r
+                 * write at 0x1. */\r
+                xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;\r
+\r
+                /* The stack cannot go beyond this location. This value is\r
+                 * programmed in the PSPLIM register on context switch.*/\r
+                xSecureContextHandle->pucStackLimit = pucStackMemory;\r
+\r
+                #if( configENABLE_MPU == 1 )\r
+                {\r
+                    /* Store the correct CONTROL value for the task on the stack.\r
+                     * This value is programmed in the CONTROL register on\r
+                     * context switch. */\r
+                    pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;\r
+                    pulCurrentStackPointer--;\r
+                    if( ulIsTaskPrivileged )\r
+                    {\r
+                        *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;\r
+                    }\r
+                    else\r
+                    {\r
+                        *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;\r
+                    }\r
+\r
+                    /* Store the current stack pointer. This value is programmed in\r
+                     * the PSP register on context switch. */\r
+                    xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;\r
+                }\r
+                #else /* configENABLE_MPU */\r
+                {\r
+                    /* Current SP is set to the starting of the stack. This\r
+                     * value programmed in the PSP register on context switch. */\r
+                    xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;\r
+\r
+                }\r
+                #endif /* configENABLE_MPU */\r
+            }\r
+            else\r
+            {\r
+                /* Free the context to avoid memory leak and make sure to return\r
+                 * NULL to indicate failure. */\r
+                vPortFree( xSecureContextHandle );\r
+                xSecureContextHandle = NULL;\r
+            }\r
+        }\r
+    }\r
+\r
+    return xSecureContextHandle;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )\r
+{\r
+    uint32_t ulIPSR;\r
+\r
+    /* Read the Interrupt Program Status Register (IPSR) value. */\r
+    secureportREAD_IPSR( ulIPSR );\r
+\r
+    /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
+     * when the processor is running in the Thread Mode. */\r
+    if( ulIPSR != 0 )\r
+    {\r
+        /* Ensure that valid parameters are passed. */\r
+        secureportASSERT( xSecureContextHandle != NULL );\r
+\r
+        /* Free the stack space. */\r
+        vPortFree( xSecureContextHandle->pucStackLimit );\r
+\r
+        /* Free the context itself. */\r
+        vPortFree( xSecureContextHandle );\r
+    }\r
+}\r
+/*-----------------------------------------------------------*/\r