Software APIs
sram_ctrl_execution_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include <stdbool.h>
6 #include <stdint.h>
7 
13 #include "sw/device/lib/testing/test_framework/check.h"
14 #include "sw/device/lib/testing/test_framework/ottf_isrs.h"
15 #include "sw/device/lib/testing/test_framework/ottf_macros.h"
17 #include "sw/device/silicon_creator/lib/epmp_state.h"
18 
20 
21 OTTF_DEFINE_TEST_CONFIG();
22 
23 static dif_sram_ctrl_t sram_ctrl;
24 
25 enum {
30 };
31 
32 OT_SECTION(".data.sram_function_test")
34 static void sram_function_test(void) {
35  uint32_t pc = 0;
36  asm("auipc %[pc], 0;" : [pc] "=r"(pc));
37  LOG_INFO("PC: %p, SRAM: [%p, %p)", pc, kSramStart, kSramEnd);
38  CHECK(pc >= kSramStart && pc < kSramEnd, "PC is outside the main SRAM");
39 }
40 
41 // Redeclaration of the addressable symbol in `sram_ret_neg_test()` to be used
42 // in `ottf_exception_handler()`.
43 extern const char kSramRetNegTestReturn[];
44 
45 void ottf_exception_handler(uint32_t *exc_info) {
46  // The frame address is the address of the stack location that holds the
47  // `mepc`, since the OTTF exception handler entry code saves the `mepc` to
48  // the top of the stack before transferring control flow to the exception
49  // handler function (which is overridden here). See the `handler_exception`
50  // subroutine in `sw/device/lib/testing/testing/ottf_isrs.S` for more details.
51  uintptr_t *mepc_stack_addr = (uintptr_t *)OT_FRAME_ADDR();
52  ibex_exc_t exception = ibex_mcause_read();
53  switch (exception) {
54  case kIbexExcInstrAccessFault:
55  LOG_INFO("Detected instruction access fault");
56  *mepc_stack_addr = (uintptr_t)kSramRetNegTestReturn;
57  break;
58  default:
59  LOG_FATAL("Unexpected exception id = 0x%x", exception);
60  abort();
61  }
62 }
63 
64 static void sram_ret_neg_test(void) {
65  memset((void *)kSramRetStart, 0, sizeof(uint32_t));
66  ((void (*)(void))kSramRetStart)();
67  CHECK(false, "Should not be here");
68  OT_ADDRESSABLE_LABEL(kSramRetNegTestReturn);
69 }
70 
71 bool test_main(void) {
72  CHECK_DIF_OK(dif_sram_ctrl_init(
74  &sram_ctrl));
75 
76  // Unlock the entire address space for RWX so that we can run this test with
77  // both rom and test_rom.
78  CSR_WRITE(CSR_REG_PMPADDR7, 0x7fffffff);
79 
80  uint32_t pmpcfg1 = 0;
81  CSR_READ(CSR_REG_PMPCFG1, &pmpcfg1);
82  CHECK((pmpcfg1 & 0xff000000) == 0,
83  "expected PMPCFG1 to be unconfigured before changing it");
84 
85  CSR_SET_BITS(CSR_REG_PMPCFG1,
86  (kEpmpModeNapot | kEpmpPermLockedReadWriteExecute) << 24);
87 
88  // Note: We can test the negative case only using the retention SRAM since
89  // execution is unconditionally enabled for the main SRAM in the RMA life
90  // cycle state.
91  sram_ret_neg_test();
92 
93  // Try to enable SRAM execution.
94  dif_result_t exec_enabled =
96 
97  // If SRAM execution was not enabled, re-check that execution fails, else
98  // check the positive case.
99  if (exec_enabled == kDifLocked) {
100  sram_ret_neg_test();
101  } else {
102  CHECK_DIF_OK(exec_enabled);
103  sram_function_test();
104  }
105 
106  return true;
107 }