From 1e35906acd37fd1e04e792c10feb844efb835b7d Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Fri, 16 Mar 2012 10:40:27 +0800 Subject: Stack overflow detection Use guard value to detect stack overflow Signed-off-by: Vic Yang BUG=chrome-os-partner:8069 TEST=Compile with detection enabled. Cause a task to overflow and see device halted. Hook gdb and see it stopped at the assertion. Change-Id: I3417cca8edf4e1291ccb7848bd564b631a9ce463 --- core/cortex-m/task.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'core/cortex-m/task.c') diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c index 34c12d674c..d11024c8ad 100644 --- a/core/cortex-m/task.c +++ b/core/cortex-m/task.c @@ -27,6 +27,7 @@ typedef union { struct { uint32_t sp; /* saved stack pointer for context switch */ uint32_t events; /* bitmaps of received events */ + uint32_t guard; /* Guard value to detect stack overflow */ uint8_t stack[0]; /* task stack */ }; uint32_t context[TASK_SIZE/4]; @@ -72,10 +73,12 @@ static void task_exit_trap(void) } +#define GUARD_VALUE 0x12345678 /* declare and fill the contexts for all the tasks */ #define TASK(n, r, d) { \ .context[0] = (uint32_t)(tasks + TASK_ID_##n + 1) - 64, \ + .context[2] = GUARD_VALUE, \ .context[TASK_SIZE/4 - 8/*r0*/] = (uint32_t)d, \ .context[TASK_SIZE/4 - 3/*lr*/] = (uint32_t)task_exit_trap, \ .context[TASK_SIZE/4 - 2/*pc*/] = (uint32_t)r, \ @@ -87,8 +90,13 @@ static task_ tasks[] __attribute__((section(".data.tasks"))) CONFIG_TASK_LIST }; #undef TASK -/* reserve space to discard context on first context switch */ -uint32_t scratchpad[17] __attribute__((section(".data.tasks"))); +/* Reserve space to discard context on first context switch. + * Fill in guard value to prevent overflow detection failure at first + * context switch. Modify this if the position of guard value changes. + * TODO: come up with a better way than hardcoding the position of guard value. + */ +uint32_t scratchpad[17] __attribute__((section(".data.tasks"))) = + {0, 0, GUARD_VALUE}; /* context switch at the next exception exit if needed */ /* TODO: who sets this back to 0 after it's set to 1? */ @@ -181,6 +189,10 @@ void svc_handler(int desched, task_id_t resched) asm volatile("cpsid f\n" "isb\n"); current = __get_task_scheduled(); +#ifdef CONFIG_OVERFLOW_DETECT + ASSERT(current->guard == GUARD_VALUE); +#endif + if (desched && !current->events) { /* Remove our own ready bit */ tasks_ready &= ~(1 << (current-tasks)); -- cgit v1.2.1