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));
606 kDifPwrmgrResetRequestSourceTwo,
610 static void collect_alert_dump_and_compare(test_round_t round) {
618 LOG_INFO(
"Testname: %s DUMP SIZE %d", expected_info[round].test_name,
620 for (
int i = 0; i < seg_size; i++) {
621 LOG_INFO(
"DUMP:%d: 0x%x", i, dump[i]);
624 CHECK(seg_size <= INT_MAX,
"seg_size must fit in int");
626 alert_handler_testutils_info_parse(dump, (
int)seg_size, &actual_info));
628 if (round == kRound4) {
635 LOG_INFO(
"loc_alert_cause: exp: %08x obs: %08x",
636 expected_info[round].alert_info.loc_alert_cause,
637 actual_info.loc_alert_cause);
638 CHECK(expected_info[round].alert_info.loc_alert_cause ==
639 actual_info.loc_alert_cause);
642 print_alert_cause(actual_info);
644 print_alert_cause(expected_info[round].alert_info);
645 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
646 CHECK(expected_info[round].alert_info.alert_cause[i] ==
647 actual_info.alert_cause[i],
648 "At alert cause %d Expected %d, got %d", i,
649 expected_info[round].alert_info.alert_cause[i],
650 actual_info.alert_cause[i]);
654 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
657 CHECK(expected_info[round].alert_info.class_accum_cnt[i] <=
658 actual_info.class_accum_cnt[i],
659 "alert_info.class_accum_cnt[%d] mismatch exp:0x%x obs:0x%x", i,
660 expected_info[round].alert_info.class_accum_cnt[i],
661 actual_info.class_accum_cnt[i]);
663 for (
int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
666 CHECK(expected_info[round].alert_info.class_esc_state[i] <=
667 actual_info.class_esc_state[i],
668 "alert_info.class_esc_state[%d] mismatch exp:0x%x obs:0x%x", i,
669 expected_info[round].alert_info.class_esc_state[i],
670 actual_info.class_esc_state[i]);
674 static void init_expected_cause(
void) {
675 for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
676 dt_alert_id_t alert_id =
677 dt_i2c_alert_to_alert_id(i2c, kDtI2cAlertFatalFault);
678 expected_info[kRound1].alert_info.alert_cause[alert_id] = 1;
681 for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
682 dt_alert_id_t alert_id =
683 dt_uart_alert_to_alert_id(uart, kDtUartAlertFatalFault);
684 expected_info[kRound2].alert_info.alert_cause[alert_id] = 1;
687 dt_alert_id_t alert_id = dt_otp_ctrl_alert_to_alert_id(
688 kOtpCtrlDt, kDtOtpCtrlAlertFatalBusIntegError);
689 expected_info[kRound2].alert_info.alert_cause[alert_id] = 1;
691 dt_alert_id_t ibex_alert_id = dt_rv_core_ibex_alert_to_alert_id(
692 kDtRvCoreIbex, kDtRvCoreIbexAlertRecovSwErr);
693 dt_alert_id_t uart_alert_id =
694 dt_uart_alert_to_alert_id((dt_uart_t)0, kDtUartAlertFatalFault);
695 dt_alert_id_t i2c_alert_id =
696 dt_i2c_alert_to_alert_id((dt_i2c_t)0, kDtI2cAlertFatalFault);
697 dt_alert_id_t spi_alert_id = dt_spi_host_alert_to_alert_id(
698 (dt_spi_host_t)0, kDtSpiHostAlertFatalFault);
699 expected_info[kRound3].alert_info.alert_cause[ibex_alert_id] = 1;
700 expected_info[kRound3].alert_info.alert_cause[uart_alert_id] = 1;
701 expected_info[kRound3].alert_info.alert_cause[i2c_alert_id] = 1;
702 expected_info[kRound3].alert_info.alert_cause[spi_alert_id] = 1;
706 uint32_t event_idx = 0;
709 irq_global_ctrl(
true);
710 irq_external_ctrl(
true);
713 init_expected_cause();
715 CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
716 CHECK_DIF_OK(dif_alert_handler_init_from_dt(kAlertHandlerDt, &alert_handler));
717 CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
719 #ifdef OPENTITAN_IS_EARLGREY
721 CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
726 ret_sram_testutils_init();
729 dt_plic_irq_id_t class_a_irq = dt_alert_handler_irq_to_plic_id(
730 kDtAlertHandler, kDtAlertHandlerIrqClassa);
731 dt_plic_irq_id_t class_d_irq = dt_alert_handler_irq_to_plic_id(
732 kDtAlertHandler, kDtAlertHandlerIrqClassd);
733 rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, class_a_irq,
736 dt_plic_irq_id_t timer_expired_irq = dt_aon_timer_irq_to_plic_id(
737 kDtAonTimerAon, kDtAonTimerIrqWkupTimerExpired);
738 dt_plic_irq_id_t timer_bark_irq =
739 dt_aon_timer_irq_to_plic_id(kDtAonTimerAon, kDtAonTimerIrqWdogTimerBark);
740 rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, timer_expired_irq,
748 rst_info = rstmgr_testutils_reason_get();
749 rstmgr_testutils_reason_clear();
751 LOG_INFO(
"reset info = 0x%02X", rst_info);
752 global_alert_called = 0;
756 CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kEventCounter));
757 CHECK_STATUS_OK(ret_sram_testutils_counter_get(kEventCounter, &event_idx));
758 CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kEventCounter));
759 LOG_INFO(
"Test round %d", event_idx);
761 #ifdef OPENTITAN_IS_EARLGREY
766 CHECK_STATUS_OK(keymgr_testutils_flash_init(&flash_ctrl, &kCreatorSecret,
769 CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
772 global_test_round = kRound1;
773 prgm_alert_handler_round1();
775 for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
777 CHECK_DIF_OK(dif_i2c_init_from_dt(i2c, &i2c_dif));
778 CHECK_DIF_OK(dif_i2c_alert_force(&i2c_dif, kDifI2cAlertFatalFault));
780 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
785 CHECK(
false,
"Should have reset before this line");
789 CHECK_STATUS_OK(ret_sram_testutils_counter_get(kEventCounter, &event_idx));
791 CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kEventCounter));
792 LOG_INFO(
"Test round %d", event_idx);
795 collect_alert_dump_and_compare(kRound1);
796 global_test_round = kRound2;
797 prgm_alert_handler_round2();
804 CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(
805 &aon_timer, bark_cycles, bite_cycles,
false));
807 for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
809 CHECK_DIF_OK(dif_uart_init_from_dt(uart, &uart_dif));
810 CHECK_DIF_OK(dif_uart_alert_force(&uart_dif, kDifUartAlertFatalFault));
812 CHECK_DIF_OK(dif_otp_ctrl_alert_force(
813 &otp_ctrl, kDifOtpCtrlAlertFatalBusIntegError));
814 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
816 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
820 CHECK(
false,
"Should have reset before this line");
821 }
else if (rst_info == kDifRstmgrResetInfoWatchdog) {
822 collect_alert_dump_and_compare(kRound2);
824 global_test_round = kRound3;
825 prgm_alert_handler_round3();
826 CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
830 CHECK(
false,
"Should have reset before this line");
832 collect_alert_dump_and_compare(kRound3);
833 global_test_round = kRound4;
834 prgm_alert_handler_round4();
847 collect_alert_dump_and_compare(kRound4);
851 LOG_FATAL(
"unexpected reset info %d", rst_info);