diff --git a/tests/kernel/fatal/prj-arc.conf b/tests/kernel/fatal/prj-arc.conf new file mode 100644 index 00000000000..0ed7ef8429d --- /dev/null +++ b/tests/kernel/fatal/prj-arc.conf @@ -0,0 +1 @@ +CONFIG_ARC_STACK_CHECKING=y diff --git a/tests/kernel/fatal/prj.conf b/tests/kernel/fatal/prj.conf index 753149797b4..1bf885697e9 100644 --- a/tests/kernel/fatal/prj.conf +++ b/tests/kernel/fatal/prj.conf @@ -1,2 +1,2 @@ -CONFIG_MAIN_THREAD_PRIORITY=7 +CONFIG_STACK_SENTINEL=y diff --git a/tests/kernel/fatal/src/main.c b/tests/kernel/fatal/src/main.c index 8590d6f8d75..160243ee6c7 100644 --- a/tests/kernel/fatal/src/main.c +++ b/tests/kernel/fatal/src/main.c @@ -9,10 +9,19 @@ #include #include -#define STACKSIZE 1024 +#define STACKSIZE 2048 +#define MAIN_PRIORITY 7 #define PRIORITY 5 static char __noinit __stack alt_stack[STACKSIZE]; + +#ifdef CONFIG_STACK_SENTINEL +#define OVERFLOW_STACKSIZE 1024 +static char *overflow_stack = alt_stack + (STACKSIZE - OVERFLOW_STACKSIZE); +#else +#define OVERFLOW_STACKSIZE STACKSIZE +#endif + static struct k_thread alt_thread; volatile int rv; @@ -39,8 +48,44 @@ void alt_thread1(void) void alt_thread2(void) { + int key; + + key = irq_lock(); k_oops(); rv = TC_FAIL; + irq_unlock(key); +} + + +void blow_up_stack(void) +{ + char buf[OVERFLOW_STACKSIZE]; + printk("posting %zu bytes of junk to stack...\n", sizeof(buf)); + memset(buf, 0xbb, sizeof(buf)); +} + +void stack_thread1(void) +{ + /* Test that stack overflow check due to timer interrupt works */ + blow_up_stack(); + printk("busy waiting...\n"); + k_busy_wait(1024 * 1024); + printk("should never see this\n"); + rv = TC_FAIL; +} + + +void stack_thread2(void) +{ + int key = irq_lock(); + + /* Test that stack overflow check due to swap works */ + blow_up_stack(); + printk("swapping...\n"); + _Swap(irq_lock()); + printk("should never see this\n"); + rv = TC_FAIL; + irq_unlock(key); } @@ -50,8 +95,10 @@ void main(void) TC_START("test_fatal"); + k_thread_priority_set(_current, K_PRIO_PREEMPT(MAIN_PRIORITY)); + printk("test alt thread 1: generic CPU exception\n"); - k_thread_create(&alt_thread, alt_stack, STACKSIZE, + k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack), (k_thread_entry_t)alt_thread1, NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0, K_NO_WAIT); @@ -63,7 +110,7 @@ void main(void) } printk("test alt thread 2: initiate kernel oops\n"); - k_thread_create(&alt_thread, alt_stack, STACKSIZE, + k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack), (k_thread_entry_t)alt_thread2, NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0, K_NO_WAIT); @@ -74,6 +121,43 @@ void main(void) printk("PASS\n"); } + printk("test stack overflow - timer irq\n"); +#ifdef CONFIG_STACK_SENTINEL + /* When testing stack sentinel feature, the overflow stack is a + * smaller section of alt_stack near the end. + * In this way when it gets overflowed by blow_up_stack() we don't + * corrupt anything else and prevent the test case from completing. + */ + k_thread_create(&alt_thread, overflow_stack, OVERFLOW_STACKSIZE, +#else + k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack), +#endif + (k_thread_entry_t)stack_thread1, + NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0, + K_NO_WAIT); + if (rv == TC_FAIL) { + printk("thread was not aborted\n"); + goto out; + } else { + printk("PASS\n"); + } + + printk("test stack overflow - swap\n"); +#ifdef CONFIG_STACK_SENTINEL + k_thread_create(&alt_thread, overflow_stack, OVERFLOW_STACKSIZE, +#else + k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack), +#endif + (k_thread_entry_t)stack_thread2, + NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0, + K_NO_WAIT); + if (rv == TC_FAIL) { + printk("thread was not aborted\n"); + goto out; + } else { + printk("PASS\n"); + } + out: TC_END_RESULT(rv); TC_END_REPORT(rv); diff --git a/tests/kernel/fatal/testcase.ini b/tests/kernel/fatal/testcase.ini index 63fbe6d020c..b97fd35be26 100644 --- a/tests/kernel/fatal/testcase.ini +++ b/tests/kernel/fatal/testcase.ini @@ -1,2 +1,11 @@ -[test] +# Uses CONFIG_STACK_SENTINEL +[stack-sentinel] tags = core ignore_faults +arch_exclude = arc + +# Uses CONFIG_ARC_STACK_CHECKING +[arc-stack-checking] +tags = core ignore_faults +extra_args = CONF_FILE=prj-arc.conf +arch_whitelist = arc +