Implement MicroBlazeV9 stack protection (#523)
* Implement stack protection for MicroBlaze (without MPU wrappers)
diff --git a/portable/GCC/MicroBlazeV9/port.c b/portable/GCC/MicroBlazeV9/port.c
index 8e70db9..5f0e261 100644
--- a/portable/GCC/MicroBlazeV9/port.c
+++ b/portable/GCC/MicroBlazeV9/port.c
@@ -105,7 +105,11 @@
*
* See the portable.h header file.
*/
+#if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters )
+#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+#endif
{
extern void *_SDA2_BASE_, *_SDA_BASE_;
const uint32_t ulR2 = ( uint32_t ) &_SDA2_BASE_;
@@ -122,6 +126,14 @@
*pxTopOfStack = ( StackType_t ) 0x00000000;
pxTopOfStack--;
+ #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
+ /* Store the stack limits. */
+ *pxTopOfStack = (StackType_t) (pxTopOfStack + 3);
+ pxTopOfStack--;
+ *pxTopOfStack = (StackType_t) pxEndOfStack;
+ pxTopOfStack--;
+ #endif
+
#if( XPAR_MICROBLAZE_USE_FPU != 0 )
/* The FSR value placed in the initial task context is just 0. */
*pxTopOfStack = portINITIAL_FSR;
diff --git a/portable/GCC/MicroBlazeV9/portasm.S b/portable/GCC/MicroBlazeV9/portasm.S
index 6bea21f..937b680 100644
--- a/portable/GCC/MicroBlazeV9/portasm.S
+++ b/portable/GCC/MicroBlazeV9/portasm.S
@@ -33,16 +33,6 @@
#include "microblaze_exceptions_g.h"
#include "xparameters.h"
-/* The context is oversized to allow functions called from the ISR to write
-back into the caller stack. */
-#if( XPAR_MICROBLAZE_USE_FPU != 0 )
- #define portCONTEXT_SIZE 136
- #define portMINUS_CONTEXT_SIZE -136
-#else
- #define portCONTEXT_SIZE 132
- #define portMINUS_CONTEXT_SIZE -132
-#endif
-
/* Offsets from the stack pointer at which saved registers are placed. */
#define portR31_OFFSET 4
#define portR30_OFFSET 8
@@ -76,7 +66,31 @@
#define portR2_OFFSET 120
#define portCRITICAL_NESTING_OFFSET 124
#define portMSR_OFFSET 128
-#define portFSR_OFFSET 132
+
+#if( XPAR_MICROBLAZE_USE_FPU != 0 )
+ #define portFSR_OFFSET 132
+ #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ #define portSLR_OFFSET 136
+ #define portSHR_OFFSET 140
+
+ #define portCONTEXT_SIZE 144
+ #define portMINUS_CONTEXT_SIZE -144
+ #else
+ #define portCONTEXT_SIZE 136
+ #define portMINUS_CONTEXT_SIZE -136
+ #endif
+#else
+ #if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ #define portSLR_OFFSET 132
+ #define portSHR_OFFSET 136
+
+ #define portCONTEXT_SIZE 140
+ #define portMINUS_CONTEXT_SIZE -140
+ #else
+ #define portCONTEXT_SIZE 132
+ #define portMINUS_CONTEXT_SIZE -132
+ #endif
+#endif
.extern pxCurrentTCB
.extern XIntc_DeviceInterruptHandler
@@ -144,6 +158,14 @@
swi r18, r1, portFSR_OFFSET
#endif
+#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ /* Save the stack limits */
+ mfs r18, rslr
+ swi r18, r1, portSLR_OFFSET
+ mfs r18, rshr
+ swi r18, r1, portSHR_OFFSET
+#endif
+
/* Save the top of stack value to the TCB. */
lwi r3, r0, pxCurrentTCB
sw r1, r0, r3
@@ -156,6 +178,17 @@
lwi r18, r0, pxCurrentTCB
lw r1, r0, r18
+#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ /* Restore the stack limits -- must not load from r1 (Stack Pointer)
+ because if the address of load or store instruction is out of range,
+ it will trigger Stack Protection Violation exception. */
+ or r18, r0, r1
+ lwi r12, r18, portSLR_OFFSET
+ mts rslr, r12
+ lwi r12, r18, portSHR_OFFSET
+ mts rshr, r12
+#endif
+
/* Restore the general registers. */
lwi r31, r1, portR31_OFFSET
lwi r30, r1, portR30_OFFSET
@@ -252,6 +285,13 @@
/* Switch to the ISR stack. */
lwi r1, r0, pulISRStack
+#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ ori r18, r0, _stack_end
+ mts rslr, r18
+ ori r18, r0, _stack
+ mts rshr, r18
+#endif
+
/* The parameter to the interrupt handler. */
ori r5, r0, configINTERRUPT_CONTROLLER_TO_USE
@@ -296,6 +336,13 @@
/* Switch to use the ISR stack. */
lwi r1, r0, pulISRStack
+#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+ ori r18, r0, _stack_end
+ mts rslr, r18
+ ori r18, r0, _stack
+ mts rshr, r18
+#endif
+
/* Select the next task to execute. */
bralid r15, vTaskSwitchContext
or r0, r0, r0
diff --git a/portable/GCC/MicroBlazeV9/portmacro.h b/portable/GCC/MicroBlazeV9/portmacro.h
index 17166b7..3df7d5c 100644
--- a/portable/GCC/MicroBlazeV9/portmacro.h
+++ b/portable/GCC/MicroBlazeV9/portmacro.h
@@ -152,6 +152,11 @@
#define portNOP() asm volatile ( "NOP" )
/*-----------------------------------------------------------*/
+#if( XPAR_MICROBLAZE_USE_STACK_PROTECTION )
+#define portHAS_STACK_OVERFLOW_CHECKING 1
+#endif
+/*-----------------------------------------------------------*/
+
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )