/* 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 /* * 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(); msleep(30); /* Wait for TASK_ID_TEST to initialize */ task_wake(TASK_ID_TEST); }