Software APIs
ibex_fi.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 "sw/device/tests/penetrationtests/firmware/fi/ibex_fi.h"
6 
8 #include "sw/device/lib/base/csr_registers.h"
10 #include "sw/device/lib/base/status.h"
13 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
16 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
17 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
18 #include "sw/device/lib/testing/sram_ctrl_testutils.h"
19 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
20 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
21 #include "sw/device/lib/ujson/ujson.h"
22 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
23 #include "sw/device/silicon_creator/manuf/lib/otp_fields.h"
24 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
25 #include "sw/device/tests/penetrationtests/json/ibex_fi_commands.h"
26 
28 #include "otp_ctrl_regs.h"
29 
30 // A function which takes an uint32_t as its only argument.
31 typedef uint32_t (*str_fn_t)(uint32_t);
32 
33 extern uint32_t increment_100x10(uint32_t start_value);
34 
35 extern uint32_t increment_100x1(uint32_t start_value);
36 
37 static str_fn_t increment_100x10_remapped = (str_fn_t)increment_100x10;
38 static str_fn_t increment_100x1_remapped = (str_fn_t)increment_100x1;
39 
40 // Interface to Ibex.
41 static dif_rv_core_ibex_t rv_core_ibex;
42 
43 // Interface to OTP.
44 static dif_otp_ctrl_t otp;
45 
46 // Indicates whether flash already was initialized for the test or not.
47 static bool flash_init;
48 // Indicates whether flash content is valid or not.
49 static bool flash_data_valid;
50 // Indicates whether ret SRAM already was initialized for the test or not.
51 static bool sram_ret_init;
52 // Indicates whether the otp arrays hold the valid reference values read from
53 // the OTP partitions.
54 static bool otp_ref_init;
55 
56 // Arrays holding the reference data read from the OTP VENDOR_TEST,
57 // CREATOR_SW_CFG, and OWNER_SW_CFG partitions.
58 uint32_t
59  otp_data_read_ref_vendor_test[(OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
60  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
61  sizeof(uint32_t)];
62 uint32_t otp_data_read_ref_creator_sw_cfg
63  [(OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
64  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
65  sizeof(uint32_t)];
66 uint32_t
67  otp_data_read_ref_owner_sw_cfg[(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
68  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
69  sizeof(uint32_t)];
70 
71 // Cond. branch macros.
72 #define CONDBRANCHBEQ "beq x5, x6, endfitestfaultybeq\n"
73 #define CONDBRANCHBNE "bne x5, x6, endfitestfaultybne\n"
74 #define CONDBRANCHBGE "bge x5, x6, endfitestfaultybge\n"
75 #define CONDBRANCHBGEU "bgeu x5, x6, endfitestfaultybgeu\n"
76 #define CONDBRANCHBLT "blt x5, x6, endfitestfaultyblt\n"
77 #define CONDBRANCHBLTU "bltu x5, x6, endfitestfaultybltu\n"
78 
79 // Init x5 = 0 macro.
80 #define INITX5 "addi x5, x0, 0"
81 
82 // Addi x5 = x5 + 1 macros.
83 #define ADDI1 "addi x5, x5, 1\n"
84 #define ADDI10 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1 ADDI1
85 #define ADDI100 \
86  ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10 ADDI10
87 #define ADDI1000 \
88  ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 ADDI100 \
89  ADDI100
90 
91 // Init tmpregs = 0 macro.
92 #define INIT_TMPREGS \
93  "addi x5, x0, 0\n addi x6, x0, 0\n addi x7, x0, 0\n" \
94  "addi x28, x0, 0\n addi x29, x0, 0\n addi x30, x0, 0\n"
95 
96 // Addi chain macro.
97 #define ADDI_CHAIN \
98  "addi x6, x5, 1\n addi x7, x6, 1\n addi x28, x7, 1\n" \
99  "addi x29, x28, 1\n addi x30, x29, 1\n addi x5, x30, 1\n"
100 
101 // Init x6 = 10000 macro.
102 #define INITX6 "li x6, 10000"
103 
104 // Subi x6 = x6 - 1 macro.
105 #define SUBI1 "addi x6, x6, -1\n"
106 
107 // Load word, addi, sw macro.
108 #define LWADDISW1 "lw x5, (%0)\n addi x5, x5, 1\n sw x5, (%0)\n"
109 #define LWADDISW10 \
110  LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 LWADDISW1 \
111  LWADDISW1 LWADDISW1 LWADDISW1
112 #define LWADDISW100 \
113  LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 LWADDISW10 \
114  LWADDISW10 LWADDISW10 LWADDISW10
115 #define LWADDISW1000 \
116  LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100 \
117  LWADDISW100 LWADDISW100 LWADDISW100 LWADDISW100
118 
119 // Load word, subi, sw macro.
120 #define LWSUBISW1 "lw x6, (%0)\n addi x6, x6, -1\n sw x6, (%0)\n"
121 
122 // Reference values.
123 const uint32_t ref_values[32] = {
124  0x1BADB002, 0x8BADF00D, 0xA5A5A5A5, 0xABABABAB, 0xABBABABE, 0xABADCAFE,
125  0xBAAAAAAD, 0xBAD22222, 0xBBADBEEF, 0xBEBEBEBE, 0xBEEFCACE, 0xC00010FF,
126  0xCAFED00D, 0xCAFEFEED, 0xCCCCCCCC, 0xCDCDCDCD, 0x0D15EA5E, 0xDEAD10CC,
127  0xDEADBEEF, 0xDEADCAFE, 0xDEADC0DE, 0xDEADFA11, 0xDEADF00D, 0xDEFEC8ED,
128  0xDEADDEAD, 0xD00D2BAD, 0xEBEBEBEB, 0xFADEDEAD, 0xFDFDFDFD, 0xFEE1DEAD,
129  0xFEEDFACE, 0xFEEEFEEE};
130 
131 // Flash information.
132 static dif_flash_ctrl_state_t flash;
133 static dif_flash_ctrl_device_info_t flash_info;
134 #define FLASH_PAGES_PER_BANK flash_info.data_pages
135 #define FLASH_WORD_SZ flash_info.bytes_per_word
136 #define FLASH_PAGE_SZ flash_info.bytes_per_page
137 #define FLASH_UINT32_WORDS_PER_PAGE \
138  (FLASH_PAGE_SZ / FLASH_WORD_SZ) * (FLASH_WORD_SZ / sizeof(uint32_t))
139 
140 // Buffer to allow the compiler to allocate a safe area in Main SRAM where
141 // we can do the write/read test without the risk of clobbering data
142 // used by the program.
143 OT_SECTION(".data")
144 static volatile uint32_t sram_main_buffer[256];
145 
146 // Make sure that this function does not get optimized by the compiler.
147 OT_USED
148 void increment_counter(void) __attribute__((optnone)) {
149  asm volatile("addi x5, x5, 1");
150 }
151 
152 static status_t init_ref_otp_data(void) {
153  // Fetch faulty-free reference values from OTP paritions.
154  if (!otp_ref_init) {
155  // Read VENDOR_TEST partition.
156  TRY(otp_ctrl_testutils_dai_read32_array(
157  &otp, kDifOtpCtrlPartitionVendorTest, 0, otp_data_read_ref_vendor_test,
158  (OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
159  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
160  sizeof(uint32_t)));
161 
162  // Read CREATOR_SW_CFG partition.
163  TRY(otp_ctrl_testutils_dai_read32_array(
165  otp_data_read_ref_creator_sw_cfg,
166  (OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
167  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
168  sizeof(uint32_t)));
169 
170  // READ OWNER_SW_CFG partition.
171  TRY(otp_ctrl_testutils_dai_read32_array(
172  &otp, kDifOtpCtrlPartitionOwnerSwCfg, 0, otp_data_read_ref_owner_sw_cfg,
173  (OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
174  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
175  sizeof(uint32_t)));
176  otp_ref_init = true;
177  }
178  return OK_STATUS();
179 }
180 
181 // Init temporary registers t0...t7 with given value.
182 static inline void init_temp_regs(uint32_t value) {
183  asm volatile("li x5, %0" : : "i"(value));
184  asm volatile("li x6, %0" : : "i"(value));
185  asm volatile("li x7, %0" : : "i"(value));
186  asm volatile("li x28, %0" : : "i"(value));
187  asm volatile("li x29, %0" : : "i"(value));
188  asm volatile("li x30, %0" : : "i"(value));
189  asm volatile("li x31, %0" : : "i"(value));
190 }
191 
192 static inline void init_reg_ref_values(void) {
193  asm volatile("li x5, %0" : : "i"(ref_values[0]));
194  asm volatile("li x6, %0" : : "i"(ref_values[1]));
195  asm volatile("li x7, %0" : : "i"(ref_values[2]));
196  asm volatile("li x12, %0" : : "i"(ref_values[3]));
197  asm volatile("li x13, %0" : : "i"(ref_values[4]));
198  asm volatile("li x14, %0" : : "i"(ref_values[5]));
199  asm volatile("li x15, %0" : : "i"(ref_values[6]));
200  asm volatile("li x16, %0" : : "i"(ref_values[7]));
201  asm volatile("li x17, %0" : : "i"(ref_values[8]));
202  asm volatile("li x28, %0" : : "i"(ref_values[9]));
203  asm volatile("li x29, %0" : : "i"(ref_values[10]));
204  asm volatile("li x30, %0" : : "i"(ref_values[11]));
205 }
206 
207 // Read back values from all registers x1...x31 into buffer.
208 static inline void read_all_regs(uint32_t buffer[]) {
209  // The much nicer approach with
210  // asm volatile("sw x1, %0" : : "m"(buffer[1]));
211  // leads to two INSNs. Test in godbolt promised single INSN
212  // Uglier workaround below inserts single INSN, but requires
213  // read_all_regs() to be called prior to the FI trigger
214  // start to avoid register overwrite.
215  asm volatile("sw x1, 0(%0)" : : "r"(&buffer[0]));
216  asm volatile("sw x2, 4(%0)" : : "r"(&buffer[0]));
217  asm volatile("sw x3, 8(%0)" : : "r"(&buffer[0]));
218  asm volatile("sw x4, 12(%0)" : : "r"(&buffer[0]));
219  asm volatile("sw x5, 16(%0)" : : "r"(&buffer[0]));
220  asm volatile("sw x6, 20(%0)" : : "r"(&buffer[0]));
221  asm volatile("sw x7, 24(%0)" : : "r"(&buffer[0]));
222  asm volatile("sw x8, 28(%0)" : : "r"(&buffer[0]));
223  asm volatile("sw x9, 32(%0)" : : "r"(&buffer[0]));
224  asm volatile("sw x10, 36(%0)" : : "r"(&buffer[0]));
225  asm volatile("sw x11, 40(%0)" : : "r"(&buffer[0]));
226  asm volatile("sw x12, 44(%0)" : : "r"(&buffer[0]));
227  asm volatile("sw x13, 48(%0)" : : "r"(&buffer[0]));
228  asm volatile("sw x14, 52(%0)" : : "r"(&buffer[0]));
229  asm volatile("sw x15, 56(%0)" : : "r"(&buffer[0]));
230  asm volatile("sw x16, 60(%0)" : : "r"(&buffer[0]));
231  asm volatile("sw x17, 64(%0)" : : "r"(&buffer[0]));
232  asm volatile("sw x18, 68(%0)" : : "r"(&buffer[0]));
233  asm volatile("sw x19, 72(%0)" : : "r"(&buffer[0]));
234  asm volatile("sw x20, 76(%0)" : : "r"(&buffer[0]));
235  asm volatile("sw x21, 80(%0)" : : "r"(&buffer[0]));
236  asm volatile("sw x22, 84(%0)" : : "r"(&buffer[0]));
237  asm volatile("sw x23, 88(%0)" : : "r"(&buffer[0]));
238  asm volatile("sw x24, 92(%0)" : : "r"(&buffer[0]));
239  asm volatile("sw x25, 96(%0)" : : "r"(&buffer[0]));
240  asm volatile("sw x26, 100(%0)" : : "r"(&buffer[0]));
241  asm volatile("sw x27, 104(%0)" : : "r"(&buffer[0]));
242  asm volatile("sw x28, 108(%0)" : : "r"(&buffer[0]));
243  asm volatile("sw x29, 112(%0)" : : "r"(&buffer[0]));
244  asm volatile("sw x30, 116(%0)" : : "r"(&buffer[0]));
245  asm volatile("sw x31, 120(%0)" : : "r"(&buffer[0]));
246 }
247 
248 static status_t read_otp_partitions(ujson_t *uj) {
249  // Clear registered alerts in alert handler.
250  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
251  // Clear the AST recoverable alerts.
252  pentest_clear_sensor_recov_alerts();
253 
254  uint32_t
255  otp_data_read_res_vendor_test[(OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
256  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
257  sizeof(uint32_t)];
258  uint32_t otp_data_read_res_creator_sw_cfg
259  [(OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
260  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
261  sizeof(uint32_t)];
262  uint32_t
263  otp_data_read_res_owner_sw_cfg[(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
264  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
265  sizeof(uint32_t)];
266 
267  pentest_set_trigger_high();
268  asm volatile(NOP10);
269  TRY(otp_ctrl_testutils_dai_read32_array(
270  &otp, kDifOtpCtrlPartitionVendorTest, 0, otp_data_read_res_vendor_test,
271  (OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
272  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
273  sizeof(uint32_t)));
274  TRY(otp_ctrl_testutils_dai_read32_array(
276  otp_data_read_res_creator_sw_cfg,
277  (OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE -
278  OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_SIZE) /
279  sizeof(uint32_t)));
280  TRY(otp_ctrl_testutils_dai_read32_array(
281  &otp, kDifOtpCtrlPartitionOwnerSwCfg, 0, otp_data_read_res_owner_sw_cfg,
282  (OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
283  OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
284  sizeof(uint32_t)));
285  asm volatile(NOP10);
286  pentest_set_trigger_low();
287 
288  // Get registered alerts from alert handler.
289  reg_alerts = pentest_get_triggered_alerts();
290  // Get fatal and recoverable AST alerts from sensor controller.
291  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
292 
293  // Detect potential mismatch caused by faults.
294  uint32_t res = 0;
295  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
296  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
297  sizeof(uint32_t));
298  i++) {
299  if (otp_data_read_ref_vendor_test[i] != otp_data_read_res_vendor_test[i]) {
300  res |= 1;
301  }
302  }
303 
304  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
305  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
306  sizeof(uint32_t));
307  i++) {
308  if (otp_data_read_ref_creator_sw_cfg[i] !=
309  otp_data_read_res_creator_sw_cfg[i]) {
310  res |= 2;
311  }
312  }
313 
314  for (size_t i = 0; i < ((OTP_CTRL_PARAM_VENDOR_TEST_SIZE -
315  OTP_CTRL_PARAM_VENDOR_TEST_DIGEST_SIZE) /
316  sizeof(uint32_t));
317  i++) {
318  if (otp_data_read_ref_owner_sw_cfg[i] !=
319  otp_data_read_res_owner_sw_cfg[i]) {
320  res |= 4;
321  }
322  }
323 
324  // Read ERR_STATUS register.
325  dif_rv_core_ibex_error_status_t codes;
326  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
327 
328  // Send res & ERR_STATUS to host.
329  ibex_fi_test_result_t uj_output;
330  uj_output.result = res;
331  uj_output.err_status = codes;
332  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
333  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
334  sizeof(sensor_alerts.alerts));
335  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
336 
337  return OK_STATUS();
338 }
339 
340 // Read back values fromo temporary registers t0...t7 into buffer.
341 static inline void read_temp_regs(uint32_t buffer[]) {
342  asm volatile("mv %0, x5" : "=r"(buffer[0]));
343  asm volatile("mv %0, x6" : "=r"(buffer[1]));
344  asm volatile("mv %0, x7" : "=r"(buffer[2]));
345  asm volatile("mv %0, x28" : "=r"(buffer[3]));
346  asm volatile("mv %0, x29" : "=r"(buffer[4]));
347  asm volatile("mv %0, x30" : "=r"(buffer[5]));
348  asm volatile("mv %0, x31" : "=r"(buffer[6]));
349 }
350 
351 // Make sure that this function does not get optimized by the compiler.
352 OT_USED
353 void not_increment_counter(void) __attribute__((optnone)) {
354  asm volatile("ret");
355  asm volatile(ADDI10);
356 }
357 
358 status_t handle_ibex_fi_address_translation(ujson_t *uj) {
359  // Clear registered alerts in alert handler.
360  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
361  // Clear the AST recoverable alerts.
362  pentest_clear_sensor_recov_alerts();
363 
364  // Create translation descriptions.
365  dif_rv_core_ibex_addr_translation_mapping_t increment_100x10_mapping = {
366  .matching_addr = (uintptr_t)increment_100x1,
367  .remap_addr = (uintptr_t)increment_100x10,
368  .size = 256,
369  };
370  dif_rv_core_ibex_addr_translation_mapping_t increment_100x1_mapping = {
371  .matching_addr = (uintptr_t)increment_100x10,
372  .remap_addr = (uintptr_t)increment_100x1,
373  .size = 256,
374  };
375 
376  // Configure slot 0 for the increment_100x10.
377  TRY(dif_rv_core_ibex_configure_addr_translation(
378  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
379  kDifRvCoreIbexAddrTranslationIBus, increment_100x10_mapping));
380  TRY(dif_rv_core_ibex_configure_addr_translation(
381  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
382  kDifRvCoreIbexAddrTranslationDBus, increment_100x10_mapping));
383 
384  // Configure slot 1 for the increment_100x1.
385  TRY(dif_rv_core_ibex_configure_addr_translation(
386  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
387  kDifRvCoreIbexAddrTranslationIBus, increment_100x1_mapping));
388  TRY(dif_rv_core_ibex_configure_addr_translation(
389  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
390  kDifRvCoreIbexAddrTranslationDBus, increment_100x1_mapping));
391 
392  // Enable the slots.
393  TRY(dif_rv_core_ibex_enable_addr_translation(
394  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
395  kDifRvCoreIbexAddrTranslationIBus));
396  TRY(dif_rv_core_ibex_enable_addr_translation(
397  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
398  kDifRvCoreIbexAddrTranslationDBus));
399 
400  TRY(dif_rv_core_ibex_enable_addr_translation(
401  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
402  kDifRvCoreIbexAddrTranslationIBus));
403  TRY(dif_rv_core_ibex_enable_addr_translation(
404  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
405  kDifRvCoreIbexAddrTranslationDBus));
406 
407  // FI code target.
408  uint32_t result_expected = 0;
409  pentest_set_trigger_high();
410  asm volatile(NOP100);
411  result_expected = increment_100x10_remapped(0);
412  pentest_set_trigger_low();
413  // Get registered alerts from alert handler.
414  reg_alerts = pentest_get_triggered_alerts();
415  // Get fatal and recoverable AST alerts from sensor controller.
416  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
417 
418  uint32_t result_target = increment_100x1_remapped(0);
419  // Compare values
420  uint32_t res = 0;
421  if (result_expected != 100) {
422  res = 1;
423  }
424 
425  if (result_target != 1000) {
426  res |= 1;
427  }
428 
429  // Read ERR_STATUS register.
430  dif_rv_core_ibex_error_status_t codes;
431  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
432 
433  // Send res & ERR_STATUS to host.
434  ibex_fi_test_result_t uj_output;
435  uj_output.result = res;
436  uj_output.err_status = codes;
437  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
438  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
439  sizeof(sensor_alerts.alerts));
440  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
441  return OK_STATUS();
442 }
443 
444 status_t handle_ibex_fi_address_translation_config(ujson_t *uj) {
445  // Clear registered alerts in alert handler.
446  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
447  // Clear the AST recoverable alerts.
448  pentest_clear_sensor_recov_alerts();
449 
450  // Address translation configuration.
452  .matching_addr = 0xa0000000,
453  .remap_addr = (uintptr_t)handle_ibex_fi_address_translation_config,
454  .size = 256,
455  };
456 
458  .matching_addr = 0xa0000000,
459  .remap_addr = (uintptr_t)handle_ibex_fi_address_translation_config,
460  .size = 256,
461  };
462 
463  // Write address translation configuration.
464  TRY(dif_rv_core_ibex_configure_addr_translation(
465  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
466  kDifRvCoreIbexAddrTranslationIBus, mapping1));
467 
468  // FI code target.
469  // Either slot 0 config, which is already written, or slot 1 config, which
470  // gets written is targeted using FI.
471  pentest_set_trigger_high();
472  TRY(dif_rv_core_ibex_configure_addr_translation(
473  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
474  kDifRvCoreIbexAddrTranslationDBus, mapping2));
475  asm volatile(NOP1000);
476  pentest_set_trigger_low();
477  // Get registered alerts from alert handler.
478  reg_alerts = pentest_get_triggered_alerts();
479  // Get fatal and recoverable AST alerts from sensor controller.
480  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
481 
482  // Read back address translation configuration.
485  TRY(dif_rv_core_ibex_read_addr_translation(
486  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_0,
487  kDifRvCoreIbexAddrTranslationIBus, &mapping1_read_back));
488  TRY(dif_rv_core_ibex_read_addr_translation(
489  &rv_core_ibex, kDifRvCoreIbexAddrTranslationSlot_1,
490  kDifRvCoreIbexAddrTranslationDBus, &mapping2_read_back));
491 
492  uint32_t res = 0;
493  // Compare mapping 1.
494  if ((mapping1_read_back.matching_addr != mapping1.matching_addr) ||
495  (mapping1_read_back.remap_addr != mapping1.remap_addr) ||
496  (mapping1_read_back.size != mapping1.size)) {
497  res = 1;
498  }
499 
500  // Compare mapping 2.
501  if ((mapping2_read_back.matching_addr != mapping2.matching_addr) ||
502  (mapping2_read_back.remap_addr != mapping2.remap_addr) ||
503  (mapping2_read_back.size != mapping2.size)) {
504  res = 1;
505  }
506 
507  // Read ERR_STATUS register.
508  dif_rv_core_ibex_error_status_t codes;
509  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
510 
511  // Send res & ERR_STATUS to host.
512  ibex_fi_test_result_t uj_output;
513  uj_output.result = res;
514  uj_output.err_status = codes;
515  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
516  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
517  sizeof(sensor_alerts.alerts));
518  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
519  return OK_STATUS();
520 }
521 
522 status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj)
523  __attribute__((optnone)) {
524  // Clear registered alerts in alert handler.
525  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
526  // Clear the AST recoverable alerts.
527  pentest_clear_sensor_recov_alerts();
528 
529  uint32_t result1 = 0;
530  uint32_t result2 = 0;
531 
532  asm volatile("addi x5, x0, 0xaf");
533  asm volatile("addi x6, x0, 0xef");
534 
535  // FI code target.
536  PENTEST_ASM_TRIGGER_HIGH
537  asm volatile(CONDBRANCHBEQ);
538  asm volatile(CONDBRANCHBEQ);
539  asm volatile(CONDBRANCHBEQ);
540  asm volatile(CONDBRANCHBEQ);
541  asm volatile(CONDBRANCHBEQ);
542  asm volatile(CONDBRANCHBEQ);
543  asm volatile(CONDBRANCHBEQ);
544  asm volatile(CONDBRANCHBEQ);
545  asm volatile(CONDBRANCHBEQ);
546  asm volatile(CONDBRANCHBEQ);
547  asm volatile(CONDBRANCHBEQ);
548  asm volatile(CONDBRANCHBEQ);
549  asm volatile(CONDBRANCHBEQ);
550  asm volatile(CONDBRANCHBEQ);
551  asm volatile(CONDBRANCHBEQ);
552  asm volatile(CONDBRANCHBEQ);
553  asm volatile(CONDBRANCHBEQ);
554  asm volatile(CONDBRANCHBEQ);
555  asm volatile(CONDBRANCHBEQ);
556  asm volatile(CONDBRANCHBEQ);
557  asm volatile(CONDBRANCHBEQ);
558  asm volatile(CONDBRANCHBEQ);
559  asm volatile(CONDBRANCHBEQ);
560  asm volatile(CONDBRANCHBEQ);
561  asm volatile(CONDBRANCHBEQ);
562  asm volatile(CONDBRANCHBEQ);
563  asm volatile(CONDBRANCHBEQ);
564  asm volatile(CONDBRANCHBEQ);
565  asm volatile(CONDBRANCHBEQ);
566  asm volatile(CONDBRANCHBEQ);
567  PENTEST_ASM_TRIGGER_LOW
568  asm volatile("mv %0, x5" : "=r"(result1));
569  asm volatile("mv %0, x6" : "=r"(result2));
570  asm volatile("beq x0, x0, endfitestbeq");
571  asm volatile(
572  "endfitestfaultybeq:\n"
573  "addi x5, x0, 0x11\n"
574  "addi x6, x0, 0x22");
575  asm volatile("mv %0, x5" : "=r"(result1));
576  asm volatile("mv %0, x6" : "=r"(result2));
577  asm volatile("endfitestbeq:\n");
578 
579  // Get registered alerts from alert handler.
580  reg_alerts = pentest_get_triggered_alerts();
581  // Get fatal and recoverable AST alerts from sensor controller.
582  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
583 
584  // Read ERR_STATUS register.
585  dif_rv_core_ibex_error_status_t codes;
586  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
587 
588  // Send loop counters & ERR_STATUS to host.
589  ibex_fi_test_result_mult_t uj_output;
590  uj_output.result1 = result1;
591  uj_output.result2 = result2;
592  uj_output.err_status = codes;
593  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
594  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
595  sizeof(sensor_alerts.alerts));
596  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
597  return OK_STATUS();
598 }
599 
600 status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj)
601  __attribute__((optnone)) {
602  // Clear registered alerts in alert handler.
603  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
604  // Clear the AST recoverable alerts.
605  pentest_clear_sensor_recov_alerts();
606 
607  uint32_t result1 = 0;
608  uint32_t result2 = 0;
609 
610  asm volatile("addi x5, x0, 0xaf");
611  asm volatile("addi x6, x0, 0xef");
612 
613  // FI code target.
614  PENTEST_ASM_TRIGGER_HIGH
615  asm volatile(CONDBRANCHBGE);
616  asm volatile(CONDBRANCHBGE);
617  asm volatile(CONDBRANCHBGE);
618  asm volatile(CONDBRANCHBGE);
619  asm volatile(CONDBRANCHBGE);
620  asm volatile(CONDBRANCHBGE);
621  asm volatile(CONDBRANCHBGE);
622  asm volatile(CONDBRANCHBGE);
623  asm volatile(CONDBRANCHBGE);
624  asm volatile(CONDBRANCHBGE);
625  asm volatile(CONDBRANCHBGE);
626  asm volatile(CONDBRANCHBGE);
627  asm volatile(CONDBRANCHBGE);
628  asm volatile(CONDBRANCHBGE);
629  asm volatile(CONDBRANCHBGE);
630  asm volatile(CONDBRANCHBGE);
631  asm volatile(CONDBRANCHBGE);
632  asm volatile(CONDBRANCHBGE);
633  asm volatile(CONDBRANCHBGE);
634  asm volatile(CONDBRANCHBGE);
635  asm volatile(CONDBRANCHBGE);
636  asm volatile(CONDBRANCHBGE);
637  asm volatile(CONDBRANCHBGE);
638  asm volatile(CONDBRANCHBGE);
639  asm volatile(CONDBRANCHBGE);
640  asm volatile(CONDBRANCHBGE);
641  asm volatile(CONDBRANCHBGE);
642  asm volatile(CONDBRANCHBGE);
643  asm volatile(CONDBRANCHBGE);
644  asm volatile(CONDBRANCHBGE);
645  PENTEST_ASM_TRIGGER_LOW
646  asm volatile("mv %0, x5" : "=r"(result1));
647  asm volatile("mv %0, x6" : "=r"(result2));
648  asm volatile("beq x0, x0, endfitestbge");
649  asm volatile(
650  "endfitestfaultybge:\n"
651  "addi x5, x0, 0x11\n"
652  "addi x6, x0, 0x22");
653  asm volatile("mv %0, x5" : "=r"(result1));
654  asm volatile("mv %0, x6" : "=r"(result2));
655  asm volatile("endfitestbge:\n");
656 
657  // Get registered alerts from alert handler.
658  reg_alerts = pentest_get_triggered_alerts();
659  // Get fatal and recoverable AST alerts from sensor controller.
660  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
661 
662  // Read ERR_STATUS register.
663  dif_rv_core_ibex_error_status_t codes;
664  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
665 
666  // Send loop counters & ERR_STATUS to host.
667  ibex_fi_test_result_mult_t uj_output;
668  uj_output.result1 = result1;
669  uj_output.result2 = result2;
670  uj_output.err_status = codes;
671  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
672  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
673  sizeof(sensor_alerts.alerts));
674  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
675  return OK_STATUS();
676 }
677 
678 status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj)
679  __attribute__((optnone)) {
680  // Clear registered alerts in alert handler.
681  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
682  // Clear the AST recoverable alerts.
683  pentest_clear_sensor_recov_alerts();
684 
685  uint32_t result1 = 0;
686  uint32_t result2 = 0;
687 
688  asm volatile("addi x5, x0, 0xaf");
689  asm volatile("addi x6, x0, 0xef");
690 
691  // FI code target.
692  PENTEST_ASM_TRIGGER_HIGH
693  asm volatile(CONDBRANCHBGEU);
694  asm volatile(CONDBRANCHBGEU);
695  asm volatile(CONDBRANCHBGEU);
696  asm volatile(CONDBRANCHBGEU);
697  asm volatile(CONDBRANCHBGEU);
698  asm volatile(CONDBRANCHBGEU);
699  asm volatile(CONDBRANCHBGEU);
700  asm volatile(CONDBRANCHBGEU);
701  asm volatile(CONDBRANCHBGEU);
702  asm volatile(CONDBRANCHBGEU);
703  asm volatile(CONDBRANCHBGEU);
704  asm volatile(CONDBRANCHBGEU);
705  asm volatile(CONDBRANCHBGEU);
706  asm volatile(CONDBRANCHBGEU);
707  asm volatile(CONDBRANCHBGEU);
708  asm volatile(CONDBRANCHBGEU);
709  asm volatile(CONDBRANCHBGEU);
710  asm volatile(CONDBRANCHBGEU);
711  asm volatile(CONDBRANCHBGEU);
712  asm volatile(CONDBRANCHBGEU);
713  asm volatile(CONDBRANCHBGEU);
714  asm volatile(CONDBRANCHBGEU);
715  asm volatile(CONDBRANCHBGEU);
716  asm volatile(CONDBRANCHBGEU);
717  asm volatile(CONDBRANCHBGEU);
718  asm volatile(CONDBRANCHBGEU);
719  asm volatile(CONDBRANCHBGEU);
720  asm volatile(CONDBRANCHBGEU);
721  asm volatile(CONDBRANCHBGEU);
722  asm volatile(CONDBRANCHBGEU);
723  PENTEST_ASM_TRIGGER_LOW
724  asm volatile("mv %0, x5" : "=r"(result1));
725  asm volatile("mv %0, x6" : "=r"(result2));
726  asm volatile("beq x0, x0, endfitestbgeu");
727  asm volatile(
728  "endfitestfaultybgeu:\n"
729  "addi x5, x0, 0x11\n"
730  "addi x6, x0, 0x22");
731  asm volatile("mv %0, x5" : "=r"(result1));
732  asm volatile("mv %0, x6" : "=r"(result2));
733  asm volatile("endfitestbgeu:\n");
734 
735  // Get registered alerts from alert handler.
736  reg_alerts = pentest_get_triggered_alerts();
737  // Get fatal and recoverable AST alerts from sensor controller.
738  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
739 
740  // Read ERR_STATUS register.
741  dif_rv_core_ibex_error_status_t codes;
742  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
743 
744  // Send loop counters & ERR_STATUS to host.
745  ibex_fi_test_result_mult_t uj_output;
746  uj_output.result1 = result1;
747  uj_output.result2 = result2;
748  uj_output.err_status = codes;
749  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
750  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
751  sizeof(sensor_alerts.alerts));
752  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
753  return OK_STATUS();
754 }
755 
756 status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj)
757  __attribute__((optnone)) {
758  // Clear registered alerts in alert handler.
759  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
760  // Clear the AST recoverable alerts.
761  pentest_clear_sensor_recov_alerts();
762 
763  uint32_t result1 = 0;
764  uint32_t result2 = 0;
765 
766  asm volatile("addi x5, x0, 0xef");
767  asm volatile("addi x6, x0, 0xaf");
768 
769  // FI code target.
770  PENTEST_ASM_TRIGGER_HIGH
771  asm volatile(CONDBRANCHBLT);
772  asm volatile(CONDBRANCHBLT);
773  asm volatile(CONDBRANCHBLT);
774  asm volatile(CONDBRANCHBLT);
775  asm volatile(CONDBRANCHBLT);
776  asm volatile(CONDBRANCHBLT);
777  asm volatile(CONDBRANCHBLT);
778  asm volatile(CONDBRANCHBLT);
779  asm volatile(CONDBRANCHBLT);
780  asm volatile(CONDBRANCHBLT);
781  asm volatile(CONDBRANCHBLT);
782  asm volatile(CONDBRANCHBLT);
783  asm volatile(CONDBRANCHBLT);
784  asm volatile(CONDBRANCHBLT);
785  asm volatile(CONDBRANCHBLT);
786  asm volatile(CONDBRANCHBLT);
787  asm volatile(CONDBRANCHBLT);
788  asm volatile(CONDBRANCHBLT);
789  asm volatile(CONDBRANCHBLT);
790  asm volatile(CONDBRANCHBLT);
791  asm volatile(CONDBRANCHBLT);
792  asm volatile(CONDBRANCHBLT);
793  asm volatile(CONDBRANCHBLT);
794  asm volatile(CONDBRANCHBLT);
795  asm volatile(CONDBRANCHBLT);
796  asm volatile(CONDBRANCHBLT);
797  asm volatile(CONDBRANCHBLT);
798  asm volatile(CONDBRANCHBLT);
799  asm volatile(CONDBRANCHBLT);
800  asm volatile(CONDBRANCHBLT);
801  PENTEST_ASM_TRIGGER_LOW
802  asm volatile("mv %0, x5" : "=r"(result1));
803  asm volatile("mv %0, x6" : "=r"(result2));
804  asm volatile("beq x0, x0, endfitestblt");
805  asm volatile(
806  "endfitestfaultyblt:\n"
807  "addi x5, x0, 0x11\n"
808  "addi x6, x0, 0x22");
809  asm volatile("mv %0, x5" : "=r"(result1));
810  asm volatile("mv %0, x6" : "=r"(result2));
811  asm volatile("endfitestblt:\n");
812 
813  // Get registered alerts from alert handler.
814  reg_alerts = pentest_get_triggered_alerts();
815  // Get fatal and recoverable AST alerts from sensor controller.
816  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
817 
818  // Read ERR_STATUS register.
819  dif_rv_core_ibex_error_status_t codes;
820  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
821 
822  // Send loop counters & ERR_STATUS to host.
823  ibex_fi_test_result_mult_t uj_output;
824  uj_output.result1 = result1;
825  uj_output.result2 = result2;
826  uj_output.err_status = codes;
827  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
828  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
829  sizeof(sensor_alerts.alerts));
830  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
831  return OK_STATUS();
832 }
833 
834 status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj)
835  __attribute__((optnone)) {
836  // Clear registered alerts in alert handler.
837  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
838  // Clear the AST recoverable alerts.
839  pentest_clear_sensor_recov_alerts();
840 
841  uint32_t result1 = 0;
842  uint32_t result2 = 0;
843 
844  asm volatile("addi x5, x0, 0xef");
845  asm volatile("addi x6, x0, 0xaf");
846 
847  // FI code target.
848  PENTEST_ASM_TRIGGER_HIGH
849  asm volatile(CONDBRANCHBLTU);
850  asm volatile(CONDBRANCHBLTU);
851  asm volatile(CONDBRANCHBLTU);
852  asm volatile(CONDBRANCHBLTU);
853  asm volatile(CONDBRANCHBLTU);
854  asm volatile(CONDBRANCHBLTU);
855  asm volatile(CONDBRANCHBLTU);
856  asm volatile(CONDBRANCHBLTU);
857  asm volatile(CONDBRANCHBLTU);
858  asm volatile(CONDBRANCHBLTU);
859  asm volatile(CONDBRANCHBLTU);
860  asm volatile(CONDBRANCHBLTU);
861  asm volatile(CONDBRANCHBLTU);
862  asm volatile(CONDBRANCHBLTU);
863  asm volatile(CONDBRANCHBLTU);
864  asm volatile(CONDBRANCHBLTU);
865  asm volatile(CONDBRANCHBLTU);
866  asm volatile(CONDBRANCHBLTU);
867  asm volatile(CONDBRANCHBLTU);
868  asm volatile(CONDBRANCHBLTU);
869  asm volatile(CONDBRANCHBLTU);
870  asm volatile(CONDBRANCHBLTU);
871  asm volatile(CONDBRANCHBLTU);
872  asm volatile(CONDBRANCHBLTU);
873  asm volatile(CONDBRANCHBLTU);
874  asm volatile(CONDBRANCHBLTU);
875  asm volatile(CONDBRANCHBLTU);
876  asm volatile(CONDBRANCHBLTU);
877  asm volatile(CONDBRANCHBLTU);
878  asm volatile(CONDBRANCHBLTU);
879  PENTEST_ASM_TRIGGER_LOW
880  asm volatile("mv %0, x5" : "=r"(result1));
881  asm volatile("mv %0, x6" : "=r"(result2));
882  asm volatile("beq x0, x0, endfitestbltu");
883  asm volatile(
884  "endfitestfaultybltu:\n"
885  "addi x5, x0, 0x11\n"
886  "addi x6, x0, 0x22");
887  asm volatile("mv %0, x5" : "=r"(result1));
888  asm volatile("mv %0, x6" : "=r"(result2));
889  asm volatile("endfitestbltu:\n");
890 
891  // Get registered alerts from alert handler.
892  reg_alerts = pentest_get_triggered_alerts();
893  // Get fatal and recoverable AST alerts from sensor controller.
894  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
895 
896  // Read ERR_STATUS register.
897  dif_rv_core_ibex_error_status_t codes;
898  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
899 
900  // Send loop counters & ERR_STATUS to host.
901  ibex_fi_test_result_mult_t uj_output;
902  uj_output.result1 = result1;
903  uj_output.result2 = result2;
904  uj_output.err_status = codes;
905  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
906  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
907  sizeof(sensor_alerts.alerts));
908  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
909  return OK_STATUS();
910 }
911 
912 status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj)
913  __attribute__((optnone)) {
914  // Clear registered alerts in alert handler.
915  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
916  // Clear the AST recoverable alerts.
917  pentest_clear_sensor_recov_alerts();
918 
919  uint32_t result1 = 0;
920  uint32_t result2 = 0;
921 
922  asm volatile("addi x5, x0, 0xaf");
923  asm volatile("addi x6, x0, 0xaf");
924 
925  // FI code target.
926  PENTEST_ASM_TRIGGER_HIGH
927  asm volatile(CONDBRANCHBNE);
928  asm volatile(CONDBRANCHBNE);
929  asm volatile(CONDBRANCHBNE);
930  asm volatile(CONDBRANCHBNE);
931  asm volatile(CONDBRANCHBNE);
932  asm volatile(CONDBRANCHBNE);
933  asm volatile(CONDBRANCHBNE);
934  asm volatile(CONDBRANCHBNE);
935  asm volatile(CONDBRANCHBNE);
936  asm volatile(CONDBRANCHBNE);
937  asm volatile(CONDBRANCHBNE);
938  asm volatile(CONDBRANCHBNE);
939  asm volatile(CONDBRANCHBNE);
940  asm volatile(CONDBRANCHBNE);
941  asm volatile(CONDBRANCHBNE);
942  asm volatile(CONDBRANCHBNE);
943  asm volatile(CONDBRANCHBNE);
944  asm volatile(CONDBRANCHBNE);
945  asm volatile(CONDBRANCHBNE);
946  asm volatile(CONDBRANCHBNE);
947  asm volatile(CONDBRANCHBNE);
948  asm volatile(CONDBRANCHBNE);
949  asm volatile(CONDBRANCHBNE);
950  asm volatile(CONDBRANCHBNE);
951  asm volatile(CONDBRANCHBNE);
952  asm volatile(CONDBRANCHBNE);
953  asm volatile(CONDBRANCHBNE);
954  asm volatile(CONDBRANCHBNE);
955  asm volatile(CONDBRANCHBNE);
956  asm volatile(CONDBRANCHBNE);
957  PENTEST_ASM_TRIGGER_LOW
958  asm volatile("mv %0, x5" : "=r"(result1));
959  asm volatile("mv %0, x6" : "=r"(result2));
960  asm volatile("beq x0, x0, endfitestbne");
961  asm volatile(
962  "endfitestfaultybne:\n"
963  "addi x5, x0, 0x11\n"
964  "addi x6, x0, 0x22");
965  asm volatile("mv %0, x5" : "=r"(result1));
966  asm volatile("mv %0, x6" : "=r"(result2));
967  asm volatile("endfitestbne:\n");
968 
969  // Get registered alerts from alert handler.
970  reg_alerts = pentest_get_triggered_alerts();
971  // Get fatal and recoverable AST alerts from sensor controller.
972  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
973 
974  // Read ERR_STATUS register.
975  dif_rv_core_ibex_error_status_t codes;
976  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
977 
978  // Send loop counters & ERR_STATUS to host.
979  ibex_fi_test_result_mult_t uj_output;
980  uj_output.result1 = result1;
981  uj_output.result2 = result2;
982  uj_output.err_status = codes;
983  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
984  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
985  sizeof(sensor_alerts.alerts));
986  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
987  return OK_STATUS();
988 }
989 
990 status_t handle_ibex_fi_char_csr_read(ujson_t *uj) {
991  // Clear registered alerts in alert handler.
992  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
993  // Clear the AST recoverable alerts.
994  pentest_clear_sensor_recov_alerts();
995 
996  // Write reference value into CSR.
997  CSR_WRITE(CSR_REG_MSCRATCH, ref_values[0]);
998 
999  // Init t0...t6 with 0.
1000  init_temp_regs(0);
1001 
1002  // FI code target.
1003  pentest_set_trigger_high();
1004  asm volatile(NOP10);
1005  asm volatile("csrr x5,mscratch");
1006  asm volatile("csrr x6,mscratch");
1007  asm volatile("csrr x7,mscratch");
1008  asm volatile("csrr x28,mscratch");
1009  asm volatile("csrr x29,mscratch");
1010  asm volatile("csrr x30,mscratch");
1011  asm volatile("csrr x31,mscratch");
1012  asm volatile(NOP10);
1013  pentest_set_trigger_low();
1014 
1015  // Load register values.
1016  // Result buffer.
1017  uint32_t res_values[7];
1018  read_temp_regs(res_values);
1019 
1020  // Get registered alerts from alert handler.
1021  reg_alerts = pentest_get_triggered_alerts();
1022  // Get fatal and recoverable AST alerts from sensor controller.
1023  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1024 
1025  // Compare against reference values.
1026  uint32_t res = 0;
1027  for (int i = 0; i < 7; i++) {
1028  if (res_values[i] != ref_values[0]) {
1029  res |= 1;
1030  }
1031  }
1032 
1033  // Read ERR_STATUS register.
1034  dif_rv_core_ibex_error_status_t codes;
1035  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1036 
1037  // Send res & ERR_STATUS to host.
1038  ibex_fi_test_result_t uj_output;
1039  uj_output.result = res;
1040  uj_output.err_status = codes;
1041  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1042  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1043  sizeof(sensor_alerts.alerts));
1044  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1045  return OK_STATUS();
1046 }
1047 
1048 status_t handle_ibex_fi_char_csr_write(ujson_t *uj) {
1049  ibex_fi_test_result_t uj_output;
1050  // Clear registered alerts in alert handler.
1051  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1052  // Clear the AST recoverable alerts.
1053  pentest_clear_sensor_recov_alerts();
1054 
1055  // Init x5 with reference value.
1056  asm volatile("li x5, %0" : : "i"(ref_values[0]));
1057 
1058  // FI code target.
1059  pentest_set_trigger_high();
1060  asm volatile(NOP10);
1061  asm volatile("csrw mscratch, x5");
1062  asm volatile("csrr x5,mscratch");
1063  asm volatile("csrw mscratch, x5");
1064  asm volatile("csrr x5,mscratch");
1065  asm volatile("csrw mscratch, x5");
1066  asm volatile("csrr x5,mscratch");
1067  asm volatile("csrw mscratch, x5");
1068  asm volatile("csrr x5,mscratch");
1069  asm volatile("csrw mscratch, x5");
1070  asm volatile("csrr x5,mscratch");
1071  asm volatile("csrw mscratch, x5");
1072  asm volatile("csrr x5,mscratch");
1073  asm volatile("csrw mscratch, x5");
1074  asm volatile("csrr x5,mscratch");
1075  asm volatile("csrw mscratch, x5");
1076  asm volatile("csrr x5,mscratch");
1077  asm volatile("csrw mscratch, x5");
1078  asm volatile("csrr x5,mscratch");
1079  asm volatile("csrw mscratch, x5");
1080  asm volatile("csrr x5,mscratch");
1081  asm volatile("csrw mscratch, x5");
1082  asm volatile("csrr x5,mscratch");
1083  asm volatile("csrw mscratch, x5");
1084  asm volatile("csrr x5,mscratch");
1085  asm volatile("csrw mscratch, x5");
1086  asm volatile("csrr x5,mscratch");
1087  asm volatile(NOP10);
1088  pentest_set_trigger_low();
1089 
1090  uint32_t res_value;
1091  asm volatile("mv %0, x5" : "=r"(res_value));
1092 
1093  // Get registered alerts from alert handler.
1094  reg_alerts = pentest_get_triggered_alerts();
1095  // Get fatal and recoverable AST alerts from sensor controller.
1096  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1097 
1098  // Compare against reference values.
1099  uj_output.result = 0;
1100  if (res_value != ref_values[0]) {
1101  uj_output.result = res_value;
1102  }
1103 
1104  // Read ERR_STATUS register.
1105  dif_rv_core_ibex_error_status_t codes;
1106  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1107 
1108  // Send res & ERR_STATUS to host.
1109  uj_output.err_status = codes;
1110  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1111  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1112  sizeof(sensor_alerts.alerts));
1113  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1114  return OK_STATUS();
1115 }
1116 
1117 status_t handle_ibex_fi_char_flash_read(ujson_t *uj) __attribute__((optnone)) {
1118  // Clear registered alerts in alert handler.
1119  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1120  // Clear the AST recoverable alerts.
1121  pentest_clear_sensor_recov_alerts();
1122 
1123  if (!flash_init) {
1124  // Configure the data flash.
1125  // Flash configuration.
1126  dif_flash_ctrl_region_properties_t region_properties = {
1127  .rd_en = kMultiBitBool4True,
1128  .prog_en = kMultiBitBool4True,
1129  .erase_en = kMultiBitBool4True,
1130  .scramble_en = kMultiBitBool4True,
1131  .ecc_en = kMultiBitBool4True,
1132  .high_endurance_en = kMultiBitBool4False};
1133 
1135  .base = FLASH_PAGES_PER_BANK,
1136  .size = 0x1,
1137  .properties = region_properties};
1138 
1139  dif_result_t res_prop =
1140  dif_flash_ctrl_set_data_region_properties(&flash, 2, data_region);
1141 
1142  dif_result_t res_en =
1144  if (res_prop == kDifLocked || res_en == kDifLocked) {
1145  LOG_INFO("Flash region locked.");
1146  }
1147 
1148  flash_init = true;
1149  }
1150 
1151  ptrdiff_t flash_bank_1_addr =
1152  (ptrdiff_t)flash_info.data_pages * (ptrdiff_t)flash_info.bytes_per_page;
1153  mmio_region_t flash_bank_1 = mmio_region_from_addr(
1154  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + (uintptr_t)flash_bank_1_addr);
1155 
1156  if (!flash_data_valid) {
1157  // Prepare page and write reference values into it.
1158  uint32_t input_page[FLASH_UINT32_WORDS_PER_PAGE];
1159  memset(input_page, 0x0, FLASH_UINT32_WORDS_PER_PAGE * sizeof(uint32_t));
1160  for (int i = 0; i < 32; i++) {
1161  input_page[i] = ref_values[i];
1162  }
1163 
1164  // Erase flash and write page with reference values.
1165  TRY(flash_ctrl_testutils_erase_and_write_page(
1166  &flash, (uint32_t)flash_bank_1_addr, /*partition_id=*/0, input_page,
1167  kDifFlashCtrlPartitionTypeData, FLASH_UINT32_WORDS_PER_PAGE));
1168 
1169  flash_data_valid = true;
1170  }
1171 
1172  // Init t0...t6 with 0.
1173  init_temp_regs(0);
1174 
1175  // FI code target.
1176  pentest_set_trigger_high();
1177  asm volatile(NOP10);
1178  asm volatile("lw x5, (%0)" : : "r"((flash_bank_1.base)));
1179  asm volatile("lw x6, (%0)" : : "r"((flash_bank_1.base)));
1180  asm volatile("lw x7, (%0)" : : "r"((flash_bank_1.base)));
1181  asm volatile("lw x28, (%0)" : : "r"((flash_bank_1.base)));
1182  asm volatile("lw x29, (%0)" : : "r"((flash_bank_1.base)));
1183  asm volatile("lw x30, (%0)" : : "r"((flash_bank_1.base)));
1184  asm volatile("lw x31, (%0)" : : "r"((flash_bank_1.base)));
1185  asm volatile(NOP10);
1186  pentest_set_trigger_low();
1187 
1188  // Load register values.
1189  // Result buffer.
1190  uint32_t res_values[7];
1191  read_temp_regs(res_values);
1192 
1193  // Get registered alerts from alert handler.
1194  reg_alerts = pentest_get_triggered_alerts();
1195  // Get fatal and recoverable AST alerts from sensor controller.
1196  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1197 
1198  // Compare against reference values.
1199  ibex_fi_faulty_addresses_data_t uj_output;
1200  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1201  memset(uj_output.data, 0, sizeof(uj_output.data));
1202 
1203  for (uint32_t flash_pos = 0; flash_pos < 7; flash_pos++) {
1204  if (res_values[flash_pos] != ref_values[0]) {
1205  uj_output.addresses[flash_pos] = flash_pos;
1206  uj_output.data[flash_pos] = res_values[flash_pos];
1207 
1208  // Re-init flash with valid data.
1209  flash_data_valid = false;
1210  }
1211  }
1212 
1213  // Read ERR_STATUS register.
1214  dif_rv_core_ibex_error_status_t codes;
1215  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1216 
1217  // Send res & ERR_STATUS to host.
1218  uj_output.err_status = codes;
1219  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1220  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1221  sizeof(sensor_alerts.alerts));
1222  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1223  return OK_STATUS();
1224 }
1225 
1226 status_t handle_ibex_fi_char_flash_write(ujson_t *uj) {
1227  // Clear registered alerts in alert handler.
1228  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1229  // Clear the AST recoverable alerts.
1230  pentest_clear_sensor_recov_alerts();
1231 
1232  if (!flash_init) {
1233  // Configure the data flash.
1234  // Flash configuration.
1235  dif_flash_ctrl_region_properties_t region_properties = {
1236  .rd_en = kMultiBitBool4True,
1237  .prog_en = kMultiBitBool4True,
1238  .erase_en = kMultiBitBool4True,
1239  .scramble_en = kMultiBitBool4True,
1240  .ecc_en = kMultiBitBool4True,
1241  .high_endurance_en = kMultiBitBool4False};
1243  .base = FLASH_PAGES_PER_BANK,
1244  .size = 0x1,
1245  .properties = region_properties};
1246  TRY(dif_flash_ctrl_set_data_region_properties(&flash, 2, data_region));
1249 
1250  flash_init = true;
1251  }
1252 
1253  ptrdiff_t flash_bank_1_addr =
1254  (ptrdiff_t)flash_info.data_pages * (ptrdiff_t)flash_info.bytes_per_page;
1255  mmio_region_t flash_bank_1 = mmio_region_from_addr(
1256  TOP_EARLGREY_FLASH_CTRL_MEM_BASE_ADDR + (uintptr_t)flash_bank_1_addr);
1257 
1258  // Prepare page and write reference values into it.
1259  uint32_t input_page[FLASH_UINT32_WORDS_PER_PAGE];
1260  memset(input_page, 0x0, FLASH_UINT32_WORDS_PER_PAGE * sizeof(uint32_t));
1261  for (int i = 0; i < 32; i++) {
1262  input_page[i] = ref_values[i];
1263  }
1264 
1265  // FI code target.
1266  pentest_set_trigger_high();
1267  // Erase flash and write page with reference values.
1268  TRY(flash_ctrl_testutils_erase_and_write_page(
1269  &flash, (uint32_t)flash_bank_1_addr, /*partition_id=*/0, input_page,
1270  kDifFlashCtrlPartitionTypeData, FLASH_UINT32_WORDS_PER_PAGE));
1271  pentest_set_trigger_low();
1272  // Get registered alerts from alert handler.
1273  reg_alerts = pentest_get_triggered_alerts();
1274  // Get fatal and recoverable AST alerts from sensor controller.
1275  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1276 
1277  // Read back and compare against reference values.
1278  uint32_t res_values[32];
1279  uint32_t res = 0;
1280  for (int i = 0; i < 32; i++) {
1281  res_values[i] =
1282  mmio_region_read32(flash_bank_1, i * (ptrdiff_t)sizeof(uint32_t));
1283  if (res_values[i] != ref_values[i]) {
1284  res |= 1;
1285  }
1286  }
1287 
1288  // Read ERR_STATUS register.
1289  dif_rv_core_ibex_error_status_t codes;
1290  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1291 
1292  // Send res & ERR_STATUS to host.
1293  ibex_fi_test_result_t uj_output;
1294  uj_output.result = res;
1295  uj_output.err_status = codes;
1296  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1297  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1298  sizeof(sensor_alerts.alerts));
1299  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1300  return OK_STATUS();
1301 }
1302 
1303 status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj)
1304  __attribute__((optnone)) {
1305  // Clear registered alerts in alert handler.
1306  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1307  // Clear the AST recoverable alerts.
1308  pentest_clear_sensor_recov_alerts();
1309 
1310  // Values are intentially not equal.
1311  // uint32_t value1 = 0;
1312  // uint32_t value2 = 1;
1313  // JH: Changed 28th June. Tests before used unharded values
1314  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1315  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1316 
1317  pentest_set_trigger_high();
1318  asm volatile(NOP10);
1319  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1320  // clang-format off
1321  asm volatile(
1322  "beq" " %0, %1, .L_HARDENED_%=;" \
1323  ".UNIMP_%=: unimp;" \
1324  "bne" " %0, %1, .UNIMP_%=;" \
1325  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2)
1326  );
1327  // clang-format on
1328  asm volatile(NOP10);
1329  pentest_set_trigger_low();
1330  // Get registered alerts from alert handler.
1331  reg_alerts = pentest_get_triggered_alerts();
1332  // Get fatal and recoverable AST alerts from sensor controller.
1333  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1334 
1335  // Read ERR_STATUS register.
1336  dif_rv_core_ibex_error_status_t codes;
1337  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1338 
1339  ibex_fi_test_result_mult_t uj_output;
1340  uj_output.err_status = codes;
1341  uj_output.result1 = value1;
1342  uj_output.result2 = value2;
1343  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1344  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1345  sizeof(sensor_alerts.alerts));
1346  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1347 
1348  return OK_STATUS();
1349 }
1350 
1351 status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj)
1352  __attribute__((optnone)) {
1353  // Clear registered alerts in alert handler.
1354  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1355  // Clear the AST recoverable alerts.
1356  pentest_clear_sensor_recov_alerts();
1357 
1358  // Values are intentially not equal.
1359  // uint32_t value1 = 0;
1360  // uint32_t value2 = 1;
1361  // JH: Changed 28th June. Tests before used unharded values
1362  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1363  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1364 
1365  pentest_set_trigger_high();
1366  asm volatile(NOP10);
1367  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1368  // clang-format off
1369  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1370  "unimp;" \
1371  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1372  // clang-format on
1373  asm volatile(NOP10);
1374  pentest_set_trigger_low();
1375  // Get registered alerts from alert handler.
1376  reg_alerts = pentest_get_triggered_alerts();
1377  // Get fatal and recoverable AST alerts from sensor controller.
1378  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1379 
1380  // Read ERR_STATUS register.
1381  dif_rv_core_ibex_error_status_t codes;
1382  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1383 
1384  ibex_fi_test_result_mult_t uj_output;
1385  uj_output.err_status = codes;
1386  uj_output.result1 = value1;
1387  uj_output.result2 = value2;
1388  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1389  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1390  sizeof(sensor_alerts.alerts));
1391  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1392 
1393  return OK_STATUS();
1394 }
1395 
1396 status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj)
1397  __attribute__((optnone)) {
1398  // Clear registered alerts in alert handler.
1399  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1400  // Clear the AST recoverable alerts.
1401  pentest_clear_sensor_recov_alerts();
1402 
1403  // Values are intentially not equal.
1404  // uint32_t value1 = 0;
1405  // uint32_t value2 = 1;
1406  // JH: Changed 28th June. Tests before used unharded values
1407  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1408  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1409 
1410  pentest_set_trigger_high();
1411  asm volatile(NOP10);
1412  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1413  // clang-format off
1414  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1415  "unimp; unimp;" \
1416  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1417  // clang-format on
1418  asm volatile(NOP10);
1419  pentest_set_trigger_low();
1420  // Get registered alerts from alert handler.
1421  reg_alerts = pentest_get_triggered_alerts();
1422  // Get fatal and recoverable AST alerts from sensor controller.
1423  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1424 
1425  // Read ERR_STATUS register.
1426  dif_rv_core_ibex_error_status_t codes;
1427  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1428 
1429  ibex_fi_test_result_mult_t uj_output;
1430  uj_output.err_status = codes;
1431  uj_output.result1 = value1;
1432  uj_output.result2 = value2;
1433  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1434  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1435  sizeof(sensor_alerts.alerts));
1436  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1437 
1438  return OK_STATUS();
1439 }
1440 
1441 status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj)
1442  __attribute__((optnone)) {
1443  // Clear registered alerts in alert handler.
1444  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1445  // Clear the AST recoverable alerts.
1446  pentest_clear_sensor_recov_alerts();
1447 
1448  // Values are intentially not equal.
1449  // uint32_t value1 = 0;
1450  // uint32_t value2 = 1;
1451  // JH: Changed 28th June. Tests before used unharded values
1452  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1453  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1454 
1455  pentest_set_trigger_high();
1456  asm volatile(NOP10);
1457  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1458  // clang-format off
1459  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1460  "unimp; unimp; unimp;" \
1461  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1462  // clang-format on
1463  asm volatile(NOP10);
1464  pentest_set_trigger_low();
1465  // Get registered alerts from alert handler.
1466  reg_alerts = pentest_get_triggered_alerts();
1467  // Get fatal and recoverable AST alerts from sensor controller.
1468  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1469 
1470  // Read ERR_STATUS register.
1471  dif_rv_core_ibex_error_status_t codes;
1472  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1473 
1474  ibex_fi_test_result_mult_t uj_output;
1475  uj_output.err_status = codes;
1476  uj_output.result1 = value1;
1477  uj_output.result2 = value2;
1478  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1479  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1480  sizeof(sensor_alerts.alerts));
1481  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1482 
1483  return OK_STATUS();
1484 }
1485 
1486 status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj)
1487  __attribute__((optnone)) {
1488  // Clear registered alerts in alert handler.
1489  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1490  // Clear the AST recoverable alerts.
1491  pentest_clear_sensor_recov_alerts();
1492 
1493  // Values are intentially not equal.
1494  // uint32_t value1 = 0;
1495  // uint32_t value2 = 1;
1496  // JH: Changed 28th June. Tests before used unharded values
1497  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1498  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1499 
1500  pentest_set_trigger_high();
1501  asm volatile(NOP10);
1502  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1503  // clang-format off
1504  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1505  "unimp; unimp; unimp; unimp;" \
1506  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1507  // clang-format on
1508  asm volatile(NOP10);
1509  pentest_set_trigger_low();
1510  // Get registered alerts from alert handler.
1511  reg_alerts = pentest_get_triggered_alerts();
1512  // Get fatal and recoverable AST alerts from sensor controller.
1513  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1514 
1515  // Read ERR_STATUS register.
1516  dif_rv_core_ibex_error_status_t codes;
1517  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1518 
1519  ibex_fi_test_result_mult_t uj_output;
1520  uj_output.err_status = codes;
1521  uj_output.result1 = value1;
1522  uj_output.result2 = value2;
1523  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1524  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1525  sizeof(sensor_alerts.alerts));
1526  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1527 
1528  return OK_STATUS();
1529 }
1530 
1531 status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj)
1532  __attribute__((optnone)) {
1533  // Clear registered alerts in alert handler.
1534  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1535  // Clear the AST recoverable alerts.
1536  pentest_clear_sensor_recov_alerts();
1537 
1538  // Values are intentially not equal.
1539  hardened_bool_t value1 = HARDENED_BOOL_TRUE;
1540  hardened_bool_t value2 = HARDENED_BOOL_FALSE;
1541 
1542  pentest_set_trigger_high();
1543  asm volatile(NOP10);
1544  // The HARDENED_CHECK macro from hardened.h is solved explicitely.
1545  // clang-format off
1546  asm volatile("beq" " %0, %1, .L_HARDENED_%=;" \
1547  "unimp; unimp; unimp; unimp; unimp;" \
1548  ".L_HARDENED_%=:;"::"r"(value1), "r"(value2) );
1549  // clang-format on
1550  asm volatile(NOP10);
1551  pentest_set_trigger_low();
1552  // Get registered alerts from alert handler.
1553  reg_alerts = pentest_get_triggered_alerts();
1554  // Get fatal and recoverable AST alerts from sensor controller.
1555  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1556 
1557  // Read ERR_STATUS register.
1558  dif_rv_core_ibex_error_status_t codes;
1559  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1560 
1561  ibex_fi_test_result_mult_t uj_output;
1562  uj_output.err_status = codes;
1563  uj_output.result1 = value1;
1564  uj_output.result2 = value2;
1565  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1566  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1567  sizeof(sensor_alerts.alerts));
1568  RESP_OK(ujson_serialize_ibex_fi_test_result_mult_t, uj, &uj_output);
1569 
1570  return OK_STATUS();
1571 }
1572 
1573 status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj) {
1574  // Clear registered alerts in alert handler.
1575  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1576  // Clear the AST recoverable alerts.
1577  pentest_clear_sensor_recov_alerts();
1578 
1579  // FI code target.
1580  uint32_t loop_counter1 = 0;
1581  uint32_t loop_counter2 = 10000;
1582  pentest_set_trigger_high();
1583  asm volatile(NOP100);
1584  for (int loop_cnt = 0; loop_cnt < 10000; loop_cnt++) {
1585  asm volatile(LWADDISW1 : : "r"((uint32_t *)&loop_counter1));
1586  asm volatile(LWSUBISW1 : : "r"((uint32_t *)&loop_counter2));
1587  }
1588  pentest_set_trigger_low();
1589  // Get registered alerts from alert handler.
1590  reg_alerts = pentest_get_triggered_alerts();
1591  // Get fatal and recoverable AST alerts from sensor controller.
1592  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1593 
1594  // Read ERR_STATUS register.
1595  dif_rv_core_ibex_error_status_t codes;
1596  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1597 
1598  // Send loop counters & ERR_STATUS to host.
1599  ibex_fi_loop_counter_mirrored_t uj_output;
1600  uj_output.loop_counter1 = loop_counter1;
1601  uj_output.loop_counter2 = loop_counter2;
1602  uj_output.err_status = codes;
1603  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1604  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1605  sizeof(sensor_alerts.alerts));
1606  RESP_OK(ujson_serialize_ibex_fi_loop_counter_mirrored_t, uj, &uj_output);
1607  return OK_STATUS();
1608 }
1609 
1610 status_t handle_ibex_fi_char_register_file(ujson_t *uj) {
1611  // Clear registered alerts in alert handler.
1612  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1613  // Clear the AST recoverable alerts.
1614  pentest_clear_sensor_recov_alerts();
1615 
1616  uint32_t res_values[12];
1617  // Initialize x5-x7, x12-x18, and x28-x30 with reference values.
1618  init_reg_ref_values();
1619 
1620  // FI code target.
1621  PENTEST_ASM_TRIGGER_HIGH
1622  asm volatile(NOP1000);
1623  PENTEST_ASM_TRIGGER_LOW;
1624 
1625  // Load register values.
1626  asm volatile("mv %0, x5" : "=r"(res_values[0]));
1627  asm volatile("mv %0, x6" : "=r"(res_values[1]));
1628  asm volatile("mv %0, x7" : "=r"(res_values[2]));
1629  asm volatile("mv %0, x12" : "=r"(res_values[3]));
1630  asm volatile("mv %0, x13" : "=r"(res_values[4]));
1631  asm volatile("mv %0, x14" : "=r"(res_values[5]));
1632  asm volatile("mv %0, x15" : "=r"(res_values[6]));
1633  asm volatile("mv %0, x16" : "=r"(res_values[7]));
1634  asm volatile("mv %0, x17" : "=r"(res_values[8]));
1635  asm volatile("mv %0, x28" : "=r"(res_values[9]));
1636  asm volatile("mv %0, x29" : "=r"(res_values[10]));
1637  asm volatile("mv %0, x30" : "=r"(res_values[11]));
1638 
1639  // Get registered alerts from alert handler.
1640  reg_alerts = pentest_get_triggered_alerts();
1641  // Get fatal and recoverable AST alerts from sensor controller.
1642  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1643 
1644  // Check if one or multiple registers values are faulty.
1645  uint32_t res = 0;
1646  for (int it = 0; it < 12; it++) {
1647  if (res_values[it] != ref_values[it]) {
1648  res |= 1;
1649  }
1650  }
1651 
1652  // Read ERR_STATUS register.
1653  dif_rv_core_ibex_error_status_t codes;
1654  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1655 
1656  // Send result & ERR_STATUS to host.
1657  ibex_fi_test_result_t uj_output;
1658  uj_output.result = res;
1659  uj_output.err_status = codes;
1660  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1661  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1662  sizeof(sensor_alerts.alerts));
1663  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
1664  return OK_STATUS();
1665 }
1666 
1667 status_t handle_ibex_fi_char_register_file_read(ujson_t *uj) {
1668  // Clear registered alerts in alert handler.
1669  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1670  // Clear the AST recoverable alerts.
1671  pentest_clear_sensor_recov_alerts();
1672 
1673  uint32_t res_values[14];
1674  // Initialize x5-x7, x12-x18, and x28-x30 with reference values.
1675  init_reg_ref_values();
1676 
1677  // FI code target.
1678  PENTEST_ASM_TRIGGER_HIGH
1679  asm volatile("or x5, x5, x5");
1680  asm volatile("or x6, x6, x6");
1681  asm volatile("or x7, x7, x7");
1682  asm volatile("or x12, x12, x12");
1683  asm volatile("or x13, x13, x13");
1684  asm volatile("or x14, x14, x14");
1685  asm volatile("or x15, x15, x15");
1686  asm volatile("or x16, x16, x16");
1687  asm volatile("or x17, x17, x17");
1688  asm volatile("or x28, x28, x28");
1689  asm volatile("or x29, x29, x29");
1690  asm volatile("or x30, x30, x30");
1691 
1692  asm volatile("or x5, x5, x5");
1693  asm volatile("or x6, x6, x6");
1694  asm volatile("or x7, x7, x7");
1695  asm volatile("or x12, x12, x12");
1696  asm volatile("or x13, x13, x13");
1697  asm volatile("or x14, x14, x14");
1698  asm volatile("or x15, x15, x15");
1699  asm volatile("or x16, x16, x16");
1700  asm volatile("or x17, x17, x17");
1701  asm volatile("or x28, x28, x28");
1702  asm volatile("or x29, x29, x29");
1703  asm volatile("or x30, x30, x30");
1704 
1705  asm volatile("or x5, x5, x5");
1706  asm volatile("or x6, x6, x6");
1707  asm volatile("or x7, x7, x7");
1708  asm volatile("or x12, x12, x12");
1709  asm volatile("or x13, x13, x13");
1710  asm volatile("or x14, x14, x14");
1711  asm volatile("or x15, x15, x15");
1712  asm volatile("or x16, x16, x16");
1713  asm volatile("or x17, x17, x17");
1714  asm volatile("or x28, x28, x28");
1715  asm volatile("or x29, x29, x29");
1716  asm volatile("or x30, x30, x30");
1717 
1718  asm volatile("or x5, x5, x5");
1719  asm volatile("or x6, x6, x6");
1720  asm volatile("or x7, x7, x7");
1721  asm volatile("or x12, x12, x12");
1722  asm volatile("or x13, x13, x13");
1723  asm volatile("or x14, x14, x14");
1724  asm volatile("or x15, x15, x15");
1725  asm volatile("or x16, x16, x16");
1726  asm volatile("or x17, x17, x17");
1727  asm volatile("or x28, x28, x28");
1728  asm volatile("or x29, x29, x29");
1729  asm volatile("or x30, x30, x30");
1730 
1731  asm volatile("or x5, x5, x5");
1732  asm volatile("or x6, x6, x6");
1733  asm volatile("or x7, x7, x7");
1734  asm volatile("or x12, x12, x12");
1735  asm volatile("or x13, x13, x13");
1736  asm volatile("or x14, x14, x14");
1737  asm volatile("or x15, x15, x15");
1738  asm volatile("or x16, x16, x16");
1739  asm volatile("or x17, x17, x17");
1740  asm volatile("or x28, x28, x28");
1741  asm volatile("or x29, x29, x29");
1742  asm volatile("or x30, x30, x30");
1743  PENTEST_ASM_TRIGGER_LOW
1744 
1745  // Load register values.
1746  asm volatile("mv %0, x5" : "=r"(res_values[0]));
1747  asm volatile("mv %0, x6" : "=r"(res_values[1]));
1748  asm volatile("mv %0, x7" : "=r"(res_values[2]));
1749  asm volatile("mv %0, x12" : "=r"(res_values[3]));
1750  asm volatile("mv %0, x13" : "=r"(res_values[4]));
1751  asm volatile("mv %0, x14" : "=r"(res_values[5]));
1752  asm volatile("mv %0, x15" : "=r"(res_values[6]));
1753  asm volatile("mv %0, x16" : "=r"(res_values[7]));
1754  asm volatile("mv %0, x17" : "=r"(res_values[8]));
1755  asm volatile("mv %0, x28" : "=r"(res_values[9]));
1756  asm volatile("mv %0, x29" : "=r"(res_values[10]));
1757  asm volatile("mv %0, x30" : "=r"(res_values[11]));
1758 
1759  // Get registered alerts from alert handler.
1760  reg_alerts = pentest_get_triggered_alerts();
1761  // Get fatal and recoverable AST alerts from sensor controller.
1762  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1763 
1764  // Check if one or multiple registers values are faulty.
1765  ibex_fi_faulty_addresses_data_t uj_output;
1766  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1767  memset(uj_output.data, 0, sizeof(uj_output.data));
1768  for (uint32_t it = 0; it < 12; it++) {
1769  if (res_values[it] != ref_values[it]) {
1770  uj_output.addresses[it] = 1; // 1 indicates an error in the register at
1771  // position it
1772  uj_output.data[it] = res_values[it];
1773  }
1774  }
1775 
1776  // Read ERR_STATUS register.
1777  dif_rv_core_ibex_error_status_t codes;
1778  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1779 
1780  // Send result & ERR_STATUS to host.
1781  uj_output.err_status = codes;
1782  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1783  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1784  sizeof(sensor_alerts.alerts));
1785  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1786  return OK_STATUS();
1787 }
1788 
1789 status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj) {
1790  // Clear registered alerts in alert handler.
1791  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1792  // Clear the AST recoverable alerts.
1793  pentest_clear_sensor_recov_alerts();
1794 
1795  // FI code target.
1796  uint32_t loop_counter1 = 0;
1797  uint32_t loop_counter2 = 10000;
1798  asm volatile(INITX5);
1799  asm volatile(INITX6);
1800  asm volatile(NOP100);
1801  PENTEST_ASM_TRIGGER_HIGH
1802  for (int loop_cnt = 0; loop_cnt < 10000; loop_cnt++) {
1803  asm volatile(ADDI1);
1804  asm volatile(SUBI1);
1805  }
1806  PENTEST_ASM_TRIGGER_LOW
1807  asm volatile("mv %0, x5" : "=r"(loop_counter1));
1808  asm volatile("mv %0, x6" : "=r"(loop_counter2));
1809 
1810  // Get registered alerts from alert handler.
1811  reg_alerts = pentest_get_triggered_alerts();
1812  // Get fatal and recoverable AST alerts from sensor controller.
1813  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1814 
1815  // Read ERR_STATUS register.
1816  dif_rv_core_ibex_error_status_t codes;
1817  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1818 
1819  // Send loop counters & ERR_STATUS to host.
1820  ibex_fi_loop_counter_mirrored_t uj_output;
1821  uj_output.loop_counter1 = loop_counter1;
1822  uj_output.loop_counter2 = loop_counter2;
1823  uj_output.err_status = codes;
1824  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1825  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1826  sizeof(sensor_alerts.alerts));
1827  RESP_OK(ujson_serialize_ibex_fi_loop_counter_mirrored_t, uj, &uj_output);
1828  return OK_STATUS();
1829 }
1830 
1831 status_t handle_ibex_fi_char_sram_read(ujson_t *uj) {
1832  // Clear registered alerts in alert handler.
1833  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1834  // Clear the AST recoverable alerts.
1835  pentest_clear_sensor_recov_alerts();
1836 
1837  // Init t0...t6 with 0.
1838  init_temp_regs(0);
1839 
1840  // Write reference value into SRAM.
1841  sram_main_buffer[0] = ref_values[0];
1842 
1843  // FI code target.
1844  pentest_set_trigger_high();
1845  asm volatile(NOP10);
1846  // Read from SRAM into temporary registers.
1847  asm volatile("lw x5, (%0)" : : "r"(&sram_main_buffer[0]));
1848  asm volatile("lw x6, (%0)" : : "r"(&sram_main_buffer[0]));
1849  asm volatile("lw x7, (%0)" : : "r"(&sram_main_buffer[0]));
1850  asm volatile("lw x28, (%0)" : : "r"(&sram_main_buffer[0]));
1851  asm volatile("lw x29, (%0)" : : "r"(&sram_main_buffer[0]));
1852  asm volatile("lw x30, (%0)" : : "r"(&sram_main_buffer[0]));
1853  asm volatile("lw x31, (%0)" : : "r"(&sram_main_buffer[0]));
1854  asm volatile(NOP10);
1855  pentest_set_trigger_low();
1856 
1857  // Load register values.
1858  // Result buffer.
1859  uint32_t res_values[7];
1860  read_temp_regs(res_values);
1861 
1862  // Get registered alerts from alert handler.
1863  reg_alerts = pentest_get_triggered_alerts();
1864  // Get fatal and recoverable AST alerts from sensor controller.
1865  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1866 
1867  ibex_fi_faulty_addresses_data_t uj_output;
1868  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1869  memset(uj_output.data, 0, sizeof(uj_output.data));
1870 
1871  for (uint32_t sram_pos = 0; sram_pos < 7; sram_pos++) {
1872  if (res_values[sram_pos] != ref_values[0]) {
1873  uj_output.addresses[sram_pos] = sram_pos;
1874  uj_output.data[sram_pos] = res_values[sram_pos];
1875  }
1876  }
1877 
1878  // Read ERR_STATUS register.
1879  dif_rv_core_ibex_error_status_t codes;
1880  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1881 
1882  // Send res & ERR_STATUS to host.
1883  uj_output.err_status = codes;
1884  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1885  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1886  sizeof(sensor_alerts.alerts));
1887  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1888  return OK_STATUS();
1889 }
1890 
1891 status_t handle_ibex_fi_char_sram_static(ujson_t *uj) {
1892  if (!sram_ret_init) {
1893  // Init retention SRAM, wipe and scramble it.
1894  dif_sram_ctrl_t ret_sram;
1895  mmio_region_t addr =
1897  TRY(dif_sram_ctrl_init(addr, &ret_sram));
1898  TRY(sram_ctrl_testutils_wipe(&ret_sram));
1899  TRY(sram_ctrl_testutils_scramble(&ret_sram));
1900  sram_ret_init = true;
1901  }
1902 
1903  int max_words = sizeof(retention_sram_owner_t) / sizeof(uint32_t);
1904 
1905  // Clear registered alerts in alert handler.
1906  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1907  // Clear the AST recoverable alerts.
1908  pentest_clear_sensor_recov_alerts();
1909 
1910  // Get address of the ret. SRAM at the beginning of the owner section.
1911  uintptr_t sram_ret_buffer_addr =
1913  offsetof(retention_sram_t, owner);
1914  mmio_region_t sram_region_ret_addr =
1915  mmio_region_from_addr(sram_ret_buffer_addr);
1916 
1917  // Write reference value into SRAM.
1918  for (int i = 0; i < max_words; i++) {
1919  mmio_region_write32(sram_region_ret_addr, i * (ptrdiff_t)sizeof(uint32_t),
1920  ref_values[0]);
1921  }
1922 
1923  // FI code target.
1924  pentest_set_trigger_high();
1925  asm volatile(NOP1000);
1926  pentest_set_trigger_low();
1927  // Get registered alerts from alert handler.
1928  reg_alerts = pentest_get_triggered_alerts();
1929  // Get fatal and recoverable AST alerts from sensor controller.
1930  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1931 
1932  // Compare against reference values.
1933  ibex_fi_faulty_addresses_data_t uj_output;
1934  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
1935  memset(uj_output.data, 0, sizeof(uj_output.data));
1936  int faulty_address_pos = 0;
1937  for (int sram_pos = 0; sram_pos < max_words; sram_pos++) {
1938  uint32_t res_value = mmio_region_read32(
1939  sram_region_ret_addr, sram_pos * (ptrdiff_t)sizeof(uint32_t));
1940  if (res_value != ref_values[0]) {
1941  uj_output.addresses[faulty_address_pos] = (uint32_t)sram_pos;
1942  uj_output.data[faulty_address_pos] = res_value;
1943  faulty_address_pos++;
1944  // Currently, we register only up to 8 faulty SRAM positions. If there
1945  // are more, we overwrite the addresses array.
1946  if (faulty_address_pos > 7) {
1947  faulty_address_pos = 0;
1948  }
1949  }
1950  }
1951 
1952  // Read ERR_STATUS register.
1953  dif_rv_core_ibex_error_status_t codes;
1954  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
1955 
1956  // Send res & ERR_STATUS to host.
1957  uj_output.err_status = codes;
1958  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
1959  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
1960  sizeof(sensor_alerts.alerts));
1961  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
1962  return OK_STATUS(0);
1963 }
1964 
1965 status_t handle_ibex_fi_char_sram_write(ujson_t *uj) {
1966  // Clear registered alerts in alert handler.
1967  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
1968  // Clear the AST recoverable alerts.
1969  pentest_clear_sensor_recov_alerts();
1970 
1971  // Get address of buffer located in SRAM.
1972  uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
1973  mmio_region_t sram_region_main_addr =
1974  mmio_region_from_addr(sram_main_buffer_addr);
1975 
1976  // Initialize SRAM region with inverse ref_values to avoid that data from a
1977  // previous run are still in memory.
1978  for (int i = 0; i < 32; i++) {
1979  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
1980  ~ref_values[i]);
1981  }
1982 
1983  // FI code target.
1984  pentest_set_trigger_high();
1985  for (int i = 0; i < 32; i++) {
1986  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
1987  ref_values[i]);
1988  }
1989  pentest_set_trigger_low();
1990  // Get registered alerts from alert handler.
1991  reg_alerts = pentest_get_triggered_alerts();
1992  // Get fatal and recoverable AST alerts from sensor controller.
1993  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
1994 
1995  // Read back and compare against reference values.
1996  uint32_t res_values[32];
1997  uint32_t res = 0;
1998  for (int i = 0; i < 32; i++) {
1999  res_values[i] = mmio_region_read32(sram_region_main_addr,
2000  i * (ptrdiff_t)sizeof(uint32_t));
2001  if (res_values[i] != ref_values[i]) {
2002  res |= 1;
2003  }
2004  }
2005 
2006  // Read ERR_STATUS register.
2007  dif_rv_core_ibex_error_status_t codes;
2008  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2009 
2010  // Send res & ERR_STATUS to host.
2011  ibex_fi_test_result_t uj_output;
2012  uj_output.result = res;
2013  uj_output.err_status = codes;
2014  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2015  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2016  sizeof(sensor_alerts.alerts));
2017  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2018  return OK_STATUS();
2019 }
2020 
2021 status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj)
2022  __attribute__((optnone)) {
2023  // Clear registered alerts in alert handler.
2024  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2025  // Clear the AST recoverable alerts.
2026  pentest_clear_sensor_recov_alerts();
2027 
2028  // Initialize SRAM region with inverse reference value.
2029  sram_main_buffer[0] = ~ref_values[0];
2030 
2031  // Init x5, x6, x6 with the reference values.
2032  asm volatile("li x5, %0" : : "i"(ref_values[0]));
2033  asm volatile("li x6, %0" : : "i"(ref_values[1]));
2034  asm volatile("li x7, %0" : : "i"(ref_values[2]));
2035 
2036  pentest_set_trigger_high();
2037  asm volatile(NOP10);
2038  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2039  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2040  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2041  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2042  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2043  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2044  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2045  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2046  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2047  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2048  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2049  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2050  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2051  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2052  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2053  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2054  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2055  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2056  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2057  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2058  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2059  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2060  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2061  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2062  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2063  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2064  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2065  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2066  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2067  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2068  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2069  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2070  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2071  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2072  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2073  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2074  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2075  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2076  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2077  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2078  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2079  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2080  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2081  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2082  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2083  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2084  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2085  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2086  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2087  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2088  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2089  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2090  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2091  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2092  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2093  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2094  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2095  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2096  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2097  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2098  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2099  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2100  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2101  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2102  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2103  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2104  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2105  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2106  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2107  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2108  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2109  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2110  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2111  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2112  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2113  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2114  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2115  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2116  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2117  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2118  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2119  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2120  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2121  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2122  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2123  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2124  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2125  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2126  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2127  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2128  asm volatile("sw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2129  asm volatile("lw x5, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2130  asm volatile("sw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2131  asm volatile("lw x6, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2132  asm volatile("sw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2133  asm volatile("lw x7, (%0)" : : "r"((uint32_t *)&sram_main_buffer[0]));
2134  asm volatile(NOP10);
2135  pentest_set_trigger_low();
2136  // Get registered alerts from alert handler.
2137  reg_alerts = pentest_get_triggered_alerts();
2138  // Get fatal and recoverable AST alerts from sensor controller.
2139  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2140 
2141  uint32_t res_values[3];
2142  asm volatile("mv %0, x5" : "=r"(res_values[0]));
2143  asm volatile("mv %0, x6" : "=r"(res_values[1]));
2144  asm volatile("mv %0, x7" : "=r"(res_values[2]));
2145 
2146  // Compare against reference values.
2147  ibex_fi_faulty_addresses_data_t uj_output;
2148  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
2149  memset(uj_output.data, 0, sizeof(uj_output.data));
2150 
2151  for (uint32_t addr = 0; addr < 3; addr++) {
2152  if (res_values[addr] != ref_values[addr]) {
2153  uj_output.addresses[addr] = (uint32_t)&sram_main_buffer[0];
2154  uj_output.data[addr] = res_values[addr];
2155  }
2156  }
2157 
2158  // Read ERR_STATUS register.
2159  dif_rv_core_ibex_error_status_t codes;
2160  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2161 
2162  // Send res & ERR_STATUS to host.
2163  uj_output.err_status = codes;
2164  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2165  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2166  sizeof(sensor_alerts.alerts));
2167  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
2168  return OK_STATUS();
2169 }
2170 
2171 status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj) {
2172  // Clear registered alerts in alert handler.
2173  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2174  // Clear the AST recoverable alerts.
2175  pentest_clear_sensor_recov_alerts();
2176 
2177  // Get address of buffer located in SRAM.
2178  uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
2179  mmio_region_t sram_region_main_addr =
2180  mmio_region_from_addr(sram_main_buffer_addr);
2181 
2182  // Initialize SRAM region with inverse ref_values to avoid that data from a
2183  // previous run are still in memory.
2184  for (int i = 0; i < 64; i++) {
2185  mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)sizeof(uint32_t),
2186  ~ref_values[0]);
2187  }
2188 
2189  // FI code target.
2190  // Unrolled for easier fault injection characterization.
2191  pentest_set_trigger_high();
2192  mmio_region_write32(sram_region_main_addr, 0 * (ptrdiff_t)sizeof(uint32_t),
2193  ref_values[0]);
2194  mmio_region_write32(sram_region_main_addr, 1 * (ptrdiff_t)sizeof(uint32_t),
2195  ref_values[0]);
2196  mmio_region_write32(sram_region_main_addr, 2 * (ptrdiff_t)sizeof(uint32_t),
2197  ref_values[0]);
2198  mmio_region_write32(sram_region_main_addr, 3 * (ptrdiff_t)sizeof(uint32_t),
2199  ref_values[0]);
2200  mmio_region_write32(sram_region_main_addr, 4 * (ptrdiff_t)sizeof(uint32_t),
2201  ref_values[0]);
2202  mmio_region_write32(sram_region_main_addr, 5 * (ptrdiff_t)sizeof(uint32_t),
2203  ref_values[0]);
2204  mmio_region_write32(sram_region_main_addr, 6 * (ptrdiff_t)sizeof(uint32_t),
2205  ref_values[0]);
2206  mmio_region_write32(sram_region_main_addr, 7 * (ptrdiff_t)sizeof(uint32_t),
2207  ref_values[0]);
2208  mmio_region_write32(sram_region_main_addr, 8 * (ptrdiff_t)sizeof(uint32_t),
2209  ref_values[0]);
2210  mmio_region_write32(sram_region_main_addr, 9 * (ptrdiff_t)sizeof(uint32_t),
2211  ref_values[0]);
2212  mmio_region_write32(sram_region_main_addr, 10 * (ptrdiff_t)sizeof(uint32_t),
2213  ref_values[0]);
2214  mmio_region_write32(sram_region_main_addr, 11 * (ptrdiff_t)sizeof(uint32_t),
2215  ref_values[0]);
2216  mmio_region_write32(sram_region_main_addr, 12 * (ptrdiff_t)sizeof(uint32_t),
2217  ref_values[0]);
2218  mmio_region_write32(sram_region_main_addr, 13 * (ptrdiff_t)sizeof(uint32_t),
2219  ref_values[0]);
2220  mmio_region_write32(sram_region_main_addr, 14 * (ptrdiff_t)sizeof(uint32_t),
2221  ref_values[0]);
2222  mmio_region_write32(sram_region_main_addr, 15 * (ptrdiff_t)sizeof(uint32_t),
2223  ref_values[0]);
2224  mmio_region_write32(sram_region_main_addr, 16 * (ptrdiff_t)sizeof(uint32_t),
2225  ref_values[0]);
2226  mmio_region_write32(sram_region_main_addr, 17 * (ptrdiff_t)sizeof(uint32_t),
2227  ref_values[0]);
2228  mmio_region_write32(sram_region_main_addr, 18 * (ptrdiff_t)sizeof(uint32_t),
2229  ref_values[0]);
2230  mmio_region_write32(sram_region_main_addr, 19 * (ptrdiff_t)sizeof(uint32_t),
2231  ref_values[0]);
2232  mmio_region_write32(sram_region_main_addr, 20 * (ptrdiff_t)sizeof(uint32_t),
2233  ref_values[0]);
2234  mmio_region_write32(sram_region_main_addr, 21 * (ptrdiff_t)sizeof(uint32_t),
2235  ref_values[0]);
2236  mmio_region_write32(sram_region_main_addr, 22 * (ptrdiff_t)sizeof(uint32_t),
2237  ref_values[0]);
2238  mmio_region_write32(sram_region_main_addr, 23 * (ptrdiff_t)sizeof(uint32_t),
2239  ref_values[0]);
2240  mmio_region_write32(sram_region_main_addr, 24 * (ptrdiff_t)sizeof(uint32_t),
2241  ref_values[0]);
2242  mmio_region_write32(sram_region_main_addr, 25 * (ptrdiff_t)sizeof(uint32_t),
2243  ref_values[0]);
2244  mmio_region_write32(sram_region_main_addr, 26 * (ptrdiff_t)sizeof(uint32_t),
2245  ref_values[0]);
2246  mmio_region_write32(sram_region_main_addr, 27 * (ptrdiff_t)sizeof(uint32_t),
2247  ref_values[0]);
2248  mmio_region_write32(sram_region_main_addr, 28 * (ptrdiff_t)sizeof(uint32_t),
2249  ref_values[0]);
2250  mmio_region_write32(sram_region_main_addr, 29 * (ptrdiff_t)sizeof(uint32_t),
2251  ref_values[0]);
2252  mmio_region_write32(sram_region_main_addr, 30 * (ptrdiff_t)sizeof(uint32_t),
2253  ref_values[0]);
2254  mmio_region_write32(sram_region_main_addr, 31 * (ptrdiff_t)sizeof(uint32_t),
2255  ref_values[0]);
2256  mmio_region_write32(sram_region_main_addr, 32 * (ptrdiff_t)sizeof(uint32_t),
2257  ref_values[0]);
2258  mmio_region_write32(sram_region_main_addr, 33 * (ptrdiff_t)sizeof(uint32_t),
2259  ref_values[0]);
2260  mmio_region_write32(sram_region_main_addr, 34 * (ptrdiff_t)sizeof(uint32_t),
2261  ref_values[0]);
2262  mmio_region_write32(sram_region_main_addr, 35 * (ptrdiff_t)sizeof(uint32_t),
2263  ref_values[0]);
2264  mmio_region_write32(sram_region_main_addr, 36 * (ptrdiff_t)sizeof(uint32_t),
2265  ref_values[0]);
2266  mmio_region_write32(sram_region_main_addr, 37 * (ptrdiff_t)sizeof(uint32_t),
2267  ref_values[0]);
2268  mmio_region_write32(sram_region_main_addr, 38 * (ptrdiff_t)sizeof(uint32_t),
2269  ref_values[0]);
2270  mmio_region_write32(sram_region_main_addr, 39 * (ptrdiff_t)sizeof(uint32_t),
2271  ref_values[0]);
2272  mmio_region_write32(sram_region_main_addr, 40 * (ptrdiff_t)sizeof(uint32_t),
2273  ref_values[0]);
2274  mmio_region_write32(sram_region_main_addr, 41 * (ptrdiff_t)sizeof(uint32_t),
2275  ref_values[0]);
2276  mmio_region_write32(sram_region_main_addr, 42 * (ptrdiff_t)sizeof(uint32_t),
2277  ref_values[0]);
2278  mmio_region_write32(sram_region_main_addr, 43 * (ptrdiff_t)sizeof(uint32_t),
2279  ref_values[0]);
2280  mmio_region_write32(sram_region_main_addr, 44 * (ptrdiff_t)sizeof(uint32_t),
2281  ref_values[0]);
2282  mmio_region_write32(sram_region_main_addr, 45 * (ptrdiff_t)sizeof(uint32_t),
2283  ref_values[0]);
2284  mmio_region_write32(sram_region_main_addr, 46 * (ptrdiff_t)sizeof(uint32_t),
2285  ref_values[0]);
2286  mmio_region_write32(sram_region_main_addr, 47 * (ptrdiff_t)sizeof(uint32_t),
2287  ref_values[0]);
2288  mmio_region_write32(sram_region_main_addr, 48 * (ptrdiff_t)sizeof(uint32_t),
2289  ref_values[0]);
2290  mmio_region_write32(sram_region_main_addr, 49 * (ptrdiff_t)sizeof(uint32_t),
2291  ref_values[0]);
2292  mmio_region_write32(sram_region_main_addr, 50 * (ptrdiff_t)sizeof(uint32_t),
2293  ref_values[0]);
2294  mmio_region_write32(sram_region_main_addr, 51 * (ptrdiff_t)sizeof(uint32_t),
2295  ref_values[0]);
2296  mmio_region_write32(sram_region_main_addr, 52 * (ptrdiff_t)sizeof(uint32_t),
2297  ref_values[0]);
2298  mmio_region_write32(sram_region_main_addr, 53 * (ptrdiff_t)sizeof(uint32_t),
2299  ref_values[0]);
2300  mmio_region_write32(sram_region_main_addr, 54 * (ptrdiff_t)sizeof(uint32_t),
2301  ref_values[0]);
2302  mmio_region_write32(sram_region_main_addr, 55 * (ptrdiff_t)sizeof(uint32_t),
2303  ref_values[0]);
2304  mmio_region_write32(sram_region_main_addr, 56 * (ptrdiff_t)sizeof(uint32_t),
2305  ref_values[0]);
2306  mmio_region_write32(sram_region_main_addr, 57 * (ptrdiff_t)sizeof(uint32_t),
2307  ref_values[0]);
2308  mmio_region_write32(sram_region_main_addr, 58 * (ptrdiff_t)sizeof(uint32_t),
2309  ref_values[0]);
2310  mmio_region_write32(sram_region_main_addr, 59 * (ptrdiff_t)sizeof(uint32_t),
2311  ref_values[0]);
2312  mmio_region_write32(sram_region_main_addr, 60 * (ptrdiff_t)sizeof(uint32_t),
2313  ref_values[0]);
2314  mmio_region_write32(sram_region_main_addr, 61 * (ptrdiff_t)sizeof(uint32_t),
2315  ref_values[0]);
2316  mmio_region_write32(sram_region_main_addr, 62 * (ptrdiff_t)sizeof(uint32_t),
2317  ref_values[0]);
2318  mmio_region_write32(sram_region_main_addr, 63 * (ptrdiff_t)sizeof(uint32_t),
2319  ref_values[0]);
2320  pentest_set_trigger_low();
2321  // Get registered alerts from alert handler.
2322  reg_alerts = pentest_get_triggered_alerts();
2323  // Get fatal and recoverable AST alerts from sensor controller.
2324  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2325 
2326  // Read back and compare against reference values.
2327  uint32_t res_values[64];
2328  uint32_t res = 0;
2329  for (int i = 0; i < 64; i++) {
2330  res_values[i] = mmio_region_read32(sram_region_main_addr,
2331  i * (ptrdiff_t)sizeof(uint32_t));
2332  if (res_values[i] != ref_values[0]) {
2333  res |= 1;
2334  }
2335  }
2336 
2337  // Read ERR_STATUS register.
2338  dif_rv_core_ibex_error_status_t codes;
2339  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2340 
2341  // Send res & ERR_STATUS to host.
2342  ibex_fi_test_result_t uj_output;
2343  uj_output.result = res;
2344  uj_output.err_status = codes;
2345  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2346  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2347  sizeof(sensor_alerts.alerts));
2348  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2349  return OK_STATUS();
2350 }
2351 
2352 status_t handle_ibex_fi_char_unconditional_branch(ujson_t *uj) {
2353  // Clear registered alerts in alert handler.
2354  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2355  // Clear the AST recoverable alerts.
2356  pentest_clear_sensor_recov_alerts();
2357 
2358  uint32_t result = 0;
2359  // Init x5 register we are using for the increment.
2360  asm volatile(INITX5);
2361 
2362  // FI code target.
2363  PENTEST_ASM_TRIGGER_HIGH
2364  // Attack target.
2365  asm volatile("jal ra, increment_counter");
2366  asm volatile("jal ra, increment_counter");
2367  asm volatile("jal ra, increment_counter");
2368  asm volatile("jal ra, increment_counter");
2369  asm volatile("jal ra, increment_counter");
2370  asm volatile("jal ra, increment_counter");
2371  asm volatile("jal ra, increment_counter");
2372  asm volatile("jal ra, increment_counter");
2373  asm volatile("jal ra, increment_counter");
2374  asm volatile("jal ra, increment_counter");
2375  asm volatile("jal ra, increment_counter");
2376  asm volatile("jal ra, increment_counter");
2377  asm volatile("jal ra, increment_counter");
2378  asm volatile("jal ra, increment_counter");
2379  asm volatile("jal ra, increment_counter");
2380  asm volatile("jal ra, increment_counter");
2381  asm volatile("jal ra, increment_counter");
2382  asm volatile("jal ra, increment_counter");
2383  asm volatile("jal ra, increment_counter");
2384  asm volatile("jal ra, increment_counter");
2385  asm volatile("jal ra, increment_counter");
2386  asm volatile("jal ra, increment_counter");
2387  asm volatile("jal ra, increment_counter");
2388  asm volatile("jal ra, increment_counter");
2389  asm volatile("jal ra, increment_counter");
2390  asm volatile("jal ra, increment_counter");
2391  asm volatile("jal ra, increment_counter");
2392  asm volatile("jal ra, increment_counter");
2393  asm volatile("jal ra, increment_counter");
2394  asm volatile("jal ra, increment_counter");
2395  PENTEST_ASM_TRIGGER_LOW
2396  asm volatile("mv %0, x5" : "=r"(result));
2397 
2398  // Get registered alerts from alert handler.
2399  reg_alerts = pentest_get_triggered_alerts();
2400  // Get fatal and recoverable AST alerts from sensor controller.
2401  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2402 
2403  // Read ERR_STATUS register.
2404  dif_rv_core_ibex_error_status_t codes;
2405  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2406 
2407  // Send loop counters & ERR_STATUS to host.
2408  ibex_fi_test_result_t uj_output;
2409  uj_output.result = result;
2410  uj_output.err_status = codes;
2411  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2412  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2413  sizeof(sensor_alerts.alerts));
2414  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2415  return OK_STATUS();
2416 }
2417 
2418 status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj) {
2419  uint32_t registers[32] = {0};
2420  read_all_regs(registers);
2421  // Clear registered alerts in alert handler.
2422  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2423  // Clear the AST recoverable alerts.
2424  pentest_clear_sensor_recov_alerts();
2425 
2426  uint32_t result = 0;
2427  // Init x5 register we are using for the increment.
2428  asm volatile(INITX5);
2429 
2430  // FI code target.
2431  PENTEST_ASM_TRIGGER_HIGH
2432  // Attack target.
2433  asm volatile("jal ra, not_increment_counter");
2434  asm volatile("jal ra, not_increment_counter");
2435  asm volatile("jal ra, not_increment_counter");
2436  asm volatile("jal ra, not_increment_counter");
2437  asm volatile("jal ra, not_increment_counter");
2438  asm volatile("jal ra, not_increment_counter");
2439  asm volatile("jal ra, not_increment_counter");
2440  asm volatile("jal ra, not_increment_counter");
2441  asm volatile("jal ra, not_increment_counter");
2442  asm volatile("jal ra, not_increment_counter");
2443  asm volatile("jal ra, not_increment_counter");
2444  asm volatile("jal ra, not_increment_counter");
2445  asm volatile("jal ra, not_increment_counter");
2446  asm volatile("jal ra, not_increment_counter");
2447  asm volatile("jal ra, not_increment_counter");
2448  asm volatile("jal ra, not_increment_counter");
2449  asm volatile("jal ra, not_increment_counter");
2450  asm volatile("jal ra, not_increment_counter");
2451  asm volatile("jal ra, not_increment_counter");
2452  asm volatile("jal ra, not_increment_counter");
2453  asm volatile("jal ra, not_increment_counter");
2454  asm volatile("jal ra, not_increment_counter");
2455  asm volatile("jal ra, not_increment_counter");
2456  asm volatile("jal ra, not_increment_counter");
2457  asm volatile("jal ra, not_increment_counter");
2458  asm volatile("jal ra, not_increment_counter");
2459  asm volatile("jal ra, not_increment_counter");
2460  asm volatile("jal ra, not_increment_counter");
2461  asm volatile("jal ra, not_increment_counter");
2462  asm volatile("jal ra, not_increment_counter");
2463  PENTEST_ASM_TRIGGER_LOW
2464  read_all_regs(registers);
2465  asm volatile("mv %0, x5" : "=r"(result));
2466 
2467  // Get registered alerts from alert handler.
2468  reg_alerts = pentest_get_triggered_alerts();
2469  // Get fatal and recoverable AST alerts from sensor controller.
2470  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2471 
2472  // Read ERR_STATUS register.
2473  dif_rv_core_ibex_error_status_t codes;
2474  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2475 
2476  // Send loop counters & ERR_STATUS to host.
2477  ibex_fi_test_result_registers_t uj_output;
2478  uj_output.result = result;
2479  memcpy(uj_output.registers, registers, sizeof(registers));
2480  uj_output.err_status = codes;
2481  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2482  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2483  sizeof(sensor_alerts.alerts));
2484  RESP_OK(ujson_serialize_ibex_fi_test_result_registers_t, uj, &uj_output);
2485  return OK_STATUS();
2486 }
2487 
2488 status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj) {
2489  // Clear registered alerts in alert handler.
2490  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2491  // Clear the AST recoverable alerts.
2492  pentest_clear_sensor_recov_alerts();
2493 
2494  // FI code target.
2495  uint32_t loop_counter = 0;
2496  pentest_set_trigger_high();
2497  asm volatile(NOP100);
2498  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2499  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2500  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2501  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2502  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2503  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2504  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2505  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2506  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2507  asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter));
2508  pentest_set_trigger_low();
2509  // Get registered alerts from alert handler.
2510  reg_alerts = pentest_get_triggered_alerts();
2511  // Get fatal and recoverable AST alerts from sensor controller.
2512  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2513 
2514  // Read ERR_STATUS register.
2515  dif_rv_core_ibex_error_status_t codes;
2516  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2517 
2518  // Send loop counter & ERR_STATUS to host.
2519  ibex_fi_loop_counter_t uj_output;
2520  uj_output.loop_counter = loop_counter;
2521  uj_output.err_status = codes;
2522  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2523  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2524  sizeof(sensor_alerts.alerts));
2525  RESP_OK(ujson_serialize_ibex_fi_loop_counter_t, uj, &uj_output);
2526  return OK_STATUS();
2527 }
2528 
2529 status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj) {
2530  // Clear registered alerts in alert handler.
2531  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2532  // Clear the AST recoverable alerts.
2533  pentest_clear_sensor_recov_alerts();
2534 
2535  uint32_t loop_counter = 0;
2536  asm volatile(INITX5);
2537 
2538  // FI code target.
2539  PENTEST_ASM_TRIGGER_HIGH
2540  asm volatile(ADDI1000);
2541  asm volatile(ADDI1000);
2542  asm volatile(ADDI1000);
2543  asm volatile(ADDI1000);
2544  asm volatile(ADDI1000);
2545  asm volatile(ADDI1000);
2546  asm volatile(ADDI1000);
2547  asm volatile(ADDI1000);
2548  asm volatile(ADDI1000);
2549  asm volatile(ADDI1000);
2550  PENTEST_ASM_TRIGGER_LOW
2551  asm volatile("mv %0, x5" : "=r"(loop_counter));
2552 
2553  // Get registered alerts from alert handler.
2554  reg_alerts = pentest_get_triggered_alerts();
2555  // Get fatal and recoverable AST alerts from sensor controller.
2556  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2557 
2558  // Read ERR_STATUS register.
2559  dif_rv_core_ibex_error_status_t codes;
2560  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2561 
2562  // Send loop counter & ERR_STATUS to host.
2563  ibex_fi_loop_counter_t uj_output;
2564  uj_output.loop_counter = loop_counter;
2565  uj_output.err_status = codes;
2566  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2567  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2568  sizeof(sensor_alerts.alerts));
2569  RESP_OK(ujson_serialize_ibex_fi_loop_counter_t, uj, &uj_output);
2570  return OK_STATUS();
2571 }
2572 
2573 status_t handle_ibex_fi_char_unrolled_reg_op_loop_chain(ujson_t *uj) {
2574  // Clear registered alerts in alert handler.
2575  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2576  // Clear the AST recoverable alerts.
2577  pentest_clear_sensor_recov_alerts();
2578 
2579  uint32_t addresses[8] = {0};
2580  uint32_t data[8] = {0};
2581  asm volatile(INIT_TMPREGS);
2582 
2583  // FI code target.
2584  PENTEST_ASM_TRIGGER_HIGH
2585  asm volatile(ADDI_CHAIN);
2586  asm volatile(ADDI_CHAIN);
2587  asm volatile(ADDI_CHAIN);
2588  asm volatile(ADDI_CHAIN);
2589  asm volatile(ADDI_CHAIN);
2590  asm volatile(ADDI_CHAIN);
2591  asm volatile(ADDI_CHAIN);
2592  asm volatile(ADDI_CHAIN);
2593  asm volatile(ADDI_CHAIN);
2594  asm volatile(ADDI_CHAIN);
2595  PENTEST_ASM_TRIGGER_LOW
2596 
2597  asm volatile("mv %0, x5" : "=r"(data[0]));
2598  asm volatile("mv %0, x6" : "=r"(data[1]));
2599  asm volatile("mv %0, x7" : "=r"(data[2]));
2600  asm volatile("mv %0, x28" : "=r"(data[3]));
2601  asm volatile("mv %0, x29" : "=r"(data[4]));
2602  asm volatile("mv %0, x30" : "=r"(data[5]));
2603 
2604  // Get registered alerts from alert handler.
2605  reg_alerts = pentest_get_triggered_alerts();
2606  // Get fatal and recoverable AST alerts from sensor controller.
2607  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2608 
2609  // Read ERR_STATUS register.
2610  dif_rv_core_ibex_error_status_t codes;
2611  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2612 
2613  // Send data, alerts & ERR_STATUS to host.
2614  ibex_fi_faulty_addresses_data_t uj_output;
2615  memset(uj_output.addresses, 0, sizeof(uj_output.addresses));
2616  memset(uj_output.data, 0, sizeof(uj_output.data));
2617 
2618  memcpy(uj_output.addresses, addresses, sizeof(addresses));
2619  memcpy(uj_output.data, data, sizeof(data));
2620  uj_output.err_status = codes;
2621  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2622  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2623  sizeof(sensor_alerts.alerts));
2624  RESP_OK(ujson_serialize_ibex_fi_faulty_addresses_data_t, uj, &uj_output);
2625  return OK_STATUS();
2626 }
2627 
2628 status_t handle_ibex_fi_init(ujson_t *uj) {
2629  penetrationtest_cpuctrl_t uj_data;
2630  TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
2631 
2632  pentest_select_trigger_type(kPentestTriggerTypeSw);
2633  // As we are using the software defined trigger, the first argument of
2634  // pentest_init is not needed. kPentestTriggerSourceAes is selected as a
2635  // placeholder.
2636  pentest_init(kPentestTriggerSourceAes,
2637  kPentestPeripheralIoDiv4 | kPentestPeripheralEdn |
2638  kPentestPeripheralCsrng | kPentestPeripheralEntropy |
2639  kPentestPeripheralAes | kPentestPeripheralHmac |
2640  kPentestPeripheralKmac | kPentestPeripheralOtbn);
2641 
2642  // Configure the alert handler. Alerts triggered by IP blocks are captured
2643  // and reported to the test.
2644  pentest_configure_alert_handler();
2645 
2646  // Configure the CPU for the pentest.
2647  penetrationtest_device_info_t uj_output;
2648  TRY(pentest_configure_cpu(
2649  uj_data.icache_disable, uj_data.dummy_instr_disable,
2650  uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
2651  &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
2652  &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
2653  &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
2654 
2655  // Enable the flash.
2656  flash_info = dif_flash_ctrl_get_device_info();
2659  TRY(flash_ctrl_testutils_wait_for_init(&flash));
2660 
2661  // Init OTP.
2662  TRY(dif_otp_ctrl_init(
2664 
2665  // Configure Ibex to allow reading ERR_STATUS register.
2666  TRY(dif_rv_core_ibex_init(
2668  &rv_core_ibex));
2669 
2670  // Read device ID and return to host.
2671  TRY(pentest_read_device_id(uj_output.device_id));
2672  RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
2673 
2674  // Initialize flash for the flash test and write reference values into page.
2675  flash_init = false;
2676  flash_data_valid = false;
2677  // Initialize retention SRAM.
2678  sram_ret_init = false;
2679  // Fetch reference values from OTP before OTP tests.
2680  otp_ref_init = false;
2681 
2682  return OK_STATUS();
2683 }
2684 
2685 status_t handle_ibex_fi_otp_data_read(ujson_t *uj) {
2686  TRY(init_ref_otp_data());
2687  TRY(read_otp_partitions(uj));
2688  return OK_STATUS();
2689 }
2690 
2691 status_t handle_ibex_fi_otp_read_lock(ujson_t *uj) {
2692  TRY(init_ref_otp_data());
2696 
2697  TRY(read_otp_partitions(uj));
2698 
2699  return OK_STATUS();
2700 }
2701 
2702 status_t handle_ibex_fi_otp_write_lock(ujson_t *uj) {
2703  // Clear registered alerts in alert handler.
2704  pentest_registered_alerts_t reg_alerts = pentest_get_triggered_alerts();
2705  // Clear the AST recoverable alerts.
2706  pentest_clear_sensor_recov_alerts();
2707 
2708  uint64_t faulty_token[kSecret0TestUnlockTokenSizeIn64BitWords];
2709  for (size_t i = 0; i < kSecret0TestUnlockTokenSizeIn64BitWords; i++) {
2710  faulty_token[i] = 0xdeadbeef;
2711  }
2712  pentest_set_trigger_high();
2713  asm volatile(NOP10);
2714  TRY(otp_ctrl_testutils_dai_write64(
2715  &otp, kDifOtpCtrlPartitionSecret0, kSecret0TestUnlockTokenOffset,
2716  faulty_token, kSecret0TestUnlockTokenSizeIn64BitWords));
2717  asm volatile(NOP10);
2718  pentest_set_trigger_low();
2719 
2720  // Get registered alerts from alert handler.
2721  reg_alerts = pentest_get_triggered_alerts();
2722  // Get fatal and recoverable AST alerts from sensor controller.
2723  pentest_sensor_alerts_t sensor_alerts = pentest_get_sensor_alerts();
2724 
2725  // Read ERR_STATUS register.
2726  dif_rv_core_ibex_error_status_t codes;
2727  TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes));
2728 
2729  // Send res & ERR_STATUS to host.
2730  ibex_fi_test_result_t uj_output;
2731  uj_output.result =
2732  0; // Writing to the locked OTP partition crashes the chip.
2733  uj_output.err_status = codes;
2734  memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts));
2735  memcpy(uj_output.ast_alerts, sensor_alerts.alerts,
2736  sizeof(sensor_alerts.alerts));
2737  RESP_OK(ujson_serialize_ibex_fi_test_result_t, uj, &uj_output);
2738 
2739  return OK_STATUS();
2740 }
2741 
2742 status_t handle_ibex_fi(ujson_t *uj) {
2743  ibex_fi_subcommand_t cmd;
2744  TRY(ujson_deserialize_ibex_fi_subcommand_t(uj, &cmd));
2745  switch (cmd) {
2746  case kIbexFiSubcommandAddressTranslation:
2747  return handle_ibex_fi_address_translation(uj);
2748  case kIbexFiSubcommandAddressTranslationCfg:
2749  return handle_ibex_fi_address_translation_config(uj);
2750  case kIbexFiSubcommandCharCondBranchBeq:
2751  return handle_ibex_fi_char_conditional_branch_beq(uj);
2752  case kIbexFiSubcommandCharCondBranchBge:
2753  return handle_ibex_fi_char_conditional_branch_bge(uj);
2754  case kIbexFiSubcommandCharCondBranchBgeu:
2755  return handle_ibex_fi_char_conditional_branch_bgeu(uj);
2756  case kIbexFiSubcommandCharCondBranchBlt:
2757  return handle_ibex_fi_char_conditional_branch_blt(uj);
2758  case kIbexFiSubcommandCharCondBranchBltu:
2759  return handle_ibex_fi_char_conditional_branch_bltu(uj);
2760  case kIbexFiSubcommandCharCondBranchBne:
2761  return handle_ibex_fi_char_conditional_branch_bne(uj);
2762  case kIbexFiSubcommandCharCsrRead:
2763  return handle_ibex_fi_char_csr_read(uj);
2764  case kIbexFiSubcommandCharCsrWrite:
2765  return handle_ibex_fi_char_csr_write(uj);
2766  case kIbexFiSubcommandCharFlashRead:
2767  return handle_ibex_fi_char_flash_read(uj);
2768  case kIbexFiSubcommandCharFlashWrite:
2769  return handle_ibex_fi_char_flash_write(uj);
2770  case kIbexFiSubcommandCharHardenedCheckComplementBranch:
2771  return handle_ibex_fi_char_hardened_check_eq_complement_branch(uj);
2772  case kIbexFiSubcommandCharHardenedCheckUnimp:
2773  return handle_ibex_fi_char_hardened_check_eq_unimp(uj);
2774  case kIbexFiSubcommandCharHardenedCheck2Unimps:
2775  return handle_ibex_fi_char_hardened_check_eq_2_unimps(uj);
2776  case kIbexFiSubcommandCharHardenedCheck3Unimps:
2777  return handle_ibex_fi_char_hardened_check_eq_3_unimps(uj);
2778  case kIbexFiSubcommandCharHardenedCheck4Unimps:
2779  return handle_ibex_fi_char_hardened_check_eq_4_unimps(uj);
2780  case kIbexFiSubcommandCharHardenedCheck5Unimps:
2781  return handle_ibex_fi_char_hardened_check_eq_5_unimps(uj);
2782  case kIbexFiSubcommandCharMemOpLoop:
2783  return handle_ibex_fi_char_mem_op_loop(uj);
2784  case kIbexFiSubcommandCharRegisterFile:
2785  return handle_ibex_fi_char_register_file(uj);
2786  case kIbexFiSubcommandCharRegisterFileRead:
2787  return handle_ibex_fi_char_register_file_read(uj);
2788  case kIbexFiSubcommandCharRegOpLoop:
2789  return handle_ibex_fi_char_reg_op_loop(uj);
2790  case kIbexFiSubcommandCharSramRead:
2791  return handle_ibex_fi_char_sram_read(uj);
2792  case kIbexFiSubcommandCharSramStatic:
2793  return handle_ibex_fi_char_sram_static(uj);
2794  case kIbexFiSubcommandCharSramWrite:
2795  return handle_ibex_fi_char_sram_write(uj);
2796  case kIbexFiSubcommandCharSramWriteRead:
2797  return handle_ibex_fi_char_sram_write_read(uj);
2798  case kIbexFiSubcommandCharSramWriteStaticUnrolled:
2799  return handle_ibex_fi_char_sram_write_static_unrolled(uj);
2800  case kIbexFiSubcommandCharUncondBranch:
2801  return handle_ibex_fi_char_unconditional_branch(uj);
2802  case kIbexFiSubcommandCharUncondBranchNop:
2803  return handle_ibex_fi_char_unconditional_branch_nop(uj);
2804  case kIbexFiSubcommandCharUnrolledMemOpLoop:
2805  return handle_ibex_fi_char_unrolled_mem_op_loop(uj);
2806  case kIbexFiSubcommandCharUnrolledRegOpLoop:
2807  return handle_ibex_fi_char_unrolled_reg_op_loop(uj);
2808  case kIbexFiSubcommandCharUnrolledRegOpLoopChain:
2809  return handle_ibex_fi_char_unrolled_reg_op_loop_chain(uj);
2810  case kIbexFiSubcommandInit:
2811  return handle_ibex_fi_init(uj);
2812  case kIbexFiSubcommandOtpDataRead:
2813  return handle_ibex_fi_otp_data_read(uj);
2814  case kIbexFiSubcommandOtpReadLock:
2815  return handle_ibex_fi_otp_read_lock(uj);
2816  case kIbexFiSubcommandOtpWriteLock:
2817  return handle_ibex_fi_otp_write_lock(uj);
2818  default:
2819  LOG_ERROR("Unrecognized IBEX FI subcommand: %d", cmd);
2820  return INVALID_ARGUMENT();
2821  }
2822  return OK_STATUS();
2823 }