5 #include "dt/dt_alert_handler.h"
6 #include "dt/dt_aon_timer.h"
8 #include "dt/dt_kmac.h"
9 #include "dt/dt_otp_ctrl.h"
10 #include "dt/dt_pwrmgr.h"
11 #include "dt/dt_rstmgr.h"
12 #include "dt/dt_rv_core_ibex.h"
13 #include "dt/dt_rv_plic.h"
14 #include "dt/dt_spi_host.h"
24 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
29 #include "sw/device/lib/runtime/irq.h"
31 #include "sw/device/lib/testing/alert_handler_testutils.h"
32 #include "sw/device/lib/testing/aon_timer_testutils.h"
33 #include "sw/device/lib/testing/ret_sram_testutils.h"
34 #include "sw/device/lib/testing/rstmgr_testutils.h"
35 #include "sw/device/lib/testing/rv_plic_testutils.h"
36 #include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
37 #include "sw/device/lib/testing/test_framework/check.h"
40 #ifdef OPENTITAN_IS_EARLGREY
41 #include "dt/dt_flash_ctrl.h"
43 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
44 #include "sw/device/lib/testing/keymgr_testutils.h"
47 #include "alert_handler_regs.h"
93 OTTF_DEFINE_TEST_CONFIG();
96 kWdogBarkMicros = 200,
97 kWdogBiteMicros = 200,
98 kEscalationPhase0Micros = 300,
99 kEscalationPhase1Micros = 200,
100 kEscalationPhase2Micros = 100,
101 kRoundOneDelay = 100,
102 kRoundTwoDelay = 100,
103 kRoundThreeDelay = 1000,
107 static const uint32_t kPlicTarget = 0;
108 static dif_rstmgr_t rstmgr;
109 static dif_alert_handler_t alert_handler;
110 static dif_uart_t uart;
111 static dif_otp_ctrl_t otp_ctrl;
112 static dif_spi_host_t spi_host;
113 static dif_rv_plic_t plic;
114 static dif_rv_core_ibex_t rv_core_ibex;
115 static dif_aon_timer_t aon_timer;
116 static dif_pwrmgr_t pwrmgr;
117 static dif_i2c_t i2c;
119 static const dt_rstmgr_t kRstmgrDt = 0;
120 static const dt_alert_handler_t kAlertHandlerDt = 0;
121 static const dt_otp_ctrl_t kOtpCtrlDt = 0;
122 static const dt_spi_host_t kSpiHostDt = 0;
123 static const dt_rv_plic_t kRvPlicDt = 0;
124 static const dt_rv_core_ibex_t kRvCoreIbexDt = 0;
125 static const dt_aon_timer_t kAonTimerDt = 0;
126 static const dt_pwrmgr_t kPwrmgrDt = 0;
128 #ifdef OPENTITAN_IS_EARLGREY
130 static const dt_flash_ctrl_t kFlashCtrlDt = 0;
133 static_assert(kDtRstmgrCount > 0,
"test requires a reset manager");
134 static_assert(kDtAlertHandlerCount > 0,
"test requires an alert handler");
135 static_assert(kDtOtpCtrlCount > 0,
"test requires an OTP controller");
136 static_assert(kDtRvPlicCount > 0,
"test requires a PLIC");
137 static_assert(kDtRvCoreIbexCount > 0,
"how did you make a top without a core?");
138 static_assert(kDtAonTimerCount > 0,
"test requires an AON timer");
139 static_assert(kDtPwrmgrCount > 0,
"test requires an pwrmgr timer");
140 static_assert(kDtSpiHostCount > 0,
"test requires at least one SPI host");
141 static_assert(kDtI2cCount > 0,
"test requires at least one I2C");
142 static_assert(kDtUartCount > 0,
"test requires at least one UART");
149 typedef enum test_round {
157 static volatile test_round_t global_test_round;
158 static volatile uint32_t global_alert_called;
160 kEscProfiles[][ALERT_HANDLER_PARAM_N_CLASSES] = {
163 .duration_cycles = 5000},
166 .duration_cycles = 3000}},
169 .duration_cycles = 3000}},
172 .duration_cycles = 5000},
175 .duration_cycles = 3000}},
178 .duration_cycles = 7200},
181 .duration_cycles = 4800},
184 .duration_cycles = 2400}}};
187 kConfigProfiles[ALERT_HANDLER_PARAM_N_CLASSES] = {
188 [kDifAlertHandlerClassA] =
191 .accumulator_threshold = 0,
192 .irq_deadline_cycles = 240,
193 .escalation_phases = kEscProfiles[kDifAlertHandlerClassA],
194 .escalation_phases_len = 2,
197 [kDifAlertHandlerClassB] =
200 .accumulator_threshold = 0,
201 .irq_deadline_cycles = 240,
202 .escalation_phases = kEscProfiles[kDifAlertHandlerClassB],
203 .escalation_phases_len = 1,
206 [kDifAlertHandlerClassC] =
209 .accumulator_threshold = 0,
210 .irq_deadline_cycles = 240,
211 .escalation_phases = kEscProfiles[kDifAlertHandlerClassC],
212 .escalation_phases_len = 2,
215 [kDifAlertHandlerClassD] =
218 .accumulator_threshold = 0,
219 .irq_deadline_cycles = 1000,
220 .escalation_phases = kEscProfiles[kDifAlertHandlerClassD],
221 .escalation_phases_len = 3,
236 .test_name =
"Single class(ClassA)",
239 .class_accum_cnt = {3, 0, 0, 0},
240 .class_esc_state = {kCstatePhase0, kCstateIdle, kCstateIdle,
246 .test_name =
"Multi classes(ClassB,C)",
249 .class_accum_cnt = {0, 0, 4, 0},
250 .class_esc_state = {kCstateIdle, kCstateIdle, kCstateIdle,
256 .test_name =
"All classes",
259 .class_accum_cnt = {1, 1, 1, 1},
260 .class_esc_state = {kCstatePhase0, kCstatePhase1,
261 kCstatePhase0, kCstatePhase0},
266 .test_name =
"Local alert(ClassB)",
270 (0x1 << kDifAlertHandlerLocalAlertAlertPingFail),
271 .class_accum_cnt = {0, 1, 0, 0},
272 .class_esc_state = {kCstateIdle, kCstatePhase2, kCstateIdle,
278 static node_t test_node(dt_instance_id_t inst_id) {
279 dt_device_type_t
device_type = dt_device_type(inst_id);
282 case kDtDeviceTypeSpiHost:
284 .alert = dt_spi_host_alert_to_alert_id(
285 dt_spi_host_from_instance_id(inst_id), kDtSpiHostAlertFatalFault),
286 .class = kDifAlertHandlerClassB,
288 case kDtDeviceTypeOtpCtrl:
290 .alert = dt_otp_ctrl_alert_to_alert_id(
291 dt_otp_ctrl_from_instance_id(inst_id),
292 kDtOtpCtrlAlertFatalBusIntegError),
293 .class = kDifAlertHandlerClassB,
295 case kDtDeviceTypeKmac:
297 .alert = dt_kmac_alert_to_alert_id(dt_kmac_from_instance_id(inst_id),
298 kDtKmacAlertFatalFaultErr),
299 .class = kDifAlertHandlerClassB,
301 case kDtDeviceTypeUart:
303 .alert = dt_uart_alert_to_alert_id(dt_uart_from_instance_id(inst_id),
304 kDtUartAlertFatalFault),
305 .class = kDifAlertHandlerClassC,
307 case kDtDeviceTypeI2c:
309 .alert = dt_i2c_alert_to_alert_id(dt_i2c_from_instance_id(inst_id),
310 kDtI2cAlertFatalFault),
311 .class = kDifAlertHandlerClassA,
314 CHECK(
false,
"unhandled device type");
319 static void set_extra_alert(
volatile uint32_t *set) {
320 CHECK_DIF_OK(dif_uart_alert_force(&uart, kDifUartAlertFatalFault));
321 CHECK_DIF_OK(dif_i2c_alert_force(&i2c, kDifI2cAlertFatalFault));
322 CHECK_DIF_OK(dif_spi_host_alert_force(&spi_host, kDifSpiHostAlertFatalFault));
333 void ottf_external_isr(uint32_t *exc_info) {
338 dt_instance_id_t inst_id = dt_plic_id_to_instance_id(plic_irq);
340 if (inst_id == dt_aon_timer_instance_id(kDtAonTimerAon)) {
341 dt_aon_timer_irq_t irq =
342 dt_aon_timer_irq_from_plic_id(kDtAonTimerAon, plic_irq);
343 CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
344 }
else if (inst_id == dt_alert_handler_instance_id(kDtAlertHandler)) {
345 dt_alert_handler_irq_t irq =
346 dt_alert_handler_irq_from_plic_id(kDtAlertHandler, plic_irq);
349 case kDtAlertHandlerIrqClassa:
352 &alert_handler, kDifI2cAlertFatalFault));
357 &alert_handler, kDifAlertHandlerClassA, &state));
360 if (global_test_round == kRound1) {
363 CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
366 case kDtAlertHandlerIrqClassb:
367 LOG_INFO(
"IRQ: class B %d", global_test_round);
369 case kDtAlertHandlerIrqClassc:
372 case kDtAlertHandlerIrqClassd:
373 if (global_alert_called == 0) {
374 set_extra_alert(&global_alert_called);
376 LOG_INFO(
"IRQ: extra alert called");
390 for (uint32_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
391 LOG_INFO(
"alert_cause[%d]: 0x%x", i, info.alert_cause[i]);
401 static void prgm_alert_handler_round1(
void) {
404 for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
405 dt_instance_id_t inst_id = dt_i2c_instance_id(i2c);
408 &alert_handler,
node.alert,
node.class,
413 &alert_handler, alert_class, kConfigProfiles[alert_class],
431 static void prgm_alert_handler_round2(
void) {
433 kDifAlertHandlerClassB};
435 kConfigProfiles[kDifAlertHandlerClassC],
436 kConfigProfiles[kDifAlertHandlerClassB]};
438 for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
439 dt_instance_id_t inst_id = dt_uart_instance_id(uart);
442 &alert_handler,
node.alert,
node.class,
445 dt_instance_id_t otp_ctrl_id = dt_otp_ctrl_instance_id(kDtOtpCtrl);
452 for (
int i = 0; i <
ARRAYSIZE(alert_classes); ++i) {
454 &alert_handler, alert_classes[i], class_configs[i],
470 static void prgm_alert_handler_round3(
void) {
473 for (dt_alert_id_t i = 0; i < kDtAlertCount; i++) {
474 dt_instance_id_t inst_id = dt_alert_id_to_instance_id(i);
475 dt_device_type_t
device_type = dt_device_type(inst_id);
479 case kDtDeviceTypeSpiHost:
480 alert_class = kDifAlertHandlerClassB;
482 case kDtDeviceTypeUart:
483 alert_class = kDifAlertHandlerClassC;
485 case kDtDeviceTypeI2c:
486 alert_class = kDifAlertHandlerClassA;
489 alert_class = kDifAlertHandlerClassD;
499 kDifAlertHandlerClassA, kDifAlertHandlerClassB, kDifAlertHandlerClassC,
500 kDifAlertHandlerClassD};
503 kConfigProfiles[kDifAlertHandlerClassD];
508 CHECK(
kUartBaudrate <= UINT32_MAX,
"kUartBaudrate must fit in uint32_t");
510 "kClockFreqPeripheralHz must fit in uint32_t");
514 class_d_esc[0] = kEscProfiles[kDifAlertHandlerClassD][0];
515 class_d_esc[1] = kEscProfiles[kDifAlertHandlerClassD][1];
516 class_d_esc[2] = kEscProfiles[kDifAlertHandlerClassD][2];
522 LOG_INFO(
"Escalation set to %d cycles",
526 kConfigProfiles[kDifAlertHandlerClassA],
527 kConfigProfiles[kDifAlertHandlerClassB],
528 kConfigProfiles[kDifAlertHandlerClassC], class_d_config};
530 for (
int i = 0; i <
ARRAYSIZE(alert_classes); ++i) {
532 &alert_handler, alert_classes[i], class_configs[i],
541 CHECK_DIF_OK(dif_rv_core_ibex_alert_force(&rv_core_ibex,
542 kDifRvCoreIbexAlertRecovSwErr));
552 static void prgm_alert_handler_round4(
void) {
562 kDifAlertHandlerLocalAlertAlertPingFail;
568 .duration_cycles = 2000}};
572 .accumulator_threshold = 0,
573 .irq_deadline_cycles = 240,
574 .escalation_phases = esc_phases,
575 .escalation_phases_len =
ARRAYSIZE(esc_phases),
591 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
595 static void peripheral_init(
void) {
596 CHECK_DIF_OK(dif_spi_host_init_from_dt(kSpiHostDt, &spi_host));
597 CHECK_DIF_OK(dif_otp_ctrl_init_from_dt(kOtpCtrlDt, &otp_ctrl));
598 CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
599 CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
600 CHECK_DIF_OK(dif_rv_core_ibex_init_from_dt(kRvCoreIbexDt, &rv_core_ibex));
601 CHECK_DIF_OK(dif_i2c_init_from_dt(kDtI2c0, &i2c));
602 CHECK_DIF_OK(dif_uart_init_from_dt(kDtUart0, &uart));
608 kDtAonTimerResetReqAonTimer, &reset_sources));
613 static void collect_alert_dump_and_compare(test_round_t round) {
621 LOG_INFO(
"Testname: %s DUMP SIZE %d", expected_info[round].test_name,
623 for (
int i = 0; i < seg_size; i++) {
624 LOG_INFO(
"DUMP:%d: 0x%x", i, dump[i]);
627 CHECK(seg_size <= INT_MAX,
"seg_size must fit in int");
629 alert_handler_testutils_info_parse(dump, (
int)seg_size, &actual_info));
631 if (round == kRound4) {
638 LOG_INFO(
"loc_alert_cause: exp: %08x obs: %08x",
639 expected_info[round].alert_info.loc_alert_cause,
640 actual_info.loc_alert_cause);
641 CHECK(expected_info[round].alert_info.loc_alert_cause ==
642 actual_info.loc_alert_cause);
645 print_alert_cause(actual_info);
647 print_alert_cause(expected_info[round].alert_info);
648 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
649 CHECK(expected_info[round].alert_info.alert_cause[i] ==
650 actual_info.alert_cause[i],
651 "At alert cause %d Expected %d, got %d", i,
652 expected_info[round].alert_info.alert_cause[i],
653 actual_info.alert_cause[i]);
657 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
660 CHECK(expected_info[round].alert_info.class_accum_cnt[i] <=
661 actual_info.class_accum_cnt[i],
662 "alert_info.class_accum_cnt[%d] mismatch exp:0x%x obs:0x%x", i,
663 expected_info[round].alert_info.class_accum_cnt[i],
664 actual_info.class_accum_cnt[i]);
666 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
669 CHECK(expected_info[round].alert_info.class_esc_state[i] <=
670 actual_info.class_esc_state[i],
671 "alert_info.class_esc_state[%d] mismatch exp:0x%x obs:0x%x", i,
672 expected_info[round].alert_info.class_esc_state[i],
673 actual_info.class_esc_state[i]);
677 static void init_expected_cause(
void) {
678 for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
679 dt_alert_id_t alert_id =
680 dt_i2c_alert_to_alert_id(i2c, kDtI2cAlertFatalFault);
681 expected_info[kRound1].alert_info.alert_cause[alert_id] = 1;
684 for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
685 dt_alert_id_t alert_id =
686 dt_uart_alert_to_alert_id(uart, kDtUartAlertFatalFault);
687 expected_info[kRound2].alert_info.alert_cause[alert_id] = 1;
690 dt_alert_id_t alert_id = dt_otp_ctrl_alert_to_alert_id(
691 kOtpCtrlDt, kDtOtpCtrlAlertFatalBusIntegError);
692 expected_info[kRound2].alert_info.alert_cause[alert_id] = 1;
694 dt_alert_id_t ibex_alert_id = dt_rv_core_ibex_alert_to_alert_id(
695 kDtRvCoreIbex, kDtRvCoreIbexAlertRecovSwErr);
696 dt_alert_id_t uart_alert_id =
697 dt_uart_alert_to_alert_id((dt_uart_t)0, kDtUartAlertFatalFault);
698 dt_alert_id_t i2c_alert_id =
699 dt_i2c_alert_to_alert_id((dt_i2c_t)0, kDtI2cAlertFatalFault);
700 dt_alert_id_t spi_alert_id = dt_spi_host_alert_to_alert_id(
701 (dt_spi_host_t)0, kDtSpiHostAlertFatalFault);
702 expected_info[kRound3].alert_info.alert_cause[ibex_alert_id] = 1;
703 expected_info[kRound3].alert_info.alert_cause[uart_alert_id] = 1;
704 expected_info[kRound3].alert_info.alert_cause[i2c_alert_id] = 1;
705 expected_info[kRound3].alert_info.alert_cause[spi_alert_id] = 1;
709 uint32_t event_idx = 0;
712 irq_global_ctrl(
true);
713 irq_external_ctrl(
true);
716 init_expected_cause();
718 CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
719 CHECK_DIF_OK(dif_alert_handler_init_from_dt(kAlertHandlerDt, &alert_handler));
720 CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
722 #ifdef OPENTITAN_IS_EARLGREY
724 CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
729 ret_sram_testutils_init();
732 dt_plic_irq_id_t class_a_irq = dt_alert_handler_irq_to_plic_id(
733 kDtAlertHandler, kDtAlertHandlerIrqClassa);
734 dt_plic_irq_id_t class_d_irq = dt_alert_handler_irq_to_plic_id(
735 kDtAlertHandler, kDtAlertHandlerIrqClassd);
736 rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, class_a_irq,
739 dt_plic_irq_id_t timer_expired_irq = dt_aon_timer_irq_to_plic_id(
740 kDtAonTimerAon, kDtAonTimerIrqWkupTimerExpired);
741 dt_plic_irq_id_t timer_bark_irq =
742 dt_aon_timer_irq_to_plic_id(kDtAonTimerAon, kDtAonTimerIrqWdogTimerBark);
743 rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, timer_expired_irq,
751 rst_info = rstmgr_testutils_reason_get();
752 rstmgr_testutils_reason_clear();
754 LOG_INFO(
"reset info = 0x%02X", rst_info);
755 global_alert_called = 0;
759 CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kEventCounter));
760 CHECK_STATUS_OK(ret_sram_testutils_counter_get(kEventCounter, &event_idx));
761 CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kEventCounter));
762 LOG_INFO(
"Test round %d", event_idx);
764 #ifdef OPENTITAN_IS_EARLGREY
769 CHECK_STATUS_OK(keymgr_testutils_flash_init(&flash_ctrl, &kCreatorSecret,
772 CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
775 global_test_round = kRound1;
776 prgm_alert_handler_round1();
778 for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
780 CHECK_DIF_OK(dif_i2c_init_from_dt(i2c, &i2c_dif));
781 CHECK_DIF_OK(dif_i2c_alert_force(&i2c_dif, kDifI2cAlertFatalFault));
783 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
788 CHECK(
false,
"Should have reset before this line");
792 CHECK_STATUS_OK(ret_sram_testutils_counter_get(kEventCounter, &event_idx));
794 CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kEventCounter));
795 LOG_INFO(
"Test round %d", event_idx);
798 collect_alert_dump_and_compare(kRound1);
799 global_test_round = kRound2;
800 prgm_alert_handler_round2();
807 CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(
808 &aon_timer, bark_cycles, bite_cycles,
false));
810 for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
812 CHECK_DIF_OK(dif_uart_init_from_dt(uart, &uart_dif));
813 CHECK_DIF_OK(dif_uart_alert_force(&uart_dif, kDifUartAlertFatalFault));
815 CHECK_DIF_OK(dif_otp_ctrl_alert_force(
816 &otp_ctrl, kDifOtpCtrlAlertFatalBusIntegError));
817 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
819 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
823 CHECK(
false,
"Should have reset before this line");
824 }
else if (rst_info == kDifRstmgrResetInfoWatchdog) {
825 collect_alert_dump_and_compare(kRound2);
827 global_test_round = kRound3;
828 prgm_alert_handler_round3();
829 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
833 CHECK(
false,
"Should have reset before this line");
835 collect_alert_dump_and_compare(kRound3);
836 global_test_round = kRound4;
837 prgm_alert_handler_round4();
850 collect_alert_dump_and_compare(kRound4);
854 LOG_FATAL(
"unexpected reset info %d", rst_info);