Software APIs
rstmgr_alert_info_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "dt/dt_alert_handler.h" // Generated.
6 #include "dt/dt_aon_timer.h" // Generated.
7 #include "dt/dt_i2c.h" // Generated.
8 #include "dt/dt_kmac.h" // Generated.
9 #include "dt/dt_otp_ctrl.h" // Generated.
10 #include "dt/dt_pwrmgr.h" // Generated.
11 #include "dt/dt_rstmgr.h" // Generated.
12 #include "dt/dt_rv_core_ibex.h" // Generated.
13 #include "dt/dt_rv_plic.h" // Generated.
14 #include "dt/dt_spi_host.h" // Generated.
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"
39 
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"
45 #endif // OPENTITAN_IS_EARLGREY
46 
47 #include "alert_handler_regs.h" // Generated.
48 
49 /*
50  RSTMGR ALERT_INFO Test
51 
52  This test runs some alert / dump scenario and check integrity of
53  ALERT_INFO coming from alert_hander to rstmgr.
54 
55  From dif_rstmgr_reset_info_t, there are 8 different resets.
56  This test covers 3 of those (kDifRstmgrResetInfoSw,
57  kDifRstmgrResetInfoWatchdog, kDifRstmgrResetInfoEscalation).
58  kDifRstmgrResetInfoNdm will be added as a separate test after ndm request test
59  is available. Test goes for 3 rounds, and on each round it creates a different
60  reset scenario.
61 
62  Round 1: Single Class profile
63  - Trigger alert from i2c0..2 by calling alert_force.
64  - This will trigger kDifAlertHandlerIrqClassa from alert_handler.
65  - Also alert_info start to transfer from alert_handler to rstmgr.
66  - Upon detecting interrupt, 'ottf_external_isr' request reset to rstmgr
67  - After reset, alert_info will be available at rstmgr.
68  - Read alert_info from rstmgr and compare with expected value.
69 
70  Round 2: Multi Classes profile
71  - Trigger alert from uart0..3 and otp_ctrl.
72  - Setup the aon_timer wdog bark and bite timeouts.
73  - Let the timer expire to create watchdog bite.
74  - After reset, coalesced alert info from uarts and otp_ctrl
75  will be available from rstmgr.
76  - Read alert_info from rstmgr and compare with expected value.
77 
78  Round 3: All Classes profile with alert escalation
79  - Trigger rv_core_ibex alert that leads to an interrupt.
80  - Trigger other alerts for all classes.
81  - rv_core_ibex alert will be escalated to phase2 then it will trigger
82  reset.
83  - Read alert_info from rstmgr and compare with expected value.
84 
85  Round 4: Local alert
86  - Trigger local alert by setting ping timeout value to 1.
87  - Once alert triggers interrupt, call sw_device reset from interrupt
88  handler.
89  - After reset, read alert_info from rstmgr and compare with expected value.
90 
91  */
92 
93 OTTF_DEFINE_TEST_CONFIG();
94 
95 enum {
96  kWdogBarkMicros = 200, // us
97  kWdogBiteMicros = 200, // us
98  kEscalationPhase0Micros = 300, // us
99  kEscalationPhase1Micros = 200, // us
100  kEscalationPhase2Micros = 100, // us
101  kRoundOneDelay = 100, // us
102  kRoundTwoDelay = 100, // us
103  kRoundThreeDelay = 1000, // us
104  kEventCounter = 0 // the retention sram counter tracking events
105 };
106 
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;
118 
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;
127 
128 #ifdef OPENTITAN_IS_EARLGREY
129 static dif_flash_ctrl_state_t flash_ctrl;
130 static const dt_flash_ctrl_t kFlashCtrlDt = 0;
131 #endif // OPENTITAN_IS_EARLGREY
132 
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");
143 
144 typedef struct node {
147 } node_t;
148 
149 typedef enum test_round {
150  kRound1 = 0,
151  kRound2 = 1,
152  kRound3 = 2,
153  kRound4 = 3,
154  kRoundTotal = 4
155 } test_round_t;
156 
157 static volatile test_round_t global_test_round;
158 static volatile uint32_t global_alert_called;
160  kEscProfiles[][ALERT_HANDLER_PARAM_N_CLASSES] = {
161  [kDifAlertHandlerClassA] = {{.phase = kDifAlertHandlerClassStatePhase0,
162  .signal = 0,
163  .duration_cycles = 5000},
165  .signal = 0,
166  .duration_cycles = 3000}},
167  [kDifAlertHandlerClassB] = {{.phase = kDifAlertHandlerClassStatePhase1,
168  .signal = 0,
169  .duration_cycles = 3000}},
170  [kDifAlertHandlerClassC] = {{.phase = kDifAlertHandlerClassStatePhase0,
171  .signal = 0,
172  .duration_cycles = 5000},
174  .signal = 0,
175  .duration_cycles = 3000}},
176  [kDifAlertHandlerClassD] = {{.phase = kDifAlertHandlerClassStatePhase0,
177  .signal = 0,
178  .duration_cycles = 7200},
180  .signal = 1,
181  .duration_cycles = 4800},
183  .signal = 3,
184  .duration_cycles = 2400}}};
185 
187  kConfigProfiles[ALERT_HANDLER_PARAM_N_CLASSES] = {
188  [kDifAlertHandlerClassA] =
189  {
191  .accumulator_threshold = 0,
192  .irq_deadline_cycles = 240,
193  .escalation_phases = kEscProfiles[kDifAlertHandlerClassA],
194  .escalation_phases_len = 2,
195  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
196  },
197  [kDifAlertHandlerClassB] =
198  {
199  .auto_lock_accumulation_counter = kDifToggleDisabled,
200  .accumulator_threshold = 0,
201  .irq_deadline_cycles = 240,
202  .escalation_phases = kEscProfiles[kDifAlertHandlerClassB],
203  .escalation_phases_len = 1,
204  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
205  },
206  [kDifAlertHandlerClassC] =
207  {
208  .auto_lock_accumulation_counter = kDifToggleDisabled,
209  .accumulator_threshold = 0,
210  .irq_deadline_cycles = 240,
211  .escalation_phases = kEscProfiles[kDifAlertHandlerClassC],
212  .escalation_phases_len = 2,
213  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
214  },
215  [kDifAlertHandlerClassD] =
216  {
217  .auto_lock_accumulation_counter = kDifToggleDisabled,
218  .accumulator_threshold = 0,
219  .irq_deadline_cycles = 1000,
220  .escalation_phases = kEscProfiles[kDifAlertHandlerClassD],
221  .escalation_phases_len = 3,
222  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
223  },
224 };
225 
226 typedef struct test_alert_info {
227  char *test_name;
230 
231 // The expected info is set for rom_ext, meaning kBootStage set to
232 // kBootStageOwner. It is adjusted in init_expected_info_for_non_rom_ext.
233 static test_alert_info_t expected_info[kRoundTotal] = {
234  [kRound1] =
235  {
236  .test_name = "Single class(ClassA)",
237  .alert_info =
238  {
239  .class_accum_cnt = {3, 0, 0, 0},
240  .class_esc_state = {kCstatePhase0, kCstateIdle, kCstateIdle,
241  kCstateIdle},
242  },
243  },
244  [kRound2] =
245  {
246  .test_name = "Multi classes(ClassB,C)",
247  .alert_info =
248  {
249  .class_accum_cnt = {0, 0, 4, 0},
250  .class_esc_state = {kCstateIdle, kCstateIdle, kCstateIdle,
251  kCstateIdle},
252  },
253  },
254  [kRound3] =
255  {
256  .test_name = "All classes",
257  .alert_info =
258  {
259  .class_accum_cnt = {1, 1, 1, 1},
260  .class_esc_state = {kCstatePhase0, kCstatePhase1,
261  kCstatePhase0, kCstatePhase0},
262  },
263  },
264  [kRound4] =
265  {
266  .test_name = "Local alert(ClassB)",
267  .alert_info =
268  {
269  .loc_alert_cause =
270  (0x1 << kDifAlertHandlerLocalAlertAlertPingFail),
271  .class_accum_cnt = {0, 1, 0, 0},
272  .class_esc_state = {kCstateIdle, kCstatePhase2, kCstateIdle,
273  kCstateIdle},
274  },
275  },
276 };
277 
278 static node_t test_node(dt_instance_id_t inst_id) {
279  dt_device_type_t device_type = dt_device_type(inst_id);
280 
281  switch (device_type) {
282  case kDtDeviceTypeSpiHost:
283  return (node_t){
284  .alert = dt_spi_host_alert_to_alert_id(
285  dt_spi_host_from_instance_id(inst_id), kDtSpiHostAlertFatalFault),
286  .class = kDifAlertHandlerClassB,
287  };
288  case kDtDeviceTypeOtpCtrl:
289  return (node_t){
290  .alert = dt_otp_ctrl_alert_to_alert_id(
291  dt_otp_ctrl_from_instance_id(inst_id),
292  kDtOtpCtrlAlertFatalBusIntegError),
293  .class = kDifAlertHandlerClassB,
294  };
295  case kDtDeviceTypeKmac:
296  return (node_t){
297  .alert = dt_kmac_alert_to_alert_id(dt_kmac_from_instance_id(inst_id),
298  kDtKmacAlertFatalFaultErr),
299  .class = kDifAlertHandlerClassB,
300  };
301  case kDtDeviceTypeUart:
302  return (node_t){
303  .alert = dt_uart_alert_to_alert_id(dt_uart_from_instance_id(inst_id),
304  kDtUartAlertFatalFault),
305  .class = kDifAlertHandlerClassC,
306  };
307  case kDtDeviceTypeI2c:
308  return (node_t){
309  .alert = dt_i2c_alert_to_alert_id(dt_i2c_from_instance_id(inst_id),
310  kDtI2cAlertFatalFault),
311  .class = kDifAlertHandlerClassA,
312  };
313  default:
314  CHECK(false, "unhandled device type");
315  abort();
316  }
317 }
318 
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));
323  *set = 1;
324 }
325 
326 /**
327  * External ISR.
328  *
329  * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
330  * line to the CPU, which results in a call to this OTTF ISR. This ISR
331  * overrides the default OTTF implementation.
332  */
333 void ottf_external_isr(uint32_t *exc_info) {
334  OT_DISCARD(exc_info);
335  dif_rv_plic_irq_id_t plic_irq;
336  CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &plic_irq));
337 
338  dt_instance_id_t inst_id = dt_plic_id_to_instance_id(plic_irq);
339 
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);
347 
348  switch (irq) {
349  case kDtAlertHandlerIrqClassa:
350  LOG_INFO("IRQ: class A");
352  &alert_handler, kDifI2cAlertFatalFault));
353 
354  // check classes
357  &alert_handler, kDifAlertHandlerClassA, &state));
358 
359  // sw reset for round 1
360  if (global_test_round == kRound1) {
361  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
362  }
363  CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
364 
365  break;
366  case kDtAlertHandlerIrqClassb:
367  LOG_INFO("IRQ: class B %d", global_test_round);
368  break;
369  case kDtAlertHandlerIrqClassc:
370  LOG_INFO("IRQ: class C");
371  break;
372  case kDtAlertHandlerIrqClassd:
373  if (global_alert_called == 0) {
374  set_extra_alert(&global_alert_called);
375  LOG_INFO("IRQ: class D");
376  LOG_INFO("IRQ: extra alert called");
377  }
378  break;
379  default:
380  LOG_FATAL("IRQ: unknown irq %d", irq);
381  }
382  }
383  // Complete the IRQ by writing the IRQ source to the Ibex specific CC
384  // register.
385 
386  CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, plic_irq));
387 }
388 
389 static void print_alert_cause(alert_handler_testutils_info_t info) {
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]);
392  }
393 }
394 
395 /*
396  * Configure alert for i2c0..i2c2 s.t.
397  * .alert class = class A
398  * .escalation phase0,1
399  * .disable ping timer
400  */
401 static void prgm_alert_handler_round1(void) {
402  dif_alert_handler_class_t alert_class = kDifAlertHandlerClassA;
403 
404  for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
405  dt_instance_id_t inst_id = dt_i2c_instance_id(i2c);
406  node_t node = test_node(inst_id);
408  &alert_handler, node.alert, node.class,
409  /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
410  }
411 
413  &alert_handler, alert_class, kConfigProfiles[alert_class],
414  /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
416  &alert_handler, 0, /*enabled=*/kDifToggleEnabled,
417  /*locked=*/kDifToggleEnabled));
418 }
419 
420 /*
421  * Configure alert for uart0..3
422  * .alert class = class C
423  * .escalation phase0,1
424  * Configure alert from aon timer
425  * .alert class = class B
426  * .escalation phases 1
427  *
428  * Set esc_phases.signal = 0 for all cases to avoid
429  * watchdog timer freeze.
430  */
431 static void prgm_alert_handler_round2(void) {
432  dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassC,
433  kDifAlertHandlerClassB};
434  dif_alert_handler_class_config_t class_configs[] = {
435  kConfigProfiles[kDifAlertHandlerClassC],
436  kConfigProfiles[kDifAlertHandlerClassB]};
437 
438  for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
439  dt_instance_id_t inst_id = dt_uart_instance_id(uart);
440  node_t node = test_node(inst_id);
442  &alert_handler, node.alert, node.class,
443  /*enabled=*/kDifToggleEnabled, /*locked=*/kDifToggleEnabled));
444  }
445  dt_instance_id_t otp_ctrl_id = dt_otp_ctrl_instance_id(kDtOtpCtrl);
446  node_t node = test_node(otp_ctrl_id);
447  CHECK_DIF_OK(dif_alert_handler_configure_alert(&alert_handler, node.alert,
448  node.class,
449  /*enabled=*/kDifToggleEnabled,
450  /*locked=*/kDifToggleEnabled));
451 
452  for (int i = 0; i < ARRAYSIZE(alert_classes); ++i) {
454  &alert_handler, alert_classes[i], class_configs[i],
455  /*enabled=*/kDifToggleEnabled,
456  /*locked=*/kDifToggleEnabled));
457  }
458 }
459 
460 /*
461  * Set I2c0 alert to class a
462  * spi_host alert to class b
463  * uart0 alert to class c and
464  * the rest to class d
465  *
466  * For class d, enable 3 phases and escalation reset will be
467  * triggered at phase2
468  */
469 
470 static void prgm_alert_handler_round3(void) {
471  // Enable all incoming alerts. This will create ping timeout event
472  // for all possible alerts and will see the timeout more often.
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);
476 
477  dif_alert_handler_class_t alert_class;
478  switch (device_type) {
479  case kDtDeviceTypeSpiHost:
480  alert_class = kDifAlertHandlerClassB;
481  break;
482  case kDtDeviceTypeUart:
483  alert_class = kDifAlertHandlerClassC;
484  break;
485  case kDtDeviceTypeI2c:
486  alert_class = kDifAlertHandlerClassA;
487  break;
488  default:
489  alert_class = kDifAlertHandlerClassD;
490  break;
491  }
492 
494  &alert_handler, i, alert_class, /*enabled=*/kDifToggleEnabled,
495  /*locked=*/kDifToggleEnabled));
496  }
497 
498  dif_alert_handler_class_t alert_classes[] = {
499  kDifAlertHandlerClassA, kDifAlertHandlerClassB, kDifAlertHandlerClassC,
500  kDifAlertHandlerClassD};
501 
502  dif_alert_handler_class_config_t class_d_config =
503  kConfigProfiles[kDifAlertHandlerClassD];
504 
506 
507  if (kDeviceType == kDeviceFpgaCw310) {
508  CHECK(kUartBaudrate <= UINT32_MAX, "kUartBaudrate must fit in uint32_t");
509  CHECK(kClockFreqPeripheralHz <= UINT32_MAX,
510  "kClockFreqPeripheralHz must fit in uint32_t");
511  uint32_t cpu_freq = (uint32_t)kClockFreqCpuHz;
512  uint32_t peri_freq = (uint32_t)kClockFreqPeripheralHz;
513  uint32_t cycles = kUartTxFifoCpuCycles * (cpu_freq / peri_freq);
514  class_d_esc[0] = kEscProfiles[kDifAlertHandlerClassD][0];
515  class_d_esc[1] = kEscProfiles[kDifAlertHandlerClassD][1];
516  class_d_esc[2] = kEscProfiles[kDifAlertHandlerClassD][2];
517  // we must allow sufficient time for the device to complete uart
518  class_d_esc[0].duration_cycles = cycles;
519  class_d_config.escalation_phases = class_d_esc;
520  }
521 
522  LOG_INFO("Escalation set to %d cycles",
523  class_d_config.escalation_phases[0].duration_cycles);
524 
525  dif_alert_handler_class_config_t class_configs[] = {
526  kConfigProfiles[kDifAlertHandlerClassA],
527  kConfigProfiles[kDifAlertHandlerClassB],
528  kConfigProfiles[kDifAlertHandlerClassC], class_d_config};
529 
530  for (int i = 0; i < ARRAYSIZE(alert_classes); ++i) {
532  &alert_handler, alert_classes[i], class_configs[i],
533  /*enabled=*/kDifToggleEnabled,
534  /*locked=*/kDifToggleEnabled));
535  }
536 
538  &alert_handler, 1000, /*enabled=*/kDifToggleEnabled,
539  /*locked=*/kDifToggleEnabled));
540 
541  CHECK_DIF_OK(dif_rv_core_ibex_alert_force(&rv_core_ibex,
542  kDifRvCoreIbexAlertRecovSwErr));
543 }
544 
545 /*
546  * Configure all global alert enable and mapped to class A
547  * Configure local alert enable and mapped to class B
548  * For class B, set signal to 3 to trigger escalation reset
549  * Change ping timeout value to 1 to cause alert ping timeout
550  */
551 
552 static void prgm_alert_handler_round4(void) {
553  // Enable all alerts to enable ping associate with them.
554  for (dif_alert_handler_alert_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
556  &alert_handler, i, kDifAlertHandlerClassA, kDifToggleEnabled,
558  }
559 
560  // Enable alert ping fail local alert and configure that to classb.
562  kDifAlertHandlerLocalAlertAlertPingFail;
563  dif_alert_handler_class_t loc_alert_class = kDifAlertHandlerClassB;
564 
565  dif_alert_handler_escalation_phase_t esc_phases[] = {
567  .signal = 3,
568  .duration_cycles = 2000}};
569 
570  dif_alert_handler_class_config_t class_config = {
572  .accumulator_threshold = 0,
573  .irq_deadline_cycles = 240,
574  .escalation_phases = esc_phases,
575  .escalation_phases_len = ARRAYSIZE(esc_phases),
576  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
577  };
578 
580  &alert_handler, loc_alert, loc_alert_class, kDifToggleEnabled,
582 
584  &alert_handler, kDifAlertHandlerClassB, class_config, kDifToggleEnabled,
586 
588  &alert_handler, 1, kDifToggleEnabled, kDifToggleEnabled));
589 
590  // Enables alert handler irq.
591  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
592  &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled));
593 }
594 
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));
603 
604  // Set pwrmgr reset_en
606  kDifPwrmgrResetRequestSourceTwo,
608 }
609 
610 static void collect_alert_dump_and_compare(test_round_t round) {
612  size_t seg_size;
613  alert_handler_testutils_info_t actual_info;
614 
615  CHECK_DIF_OK(dif_rstmgr_alert_info_dump_read(
616  &rstmgr, dump, DIF_RSTMGR_ALERT_INFO_MAX_SIZE, &seg_size));
617 
618  LOG_INFO("Testname: %s DUMP SIZE %d", expected_info[round].test_name,
619  seg_size);
620  for (int i = 0; i < seg_size; i++) {
621  LOG_INFO("DUMP:%d: 0x%x", i, dump[i]);
622  }
623 
624  CHECK(seg_size <= INT_MAX, "seg_size must fit in int");
625  CHECK_STATUS_OK(
626  alert_handler_testutils_info_parse(dump, (int)seg_size, &actual_info));
627 
628  if (round == kRound4) {
629  // Check local alert only.
630  // While testing ping timeout for local alert,
631  // global alert ping timeout can be triggered
632  // dut to short timeout value.
633  // However, alert source of this ping timeout can be choosen randomly,
634  // as documented in issue #2321, so we only check local alert cause.
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);
640  } else {
641  LOG_INFO("observed alert cause:");
642  print_alert_cause(actual_info);
643  LOG_INFO("expected alert cause:");
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]);
651  }
652  }
653 
654  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
655  // We cannot do an "equal" check here since some of the alerts may
656  // be fatal and cause the accumulated count to continuously grow.
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]);
662  }
663  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
664  // added '<' because expected state can be minimum phase but
665  // depends on simulation, sometimes it captures higher phase.
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]);
671  }
672 }
673 
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;
679  }
680 
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;
685  }
686 
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;
690 
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;
703 }
704 
705 bool test_main(void) {
706  uint32_t event_idx = 0;
707 
708  // Enable global and external IRQ at Ibex.
709  irq_global_ctrl(true);
710  irq_external_ctrl(true);
711 
712  // set expected values
713  init_expected_cause();
714 
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));
718 
719 #ifdef OPENTITAN_IS_EARLGREY
720  CHECK_DIF_OK(dif_flash_ctrl_init_state_from_dt(&flash_ctrl, kFlashCtrlDt));
721  CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
722 #endif // OPENTITAN_IS_EARLGREY
723 
724  peripheral_init();
725 
726  ret_sram_testutils_init();
727 
728  // Enable all interrupts used in this test.
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,
734  class_d_irq);
735 
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,
741  timer_bark_irq);
742 
743  // enable alert info
745 
746  // Check if there was a HW reset caused by the escalation.
748  rst_info = rstmgr_testutils_reason_get();
749  rstmgr_testutils_reason_clear();
750 
751  LOG_INFO("reset info = 0x%02X", rst_info);
752  global_alert_called = 0;
753 
754  if (rst_info == kDifRstmgrResetInfoPor) {
755  // Initialize the counter. Upon POR they have random values.
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);
760 
761 #ifdef OPENTITAN_IS_EARLGREY
762  // If not running rom_ext we need to initialize the info FLASH partitions
763  // storing the Creator and Owner secrets to avoid getting the flash
764  // controller into a fatal error state.
765  if (kBootStage != kBootStageOwner) {
766  CHECK_STATUS_OK(keymgr_testutils_flash_init(&flash_ctrl, &kCreatorSecret,
767  &kOwnerSecret));
768  }
769  CHECK_STATUS_OK(flash_ctrl_testutils_show_faults(&flash_ctrl));
770 #endif // OPENTITAN_IS_EARLGREY
771 
772  global_test_round = kRound1;
773  prgm_alert_handler_round1();
774 
775  for (dt_i2c_t i2c = 0; i2c < kDtI2cCount; i2c++) {
776  dif_i2c_t i2c_dif;
777  CHECK_DIF_OK(dif_i2c_init_from_dt(i2c, &i2c_dif));
778  CHECK_DIF_OK(dif_i2c_alert_force(&i2c_dif, kDifI2cAlertFatalFault));
779  }
780  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
781  &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
782 
783  // Give an enough delay until sw rest happens.
784  busy_spin_micros(kRoundOneDelay);
785  CHECK(false, "Should have reset before this line");
786  } else {
787  // The retention sram counters have been initialized, so only now they
788  // can be reliably used.
789  CHECK_STATUS_OK(ret_sram_testutils_counter_get(kEventCounter, &event_idx));
790  // Increment retention sram counter to know where we are.
791  CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kEventCounter));
792  LOG_INFO("Test round %d", event_idx);
793 
794  if (rst_info == kDifRstmgrResetInfoSw && event_idx == 1) {
795  collect_alert_dump_and_compare(kRound1);
796  global_test_round = kRound2;
797  prgm_alert_handler_round2();
798 
799  // Setup the aon_timer the wdog bark and bite timeouts.
800  uint32_t bark_cycles = (uint32_t)udiv64_slow(
801  kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL);
802  uint32_t bite_cycles = (uint32_t)udiv64_slow(
803  kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL);
804  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(
805  &aon_timer, bark_cycles, bite_cycles, false));
806 
807  for (dt_uart_t uart = 0; uart < kDtUartCount; uart++) {
808  dif_uart_t uart_dif;
809  CHECK_DIF_OK(dif_uart_init_from_dt(uart, &uart_dif));
810  CHECK_DIF_OK(dif_uart_alert_force(&uart_dif, kDifUartAlertFatalFault));
811  }
812  CHECK_DIF_OK(dif_otp_ctrl_alert_force(
813  &otp_ctrl, kDifOtpCtrlAlertFatalBusIntegError));
814  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
815  &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled));
816  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
817  &alert_handler, kDifAlertHandlerIrqClassc, kDifToggleEnabled));
818 
819  busy_spin_micros(kRoundTwoDelay);
820  CHECK(false, "Should have reset before this line");
821  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
822  collect_alert_dump_and_compare(kRound2);
823 
824  global_test_round = kRound3;
825  prgm_alert_handler_round3();
826  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
827  &alert_handler, kDifAlertHandlerIrqClassd, kDifToggleEnabled));
828 
829  busy_spin_micros(kRoundThreeDelay);
830  CHECK(false, "Should have reset before this line");
831  } else if (rst_info == kDifRstmgrResetInfoEscalation && event_idx == 3) {
832  collect_alert_dump_and_compare(kRound3);
833  global_test_round = kRound4;
834  prgm_alert_handler_round4();
835  // Previously, this test assumed that escalation would always happen
836  // within a fixed amount of time. However, that is not necessarily
837  // the case for ping timeouts. The ping mechanism randomly selects a
838  // peripheral to check. However, since the selection vector is larger
839  // than the number of peripherals we have, it does not always select a
840  // valid peripheral. When the alert handler does not select a valid
841  // peripheral, it simply moves on to the test the next ping. However the
842  // max wait time until the next ping is checked is in the mS range.
843  // Therefore, the test should not make that assumption and just wait in
844  // place.
846  } else if (rst_info == kDifRstmgrResetInfoEscalation && event_idx == 4) {
847  collect_alert_dump_and_compare(kRound4);
848 
849  return true;
850  } else {
851  LOG_FATAL("unexpected reset info %d", rst_info);
852  }
853  }
854  return false;
855 }