Software APIs
alert_handler_lpg_sleep_mode_pings.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 <assert.h>
6 #include <limits.h>
7 #include <stdbool.h>
8 #include <stdint.h>
9 
15 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
17 #include "sw/device/lib/runtime/irq.h"
19 #include "sw/device/lib/testing/alert_handler_testutils.h"
20 #include "sw/device/lib/testing/aon_timer_testutils.h"
21 #include "sw/device/lib/testing/keymgr_testutils.h"
22 #include "sw/device/lib/testing/pwrmgr_testutils.h"
23 #include "sw/device/lib/testing/rand_testutils.h"
24 #include "sw/device/lib/testing/ret_sram_testutils.h"
25 #include "sw/device/lib/testing/rstmgr_testutils.h"
26 #include "sw/device/lib/testing/rv_plic_testutils.h"
27 #include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
28 #include "sw/device/lib/testing/test_framework/check.h"
30 
31 #include "alert_handler_regs.h"
32 #include "sw/device/lib/testing/autogen/isr_testutils.h"
33 
34 OTTF_DEFINE_TEST_CONFIG();
35 
36 static const dt_pwrmgr_t kPwrmgrDt = 0;
37 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
38 static const dt_aon_timer_t kAonTimerDt = 0;
39 static_assert(kDtAonTimerCount >= 1,
40  "this test expects at least one aon_timer");
41 static const dt_rstmgr_t kRstmgrDt = 0;
42 static_assert(kDtPwrmgrCount == 1, "this test expects a rstmgr");
43 static const dt_alert_handler_t kAlertHandlerDt = 0;
44 static_assert(kDtAlertHandlerCount == 1, "this test expects an alert_handler");
45 static const dt_rv_core_ibex_t kRvCoreIbexDt = 0;
46 static_assert(kDtRvCoreIbexCount == 1, "this test expects exactly one Ibex");
47 static const dt_flash_ctrl_t kFlashCtrlDt = 0;
48 static_assert(kDtFlashCtrlCount == 1, "this test expects a flash_ctrl");
49 static const dt_rv_plic_t kRvPlicDt = 0;
50 static_assert(kDtRvPlicCount == 1, "this test expects exactly one rv_plic");
51 
52 enum {
53  kPlicTarget = 0,
54 };
55 
56 static dif_rv_plic_t plic;
57 static dif_alert_handler_t alert_handler;
58 static dif_aon_timer_t aon_timer;
59 static dif_pwrmgr_t pwrmgr;
60 static dif_rstmgr_t rstmgr;
61 static dif_rv_core_ibex_t ibex;
62 static dif_flash_ctrl_state_t flash_ctrl;
63 
64 static dif_pwrmgr_request_sources_t wakeup_sources;
65 
66 /**
67  * Initialize the peripherals used in this test.
68  */
69 static void init_peripherals(void) {
70  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
71 
72  CHECK_DIF_OK(dif_alert_handler_init_from_dt(kAlertHandlerDt, &alert_handler));
73 
74  // Initialize pwrmgr
75  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
76  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
77  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
78  kDtAonTimerWakeupWkupReq, &wakeup_sources));
79 
80  // Initialize aon_timer
81  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
82 
83  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
84 
85  CHECK_DIF_OK(dif_rv_core_ibex_init_from_dt(kRvCoreIbexDt, &ibex));
86 
87  CHECK_DIF_OK(dif_flash_ctrl_init_state_from_dt(&flash_ctrl, kFlashCtrlDt));
88 }
89 
90 /**
91  * A utility function to wait enough until the alert handler pings a peripheral
92  * alert
93  */
94 void wait_enough_for_alert_ping(void) {
95  // wait enough
97  // 2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz)
98  // 2*4*(2**16)*(400ns) = 0.2s
99  busy_spin_micros(1000 * 200);
100  } else if (kDeviceType == kDeviceSimDV) {
101  // NUM_ALERTS*2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz)
102  // 2*4*(2**3)*(40ns) = 3us
103  busy_spin_micros(3);
104  } else {
105  // Verilator
106  // 2*margin_of_safety*(2**DW)*(1/kClockFreqPeripheralHz)
107  // 2*4*(2**16)*(8us) = 4s
108  // This seems to be impractical for the current clock frequency config
109  // of the Verilator tests (kClockFreqPeripheralHz = 125K).
110  LOG_FATAL("SUPPORTED PLATFORMS: DV and FPGA");
111  LOG_FATAL("TO SUPPORT THE PLATFORM %d, COMPUTE THE RIGHT WAIT-TIME",
112  kDeviceType);
113  }
114 }
115 
116 // NVM counters/fields to keep test steps between deep sleep modes
117 enum {
118  // The counter ID for the non-volatile counter keeping the test steps.
119  kCounterTestSteps = 0,
120  // The counter ID for the non-volatile counter keeping num_iters for each
121  // test phase.
122  kCounterTestPhase = 1,
123 };
124 
125 /**
126  * Program the alert handler to escalate on alerts upto phase 1 (i.e. wipe
127  * secret) but not trigger reset. Then CPU can check if the correct interrupt
128  * fires and check the local alert cause register.
129  */
130 static void alert_handler_config(uint32_t ping_timeout) {
131  dif_alert_handler_alert_t alerts[ALERT_HANDLER_PARAM_N_ALERTS];
132  dif_alert_handler_class_t alert_classes[ALERT_HANDLER_PARAM_N_ALERTS];
133 
134  // Enable all incoming alerts and configure them to classa.
135  // This alert should never fire because we do not expect any incoming alerts.
136  for (dif_alert_handler_alert_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
137  alerts[i] = i;
138  alert_classes[i] = kDifAlertHandlerClassA;
139  }
140 
141  // Enable alert ping fail local alert and configure that to classb.
142  // Enable other local alerts and configure them to classa.
143  dif_alert_handler_local_alert_t loc_alerts[] = {
144  kDifAlertHandlerLocalAlertAlertPingFail,
145  kDifAlertHandlerLocalAlertAlertIntegrityFail,
146  kDifAlertHandlerLocalAlertBusIntegrityFail,
147  kDifAlertHandlerLocalAlertEscalationIntegrityFail,
148  kDifAlertHandlerLocalAlertEscalationPingFail,
149  kDifAlertHandlerLocalAlertShadowedStorageError,
150  kDifAlertHandlerLocalAlertShadowedUpdateError};
151  dif_alert_handler_class_t loc_alert_classes[] = {
152  kDifAlertHandlerClassB, kDifAlertHandlerClassA, kDifAlertHandlerClassA,
153  kDifAlertHandlerClassA, kDifAlertHandlerClassA, kDifAlertHandlerClassA,
154  kDifAlertHandlerClassA};
155 
156  dif_alert_handler_escalation_phase_t esc_phases[] = {
158  .signal = 0,
159  .duration_cycles = 2000}};
160 
161  dif_alert_handler_class_config_t class_config = {
163  .accumulator_threshold = 0,
164  .irq_deadline_cycles = 10000,
165  .escalation_phases = esc_phases,
166  .escalation_phases_len = ARRAYSIZE(esc_phases),
167  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
168  };
169 
170  dif_alert_handler_class_config_t class_configs[] = {class_config,
171  class_config};
172 
173  dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA,
174  kDifAlertHandlerClassB};
175  dif_alert_handler_config_t config = {
176  .alerts = alerts,
177  .alert_classes = alert_classes,
178  .alerts_len = ARRAYSIZE(alerts),
179  .local_alerts = loc_alerts,
180  .local_alert_classes = loc_alert_classes,
181  .local_alerts_len = ARRAYSIZE(loc_alerts),
182  .classes = classes,
183  .class_configs = class_configs,
184  .classes_len = ARRAYSIZE(class_configs),
185  .ping_timeout = ping_timeout,
186  };
187 
188  CHECK_STATUS_OK(alert_handler_testutils_configure_all(&alert_handler, config,
190  // Enables alert handler irq.
191  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
192  &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
193 
194  CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
195  &alert_handler, kDifAlertHandlerIrqClassb, kDifToggleEnabled));
196 }
197 
198 /**
199  * Clear all alert_cause and local_alert_cause registers
200  */
201 static void alert_handler_clear_cause_regs(void) {
202  // Loop over all alert_cause regs
203  for (dif_alert_handler_alert_t i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; i++) {
204  CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, i));
205  }
206 
207  // Loop over all loc_alert_cause regs
208  for (dif_alert_handler_local_alert_t i = 0; i < 7; i++) {
209  CHECK_DIF_OK(dif_alert_handler_local_alert_acknowledge(&alert_handler, i));
210  }
211 }
212 
213 /**
214  * Counts and returns the number of fired alerts
215  */
216 static uint16_t alert_handler_num_fired_alerts(void) {
217  bool is_cause;
218  // Indicates if any of the alerts or local alerts is fired.
219  uint16_t accumulator = 0;
220  // Loop over all alert_cause regs
221  for (size_t alert = 0; alert < ALERT_HANDLER_PARAM_N_ALERTS; alert++) {
222  CHECK_DIF_OK(
223  dif_alert_handler_alert_is_cause(&alert_handler, alert, &is_cause));
224  accumulator += is_cause;
225  }
226  return accumulator;
227 }
228 
229 /**
230  * Counts and returns the number of fired loc_alerts
231  */
232 static uint16_t alert_handler_num_fired_loc_alerts(void) {
233  bool is_cause;
234  // Indicates if any of the alerts or local alerts is fired.
235  uint16_t accumulator = 0;
236  // Loop over all loc_alert_cause regs
237  // Keep the result for kDifAlertHandlerLocalAlertAlertPingFail in a seperate
238  // variable
239  for (dif_alert_handler_local_alert_t i = 0; i < 7; i++) {
240  CHECK_DIF_OK(
241  dif_alert_handler_local_alert_is_cause(&alert_handler, i, &is_cause));
242  accumulator += is_cause;
243  }
244  return accumulator;
245 }
246 
247 /**
248  * Configures the power manager and enter a sleep mode
249  * @param deep_sleep: true => deep sleep, false => normal sleep
250  */
251 static void enter_low_power(bool deep_sleep) {
253  CHECK_DIF_OK(dif_pwrmgr_get_domain_config(&pwrmgr, &cfg));
255  kDifPwrmgrDomainOptionUsbClockInLowPower |
256  kDifPwrmgrDomainOptionUsbClockInActivePower)) |
257  (!deep_sleep ? kDifPwrmgrDomainOptionMainPowerInLowPower : 0);
258 
259  CHECK_STATUS_OK(
260  pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources, cfg));
262 }
263 
264 /**
265  * Verifies that wakeup source is the AON timer.
266  */
267 static void check_wakeup_reason(void) {
268  dif_pwrmgr_wakeup_reason_t wakeup_reason;
269  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
270  CHECK(UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, wakeup_sources)) ==
271  true,
272  "wakeup reason wrong exp:%d obs:%d", wakeup_sources, wakeup_reason);
273 }
274 
275 /**
276  * Clean up wakeup sources.
277  */
278 void cleanup_wakeup_src(void) {
279  CHECK_DIF_OK(dif_aon_timer_wakeup_stop(&aon_timer));
280  CHECK_DIF_OK(dif_aon_timer_clear_wakeup_cause(&aon_timer));
281  // Ensure the de-asserted events have cleared from the wakeup pipeline
282  // within 30us.
283  busy_spin_micros(30);
284  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_clear(&pwrmgr));
285 }
286 
287 // To keep the random number of iterations
288 static uint32_t rnd_num_iterations;
289 // To keep track of the test steps
290 static size_t test_step_cnt;
291 
292 /**
293  * Helper function to keep the test body clean
294  * Initializes the flash_ctrl and test counters.
295  * This is called once per reset.
296  */
297 void init_test_components(void) {
298  // Enable global and external IRQ at Ibex.
299  irq_global_ctrl(true);
300  irq_external_ctrl(true);
301 
302  init_peripherals();
303 
304  // Enable all the AON interrupts used in this test.
305  dif_rv_plic_irq_id_t plic_id =
306  dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup);
307  rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, plic_id, plic_id);
308 
309  // Enable pwrmgr interrupt
310  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
311 }
312 
313 /**
314  * Execute the test phases:
315  * Phase #1: Check if sleep/wakeup causes any spurious alerts
316  * Phase #2: Check if the ping mechanism keep working after sleep/wakeup cycles
317  */
318 static void execute_test_phases(uint8_t test_phase, uint32_t ping_timeout_cyc) {
319  // To keep the test results
320  bool is_cause;
321  bool is_locked;
322  bool sleep_mode;
323  uint16_t num_fired_alerts;
324  uint16_t num_fired_loc_alerts;
325 
326  // Need to configure the alert handler again after deep sleep
327  CHECK_DIF_OK(
328  dif_alert_handler_is_ping_timer_locked(&alert_handler, &is_locked));
329  // Configure the alert handler after wakeup if necessary
330  if (!is_locked) {
331  alert_handler_config(/*ping_timeout=*/ping_timeout_cyc);
332  }
333 
334  // Power-on reset
335  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
336  LOG_INFO("POR reset");
337  // Initialize the counters.
338  CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kCounterTestSteps));
339  CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kCounterTestPhase));
340  // set num_iterations to a random value between 4 and 8
341  rand_testutils_reseed();
342  rnd_num_iterations = rand_testutils_gen32_range(4, 8);
343  CHECK_STATUS_OK(
344  ret_sram_testutils_counter_set(kCounterTestPhase, rnd_num_iterations));
345  CHECK_STATUS_OK(
346  ret_sram_testutils_counter_get(kCounterTestSteps, &test_step_cnt));
347 
348  // Set the AON timer to send a wakeup signal in ~10-20us.
349  CHECK_STATUS_OK(aon_timer_testutils_wakeup_config(
350  &aon_timer, (uint32_t)rand_testutils_gen32_range(2, 4)));
351  // Enter normal sleep mode.
352  enter_low_power(/*deep_sleep=*/false);
353  } else { /*wakeup reset*/
354  LOG_INFO("Test phase = %d, test step = %d", test_phase, test_step_cnt);
355  // Check the wakeup reason and do the cleanup
356  check_wakeup_reason();
357  cleanup_wakeup_src();
358 
359  // Check if handler is locked after waking up from normal sleep.
360  CHECK_DIF_OK(
361  dif_alert_handler_is_ping_timer_locked(&alert_handler, &is_locked));
362  CHECK(
363  is_locked,
364  "The alert handler should be locked after waking up from normal sleep");
365 
366  // Check if sleep/wakeup cycle caused any spurious alerts.
367  //
368  // Phase#1: No alerts or loc_alerts shall be fired
369  // `ping_timeout_cnt = 256`. End the test if any alerts or loc_alerts is
370  // fired.
371  //
372  // Phase #2: N/A (As the `ping_timeout_cnt = 2` in this phase, the ping-fail
373  // alerts will come continuosly)
374  num_fired_alerts = alert_handler_num_fired_alerts();
375  num_fired_loc_alerts = alert_handler_num_fired_loc_alerts();
376  if (test_phase == 1) {
377  // No alerts is expected to fire
378  CHECK(num_fired_alerts == 0, "Phase #1: Expected_num_fired_alerts is 0");
379  CHECK(num_fired_loc_alerts == 0,
380  "Phase #1: Expected_num_fired_loc_alerts is 0");
381  }
382 
383  // Check that ping mechanism still works as expected after sleep/wakeup
384  // cycle
385  //
386  // Phase #1: No alerts or loc_alerts shall be fired
387  //
388  // Phase #2: new alerts shall be fired
389  // Phase #2: `kDifAlertHandlerLocalAlertAlertPingFail` shall be fired
390  // Phase #2: `kDifAlertHandlerLocalAlertEscalationPingFail` shall be fired.
391  if (test_phase == 1) {
392  // Wait for new pings
393  wait_enough_for_alert_ping();
394 
395  CHECK(alert_handler_num_fired_alerts() == 0,
396  "Phase #1: Expected_num_fired_alerts is 0");
397  CHECK(alert_handler_num_fired_loc_alerts() == 0,
398  "Phase #1: Expected_num_fired_loc_alerts is 0");
399  } else if (test_phase == 2) {
400  // Clear local_alert_cause and alert_cause regs for a clean start
401  // to test the ping-fail mechanism.
402  alert_handler_clear_cause_regs();
403 
404  // Wait for new pings
405  wait_enough_for_alert_ping();
406 
407  CHECK(alert_handler_num_fired_alerts() > 0,
408  "Phase #2: No new alerts has been fired after wakeup!");
409  CHECK(alert_handler_num_fired_loc_alerts() == 2,
410  "Phase #2: Only 2 loc_alerts (esc-ping-fail, alert-ping-fail) "
411  "should be fired!");
413  &alert_handler, kDifAlertHandlerLocalAlertAlertPingFail, &is_cause));
414  CHECK(is_cause,
415  "Phase #2: kDifAlertHandlerLocalAlertAlertPingFail must have been "
416  "fired");
418  &alert_handler, kDifAlertHandlerLocalAlertEscalationPingFail,
419  &is_cause));
420  CHECK(is_cause,
421  "Phase #2: kDifAlertHandlerLocalAlertEscalationPingFail must have "
422  "been fired");
423  } else {
424  LOG_FATAL("WRONG TEST PHASE!!");
425  }
426 
427  // Increment the test_step counter for the next test step
428  CHECK_STATUS_OK(ret_sram_testutils_counter_increment(kCounterTestSteps));
429  CHECK_STATUS_OK(
430  ret_sram_testutils_counter_get(kCounterTestSteps, &test_step_cnt));
431 
432  // Set the AON timer to send a wakeup signal in ~100-150us.
433  CHECK_STATUS_OK(aon_timer_testutils_wakeup_config(
434  &aon_timer, (uint32_t)rand_testutils_gen32_range(20, 30)));
435 
436  // Enter the normal sleep or deep sleep mode
437  // Deep sleep mode is time consuming in DV, and normal sleep mode is more
438  // important for the test. Therefore, the test goes to the deep sleep mode
439  // only once while transitioning from phase #1 to phase #2.
440  sleep_mode = (test_step_cnt == rnd_num_iterations);
441  enter_low_power(/*deep_sleep=*/sleep_mode);
442  }
443 }
444 
445 /**
446  * External interrupt handler.
447  */
448 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
449  dif_rv_plic_irq_id_t irq_id) {
450  if (devid == dt_pwrmgr_instance_id(kPwrmgrDt) &&
451  irq_id == dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup)) {
452  CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge(&pwrmgr, kDtPwrmgrIrqWakeup));
453  return true;
454  } else {
455  return false;
456  }
457 }
458 
459 /**
460  * Resets the chip.
461  */
462 static void chip_sw_reset(void) {
463  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
464  busy_spin_micros(100);
465  CHECK(false, "Should have reset before this line");
466 }
467 
468 bool test_main(void) {
469  init_test_components();
470 
471  ret_sram_testutils_init();
472 
473  dif_rstmgr_reset_info_bitfield_t rst_info = rstmgr_testutils_reason_get();
474  rstmgr_testutils_reason_clear();
475  if (rst_info & kDifRstmgrResetInfoPor) {
476  // Power-on reset
477  // if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
478  LOG_INFO("POR reset");
479  // Initialize the counters.
480  CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kCounterTestSteps));
481  CHECK_STATUS_OK(ret_sram_testutils_counter_clear(kCounterTestPhase));
482  // set num_iterations to a random value between 4 and 8
483  rand_testutils_reseed();
484  rnd_num_iterations = rand_testutils_gen32_range(4, 8);
485  CHECK_STATUS_OK(
486  ret_sram_testutils_counter_set(kCounterTestPhase, rnd_num_iterations));
487  LOG_INFO("Will run %d iterations per phase", rnd_num_iterations);
488  CHECK_STATUS_OK(
489  ret_sram_testutils_counter_get(kCounterTestSteps, &test_step_cnt));
490 
491  // We need to initialize the info FLASH partitions storing the Creator and
492  // Owner secrets to avoid getting the flash controller into a fatal error
493  // state.
494  if (kDeviceType == kDeviceFpgaCw310) {
495  CHECK_STATUS_OK(keymgr_testutils_flash_init(&flash_ctrl, &kCreatorSecret,
496  &kOwnerSecret));
497  chip_sw_reset();
498  }
499  }
500  CHECK_STATUS_OK(
501  ret_sram_testutils_counter_get(kCounterTestPhase, &rnd_num_iterations));
502  CHECK_STATUS_OK(
503  ret_sram_testutils_counter_get(kCounterTestSteps, &test_step_cnt));
504 
505  // TEST PHASE #1 (ping-timeout = 256)
506  // To ensure that the ping mechanism won't send spurious failure.
507  // No alert or local_alert is expected to be fired.
508  while (test_step_cnt < rnd_num_iterations) {
509  execute_test_phases(/*test_phase=*/1, /*ping_timeout_cyc=*/256);
510  }
511 
512  // TEST PHASE #2: ping_timeout = 1
513  // To ensure that ping mechanism will continue to send out pings after wakeup
514  // At least one of the alerts should cause a ping_timeout_fail event after
515  // wakeup.
516  while (test_step_cnt <= 2 * rnd_num_iterations) {
517  execute_test_phases(/*test_phase=*/2, /*ping_timeout_cyc=*/1);
518  }
519 
520  // Do the cleanup
521  cleanup_wakeup_src();
522 
523  return true;
524 }