blob: ca89c058f270f035e9057bb416b8c9ded966846d [file] [log] [blame] [edit]
/* Copyright 2022 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "common.h"
#include "panic.h"
#include "system.h"
#include "task.h"
#include "test_util.h"
#include <stdlib.h>
/*
* trapping addition: __addvsi3.
*/
test_static int test_ftrapv_addition(void)
{
int32_t test_overflow = INT32_MAX;
int32_t ret;
ccprintf("Testing signed integer addition overflow\n");
cflush();
ret = test_overflow + 1;
/* Should never reach this. */
ccprintf("ret: %d\n", ret);
cflush();
return EC_ERROR_UNKNOWN;
}
/*
* trapping subtraction: __subvsi3.
*/
test_static int test_ftrapv_subtraction(void)
{
int32_t test_overflow = INT32_MIN;
int32_t ret;
ccprintf("Testing signed integer subtraction overflow\n");
cflush();
ret = test_overflow - 1;
/* Should never reach this. */
ccprintf("ret: %d\n", ret);
cflush();
return EC_ERROR_UNKNOWN;
}
/*
* trapping multiplication: __mulvsi3.
*/
test_static int test_ftrapv_multiplication(void)
{
int32_t test_overflow = INT32_MAX;
int32_t ret;
ccprintf("Testing signed integer multiplication overflow\n");
cflush();
ret = test_overflow * 2;
/* Should never reach this. */
ccprintf("ret: %d\n", ret);
cflush();
return EC_ERROR_UNKNOWN;
}
/*
* trapping negation: __negvsi2.
*/
test_static int test_ftrapv_negation(void)
{
int32_t test_overflow = INT32_MIN;
int32_t ret;
ccprintf("Testing signed integer negation overflow\n");
cflush();
ret = -test_overflow;
/* Should never reach this. */
ccprintf("ret: %d\n", ret);
cflush();
return EC_ERROR_UNKNOWN;
}
/*
* trapping absolute value: __absvsi2.
*
* TODO(b/258074414): Trapping on absolute value overflow is broken in clang.
*/
test_static int test_ftrapv_absolute_value(void)
{
int32_t test_overflow = INT32_MIN;
int32_t ret;
ccprintf("Testing signed integer absolute value overflow\n");
cflush();
ret = abs(test_overflow);
/* Should never reach this. */
ccprintf("ret: %d\n", ret);
cflush();
return EC_ERROR_UNKNOWN;
}
test_static int test_panic_data(void)
{
const uint32_t expected_reason = 0;
const uint32_t expected_info = 0;
/*
* https://developer.arm.com/documentation/dui0552/a/the-cortex-m3-processor/exception-model/exception-types
*/
const uint8_t expected_exception = 6; /* usage fault */
uint32_t reason = UINT32_MAX;
uint32_t info = UINT32_MAX;
uint8_t exception = UINT8_MAX;
panic_get_reason(&reason, &info, &exception);
TEST_EQ(reason, expected_reason, "%08x");
TEST_EQ(info, expected_info, "%d");
TEST_EQ(exception, expected_exception, "%d");
return EC_SUCCESS;
}
test_static void run_test_step1(void)
{
test_set_next_step(TEST_STATE_STEP_2);
RUN_TEST(test_ftrapv_addition);
}
test_static void run_test_step2(void)
{
RUN_TEST(test_panic_data);
if (test_get_error_count())
test_reboot_to_next_step(TEST_STATE_FAILED);
else
test_reboot_to_next_step(TEST_STATE_STEP_3);
}
test_static void run_test_step3(void)
{
test_set_next_step(TEST_STATE_STEP_4);
RUN_TEST(test_ftrapv_subtraction);
}
test_static void run_test_step4(void)
{
RUN_TEST(test_panic_data);
if (test_get_error_count())
test_reboot_to_next_step(TEST_STATE_FAILED);
else
test_reboot_to_next_step(TEST_STATE_STEP_5);
}
test_static void run_test_step5(void)
{
test_set_next_step(TEST_STATE_STEP_6);
RUN_TEST(test_ftrapv_multiplication);
}
test_static void run_test_step6(void)
{
RUN_TEST(test_panic_data);
if (test_get_error_count())
test_reboot_to_next_step(TEST_STATE_FAILED);
else
test_reboot_to_next_step(TEST_STATE_STEP_7);
}
test_static void run_test_step7(void)
{
test_set_next_step(TEST_STATE_STEP_8);
RUN_TEST(test_ftrapv_negation);
}
test_static void run_test_step8(void)
{
RUN_TEST(test_panic_data);
if (test_get_error_count())
test_reboot_to_next_step(TEST_STATE_FAILED);
else
test_reboot_to_next_step(TEST_STATE_STEP_9);
}
test_static void run_test_step9(void)
{
/*
* TODO(b/258074414): Trapping on absolute value overflow is broken in
* clang, so skip the check.
*/
#if 0
test_set_next_step(TEST_STATE_STEP_10);
RUN_TEST(test_ftrapv_absolute_value);
#else
test_reboot_to_next_step(TEST_STATE_STEP_10);
#endif
}
test_static void run_test_step10(void)
{
/*
* TODO(b/258074414): Trapping on absolute value overflow is broken in
* clang, so skip the check.
*/
#if 0
RUN_TEST(test_panic_data);
#endif
if (test_get_error_count())
test_reboot_to_next_step(TEST_STATE_FAILED);
else
test_reboot_to_next_step(TEST_STATE_PASSED);
}
void test_run_step(uint32_t state)
{
if (state & TEST_STATE_MASK(TEST_STATE_STEP_1)) {
run_test_step1();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_2)) {
run_test_step2();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_3)) {
run_test_step3();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_4)) {
run_test_step4();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_5)) {
run_test_step5();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_6)) {
run_test_step6();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_7)) {
run_test_step7();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_8)) {
run_test_step8();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_9)) {
run_test_step9();
} else if (state & TEST_STATE_MASK(TEST_STATE_STEP_10)) {
run_test_step10();
}
}
int task_test(void *unused)
{
if (IS_ENABLED(SECTION_IS_RW))
test_run_multistep();
return EC_SUCCESS;
}
void run_test(int argc, const char **argv)
{
test_reset();
crec_msleep(30); /* Wait for TASK_ID_TEST to initialize */
task_wake(TASK_ID_TEST);
}
OSZAR »