Software APIs
sram_ctrl_lc_escalation_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 /**
6  * This test checks that SRAMs become inaccessible when an alert is escalated.
7  *
8  * The device side of this test:
9  *
10  * 1. Writes to and reads back data from both main and retention SRAM.
11  * 2. Configures the alert handlers to lock up the SRAMs for the LC bus
12  * bus integrity alert.
13  * 3. Forces that alert.
14  *
15  * This level of escalation also locks up ibex, so we cannot check the SRAMs
16  * from within this test. Instead, a test bench must try to access the SRAMs
17  * through the debug module.
18  */
19 
27 #include "sw/device/lib/testing/test_framework/check.h"
29 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
30 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
31 
33 #include "sram_ctrl_regs.h" // Generated.
34 
35 static const uint32_t kStatusRegMask = kDifSramCtrlStatusBusIntegErr |
38 
39 enum {
40  kCommandTimeoutMicros = 1 * 1000 * 1000,
41 };
42 
43 static dif_alert_handler_t alert_handler;
44 static dif_lc_ctrl_t lc_ctrl;
45 static dif_sram_ctrl_t sram_ctrl_main;
46 static dif_sram_ctrl_t sram_ctrl_ret;
47 
48 // Buffer to allow the compiler to allocate a safe area in Main SRAM where
49 // we can do the write/read test without the risk of clobbering data
50 // used by the program.
51 OT_SECTION(".data")
52 static volatile uint32_t sram_buffer_main;
53 
54 enum test_phase {
55  kTestPhaseCfg,
56  kTestPhaseEscalate,
57 };
58 static volatile uint8_t test_phase = kTestPhaseCfg;
59 
60 static volatile uintptr_t sram_buffer_addr_main;
61 static volatile uintptr_t sram_buffer_addr_ret;
62 
63 /// Write and read back a word of data to check SRAM is responsive.
64 static bool write_read_data(mmio_region_t sram_region, uint32_t data) {
65  mmio_region_write32(sram_region, 0, data);
66  uint32_t read_data = mmio_region_read32(sram_region, 0);
67 
68  return read_data == data;
69 }
70 
71 status_t configure_srams(void) {
72  uint32_t base_addr;
74  TRY(dif_sram_ctrl_init(mmio_region_from_addr(base_addr), &sram_ctrl_main));
76  TRY(dif_sram_ctrl_init(mmio_region_from_addr(base_addr), &sram_ctrl_ret));
77 
80 
81  // Check Status registers
82  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl_ret, &status_ret));
83  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl_main, &status_main));
84 
85  CHECK((status_main & kStatusRegMask) == 0x0,
86  "SRAM main status error bits set, status = %08x.", status_main);
87  CHECK((status_ret & kStatusRegMask) == 0x0,
88  "SRAM ret status error bits set, status = %08x.", status_ret);
89 
90  return OK_STATUS();
91 }
92 
93 status_t configure_alert_handler(void) {
94  TRY(dif_alert_handler_init(
96  &alert_handler));
97 
98  dif_alert_handler_escalation_phase_t esc_phases[] = {{
100  .signal = 1, // This level causes ibex and SRAMs to lock up.
101  .duration_cycles = UINT32_MAX,
102  }};
103 
104  dif_alert_handler_class_config_t class_config = {
106  .accumulator_threshold = 0,
107  .irq_deadline_cycles = 1000,
108  .escalation_phases = esc_phases,
109  .escalation_phases_len = ARRAYSIZE(esc_phases),
110  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
111  };
112 
115  kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
116  TRY(dif_alert_handler_configure_class(&alert_handler, kDifAlertHandlerClassA,
117  class_config, kDifToggleEnabled,
119 
120  return OK_STATUS();
121 }
122 
123 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
124 
125 bool test_main(void) {
126  CHECK_DIF_OK(dif_lc_ctrl_init(
128 
129  CHECK_STATUS_OK(configure_alert_handler());
130  CHECK_STATUS_OK(configure_srams());
131 
132  // Read and Write to/from SRAMs. Main SRAM will use the address of the
133  // buffer that has been allocated. Ret SRAM can start at the owner section.
134  sram_buffer_addr_main = (uintptr_t)&sram_buffer_main;
135  sram_buffer_addr_ret = TOP_EARLGREY_SRAM_CTRL_RET_AON_RAM_BASE_ADDR +
136  offsetof(retention_sram_t, owner);
137 
138  mmio_region_t sram_region_main = mmio_region_from_addr(sram_buffer_addr_main);
139  mmio_region_t sram_region_ret = mmio_region_from_addr(sram_buffer_addr_ret);
140 
141  // Write and read-back some data to both SRAMs to confirm they're responding.
142  CHECK(write_read_data(sram_region_main, 0x6b4abfae),
143  "main SRAM was not written to/read from correctly");
144  CHECK(write_read_data(sram_region_ret, 0x6b4abfae),
145  "retention SRAM was not written to/read from correctly");
146 
147  OTTF_WAIT_FOR(test_phase == kTestPhaseEscalate, kCommandTimeoutMicros);
148 
149  // Trigger an alert in the lifecycle controller.
150  CHECK_DIF_OK(
151  dif_lc_ctrl_alert_force(&lc_ctrl, kDifLcCtrlAlertFatalBusIntegError));
152 
153  // Ibex should have also locked up because of the alert so we don't expect
154  // to continue executing.
155  LOG_ERROR("Did not expect to execute after alert fired");
156  return false;
157 }