altos/stm: Validate current task SP in interrupt by looking at PSP
authorKeith Packard <keithp@keithp.com>
Sat, 26 Mar 2016 22:54:24 +0000 (15:54 -0700)
committerKeith Packard <keithp@keithp.com>
Sat, 26 Mar 2016 23:07:20 +0000 (16:07 -0700)
We use a separate stack pointer for task code, which means we can
verify that it is in range in any interrupt handler. This adds checks
for the task stack (under #ifdef DEBUG) that run in ao_wakeup as well
as at every timer interrupt.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/kernel/ao_task.c
src/kernel/ao_task.h
src/stm/ao_arch_funcs.h
src/stm/ao_timer.c

index 55e423bb90bae9589f926ddbb3aeae690e2ad48a..104d1074b8b66a6b8286a9e21e1f79d1e3ad7b8e 100644 (file)
@@ -355,7 +355,6 @@ ao_yield(void) ao_arch_naked_define
         */
        if (ao_cur_task->wchan == NULL)
                ao_task_to_run_queue(ao_cur_task);
-       ao_cur_task = NULL;
        for (;;) {
                ao_arch_memory_barrier();
                if (!ao_list_is_empty(&run_queue))
@@ -425,6 +424,7 @@ ao_sleep(__xdata void *wchan)
 void
 ao_wakeup(__xdata void *wchan) __reentrant
 {
+       ao_validate_cur_stack();
 #if HAS_TASK_QUEUE
        struct ao_task  *sleep, *next;
        struct ao_list  *sleep_queue;
index c6bec0e397dccba3f1625160330ff4af049f27fa..0e353fe83a9998fcebffd52e0eb207d8c9002814 100644 (file)
@@ -56,6 +56,10 @@ extern __data uint8_t ao_num_tasks;
 extern __xdata struct ao_task *__data ao_cur_task;
 extern __data uint8_t ao_task_minimize_latency;        /* Reduce IRQ latency */
 
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
 /*
  ao_task.c
  */
index 02b344b11078edfc1eb8dd3283fe23c6022a4df9..6b38032cc352a296b75731095d2fe10b76297f44 100644 (file)
@@ -366,6 +366,22 @@ static inline void ao_arch_restore_stack(void) {
 #define HAS_SAMPLE_PROFILE 0
 #endif
 
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK    1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+       uint8_t         *psp;
+
+       asm("mrs %0,psp" : "=&r" (psp));
+       if (ao_cur_task &&
+           psp <= ao_cur_task->stack &&
+           psp >= ao_cur_task->stack - 256)
+               ao_panic(AO_PANIC_STACK);
+}
+#endif
+
 #if !HAS_SAMPLE_PROFILE
 #define HAS_ARCH_START_SCHEDULER       1
 
index 8db62e76a806b6ff51e49ecb3e23d0cc087aab72..91ede84bcc5ee7f4e015fb46b6188412c35b6746 100644 (file)
@@ -41,6 +41,7 @@ volatile __data uint8_t       ao_data_count;
 
 void stm_systick_isr(void)
 {
+       ao_validate_cur_stack();
        if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
                ++ao_tick_count;
 #if HAS_TASK_QUEUE