tests: fatal: increase coverage

- _SysFatalErrorHandler is supposed to be user-overridable.
The test case now installs its own handler to show that this
has happened properly.

- Use TC_PRINT() TC_ERROR() macros

- Since we have out own _SysFatalErrorHandler, show that
k_panic() works

- Show that _SysFatalErrorHandler gets invoked with the expected
reason code for some of the scenarios.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-06-07 10:57:01 -07:00 committed by Maureen Helm
commit 000429c069

View file

@ -25,6 +25,27 @@ static char *overflow_stack = alt_stack + (STACKSIZE - OVERFLOW_STACKSIZE);
static struct k_thread alt_thread;
volatile int rv;
static volatile int crash_reason;
/* ARM is a special case, in that k_thread_abort() does indeed return
* instead of calling _Swap() directly. The PendSV exception is queued
* and immediately fires upon completing the exception path; the faulting
* thread is never run again.
*/
#ifndef CONFIG_ARM
FUNC_NORETURN
#endif
void _SysFatalErrorHandler(unsigned int reason, const NANO_ESF *pEsf)
{
TC_PRINT("Caught system error -- reason %d\n", reason);
crash_reason = reason;
k_thread_abort(_current);
#ifndef CONFIG_ARM
CODE_UNREACHABLE;
#endif
}
void alt_thread1(void)
{
#if defined(CONFIG_X86)
@ -52,15 +73,26 @@ void alt_thread2(void)
key = irq_lock();
k_oops();
TC_ERROR("SHOULD NEVER SEE THIS\n");
rv = TC_FAIL;
irq_unlock(key);
}
void alt_thread3(void)
{
int key;
key = irq_lock();
k_panic();
TC_ERROR("SHOULD NEVER SEE THIS\n");
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));
TC_PRINT("posting %zu bytes of junk to stack...\n", sizeof(buf));
memset(buf, 0xbb, sizeof(buf));
}
@ -68,9 +100,9 @@ void stack_thread1(void)
{
/* Test that stack overflow check due to timer interrupt works */
blow_up_stack();
printk("busy waiting...\n");
TC_PRINT("busy waiting...\n");
k_busy_wait(1024 * 1024);
printk("should never see this\n");
TC_ERROR("should never see this\n");
rv = TC_FAIL;
}
@ -81,9 +113,9 @@ void stack_thread2(void)
/* Test that stack overflow check due to swap works */
blow_up_stack();
printk("swapping...\n");
TC_PRINT("swapping...\n");
_Swap(irq_lock());
printk("should never see this\n");
TC_ERROR("should never see this\n");
rv = TC_FAIL;
irq_unlock(key);
}
@ -97,31 +129,55 @@ void main(void)
k_thread_priority_set(_current, K_PRIO_PREEMPT(MAIN_PRIORITY));
printk("test alt thread 1: generic CPU exception\n");
TC_PRINT("test alt thread 1: generic CPU exception\n");
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
(k_thread_entry_t)alt_thread1,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
NULL, NULL, NULL, K_PRIO_COOP(PRIORITY), 0,
K_NO_WAIT);
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
TC_ERROR("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
TC_PRINT("PASS\n");
}
printk("test alt thread 2: initiate kernel oops\n");
TC_PRINT("test alt thread 2: initiate kernel oops\n");
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
(k_thread_entry_t)alt_thread2,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
NULL, NULL, NULL, K_PRIO_COOP(PRIORITY), 0,
K_NO_WAIT);
k_thread_abort(&alt_thread);
if (crash_reason != _NANO_ERR_KERNEL_OOPS) {
TC_ERROR("bad reason code got %d expected %d\n",
crash_reason, _NANO_ERR_KERNEL_OOPS);
rv = TC_FAIL;
}
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
TC_ERROR("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
TC_PRINT("PASS\n");
}
printk("test stack overflow - timer irq\n");
TC_PRINT("test alt thread 3: initiate kernel panic\n");
k_thread_create(&alt_thread, alt_stack, sizeof(alt_stack),
(k_thread_entry_t)alt_thread3,
NULL, NULL, NULL, K_PRIO_COOP(PRIORITY), 0,
K_NO_WAIT);
k_thread_abort(&alt_thread);
if (crash_reason != _NANO_ERR_KERNEL_PANIC) {
TC_ERROR("bad reason code got %d expected %d\n",
crash_reason, _NANO_ERR_KERNEL_PANIC);
rv = TC_FAIL;
}
if (rv == TC_FAIL) {
TC_ERROR("thread was not aborted\n");
goto out;
} else {
TC_PRINT("PASS\n");
}
TC_PRINT("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.
@ -135,14 +191,19 @@ void main(void)
(k_thread_entry_t)stack_thread1,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
if (crash_reason != _NANO_ERR_STACK_CHK_FAIL) {
TC_ERROR("bad reason code got %d expected %d\n",
crash_reason, _NANO_ERR_KERNEL_PANIC);
rv = TC_FAIL;
}
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
TC_ERROR("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
TC_PRINT("PASS\n");
}
printk("test stack overflow - swap\n");
TC_PRINT("test stack overflow - swap\n");
#ifdef CONFIG_STACK_SENTINEL
k_thread_create(&alt_thread, overflow_stack, OVERFLOW_STACKSIZE,
#else
@ -151,13 +212,17 @@ void main(void)
(k_thread_entry_t)stack_thread2,
NULL, NULL, NULL, K_PRIO_PREEMPT(PRIORITY), 0,
K_NO_WAIT);
if (crash_reason != _NANO_ERR_STACK_CHK_FAIL) {
TC_ERROR("bad reason code got %d expected %d\n",
crash_reason, _NANO_ERR_KERNEL_PANIC);
rv = TC_FAIL;
}
if (rv == TC_FAIL) {
printk("thread was not aborted\n");
TC_ERROR("thread was not aborted\n");
goto out;
} else {
printk("PASS\n");
TC_PRINT("PASS\n");
}
out:
TC_END_RESULT(rv);
TC_END_REPORT(rv);