Stack overflow detection

Use guard value to detect stack overflow

Signed-off-by: Vic Yang <victoryang@google.com>

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
This commit is contained in:
Vic Yang
2012-03-16 10:40:27 +08:00
parent 7209e7c2d0
commit 1e35906acd

View File

@@ -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));