Software APIs
rom_epmp_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 "sw/device/silicon_creator/rom/rom_epmp.h"
6 
7 #include <stdbool.h>
8 #include <stdint.h>
9 
12 #include "sw/device/lib/base/csr.h"
21 #include "sw/device/lib/testing/pinmux_testutils.h"
22 #include "sw/device/lib/testing/test_framework/status.h"
24 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
25 #include "sw/device/silicon_creator/lib/drivers/uart.h"
26 #include "sw/device/silicon_creator/lib/epmp_test_unlock.h"
27 #include "sw/device/silicon_creator/rom/rom_epmp.h"
28 
29 #include "flash_ctrl_regs.h" // Generated.
31 
32 /**
33  * ROM ePMP test.
34  *
35  * This test uses the ROM linker script and ePMP setup code to initialize
36  * its own ePMP configuration and then attempts to execute instructions in
37  * various address spaces. Typically execution in these address spaces should be
38  * blocked unless the unlock function has been called with a region containing
39  * the address of the access.
40  */
41 
42 /**
43  * Get the value of the `mcause` register.
44  *
45  * @returns The encoded interrupt or exception cause.
46  */
47 static uint32_t get_mcause(void) {
48  uint32_t mcause;
49  CSR_READ(CSR_REG_MCAUSE, &mcause);
50  return mcause;
51 }
52 
53 /**
54  * Get the value of the `mepc` register.
55  *
56  * @returns The value of the machine exception program counter.
57  */
58 static uint32_t get_mepc(void) {
59  uint32_t mepc;
60  CSR_READ(CSR_REG_MEPC, &mepc);
61  return mepc;
62 }
63 
64 /**
65  * Set the value of the `mepc` register.
66  *
67  * After an exception has been handled execution will be resumed at the address
68  * contained within `mepc`.
69  *
70  * @param pc The value to set the machine exception program counter to.
71  */
72 static void set_mepc(uint32_t pc) { CSR_WRITE(CSR_REG_MEPC, pc); }
73 
74 /**
75  * Interrupt handlers.
76  *
77  * If operating correctly this test should only trigger exceptions. Interrupts
78  * are therefore not recovered.
79  */
80 void rom_nmi_handler(void) { wait_for_interrupt(); }
81 void rom_interrupt_handler(void) { wait_for_interrupt(); }
82 
83 /**
84  * The type of last exception (if any) received.
85  *
86  * Set by the exception handler.
87  */
88 volatile ibex_exc_t exception_received = 0;
89 
90 /**
91  * The `mepc` value for the last exception (if any) received.
92  *
93  * Set by the exception handler.
94  */
95 volatile uintptr_t exception_pc = 0;
96 
97 /**
98  * Exception handler.
99  *
100  * Handle instruction access faults and illegal instructions by setting
101  * `exception_received` and `exception_pc` and then returning to the code
102  * that jumped (via a call) to the offending instruction.
103  *
104  * This will likely only work correctly if the instruction exception was
105  * caused by a jump from `execute` to an invalid instruction (whether illegal
106  * or inaccessible).
107  *
108  * For all other exceptions hang (could also shutdown) so as not to hide them.
109  */
110 void rom_exception_handler(void) __attribute__((interrupt));
111 void rom_exception_handler(void) {
112  uint32_t mcause = get_mcause();
113  if (mcause == kIbexExcInstrAccessFault ||
114  mcause == kIbexExcIllegalInstrFault) {
115  exception_received = (ibex_exc_t)mcause;
116  exception_pc = get_mepc();
117 
118  // Return to caller.
119  uintptr_t ret = (uintptr_t)__builtin_return_address(0);
120  set_mepc((uint32_t)ret);
121  return;
122  }
123 
124  // Wait forever if an unexpected exception is encountered.
126 }
127 
128 /**
129  * Attempt to execute the code at `pc` by calling it like a function.
130  *
131  * Typically the contents of `pc` should be an invalid instruction such
132  * as an all zero value. In this case if execution was blocked by PMP an
133  * instruction fault exception will be raised. If however execution was
134  * allowed then an illegal instruction exception will be raised instead.
135  *
136  * The interrupt handler will arrange for control to be returned to the
137  * caller on encountering either an instruction fault or illegal
138  * instruction error so this function will report a result in either
139  * case.
140  *
141  * @param pc The address of the instruction to try and execute.
142  * @param expect The expected exception that will be raised.
143  * @returns Whether the expected exception was raised at the correct PC.
144  */
145 static bool execute(const void *pc, ibex_exc_t expect) {
146  exception_pc = 0;
147  exception_received = kIbexExcMax;
148 
149  // Jump to the target PC.
150  //
151  // Using a `call` here (`jal` or `jalr`) sets the return address (`ra`)
152  // register. When an exception is raised the interrupt handler will recover
153  // by restarting execution at the address in `ra` thereby making it appear
154  // as if the call returned normally.
155  //
156  // ...
157  // jal ra, pc # <- Set return address and jump to pc.
158  // ... # <- Interrupt handler restarts execution at the next
159  // # instruction in the caller, here.
160  //
161  // pc:
162  // unimp # <- Illegal instruction or access fault. Enter interrupt
163  // handler.
164  //
165  ((void (*)(void))pc)();
166 
167  // Be careful to ensure that the exception was raised when trying to
168  // execute `pc` just in case a valid instruction is actually executed
169  // and then execution continued to a point where an exception is
170  // raised.
171  if (exception_received != kIbexExcMax && exception_pc != (uintptr_t)pc) {
172  return false;
173  }
174  return exception_received == expect;
175 }
176 
177 /**
178  * An instruction that has all bits set. This value is specifically chosen to
179  * match an erased flash.
180  *
181  * Attempts to execute this instruction, `unimp`, will result in an illegal
182  * instruction exception.
183  *
184  * Note that if compressed instructions are enabled only the first two bytes
185  * will be decoded (as `c.unimp`).
186  */
187 static const uint32_t kUnimpInstruction = UINT32_MAX;
188 
189 /**
190  * Illegal instruction residing in .rodata.
191  */
192 static const uint32_t illegal_ins_ro[] = {
193  kUnimpInstruction,
194 };
195 
196 /**
197  * Illegal instruction residing in .bss.
198  */
199 static uint32_t illegal_ins_rw[] = {
200  0,
201 };
202 
203 /**
204  * Report whether the given pointer points to a location with the provided
205  * address space.
206  *
207  * @param ptr Pointer to test.
208  * @param start Address of the start of the address space.
209  * @param size The size of the address space in bytes.
210  * @returns Whether the pointer is in the address space.
211  */
212 static bool is_in_address_space(const void *ptr, uintptr_t start,
213  uintptr_t size) {
214  return (uintptr_t)ptr >= start && (uintptr_t)ptr < (start + size);
215 }
216 
217 /**
218  * Set to false if a test fails.
219  */
220 static bool passed = false;
221 
222 /**
223  * Custom CHECK macro to assert a condition that if false should cause the
224  * test to fail. Note: we can't use the normal CHECK macro because it tries to
225  * write to the DV address space but that is locked by the ePMP configuration.
226  */
227 #define CHECK(condition) \
228  if (!(condition)) { \
229  LOG_ERROR("CHECK-fail: " #condition); \
230  passed = false; \
231  }
232 
233 /**
234  * Test that .rodata in the ROM is not executable.
235  */
236 static void test_noexec_rodata(void) {
237  CHECK(is_in_address_space(illegal_ins_ro, TOP_EARLGREY_ROM_CTRL_ROM_BASE_ADDR,
239  CHECK(execute(illegal_ins_ro, kIbexExcInstrAccessFault));
240 }
241 
242 /**
243  * Test that the .bss section in RAM is not executable.
244  */
245 static void test_noexec_rwdata(void) {
246  dif_sram_ctrl_t sram_ctrl;
247  CHECK(dif_sram_ctrl_init(
249  &sram_ctrl) == kDifOk);
251  kDifOk);
252  CHECK(is_in_address_space(illegal_ins_rw, TOP_EARLGREY_RAM_MAIN_BASE_ADDR,
254  CHECK(execute(illegal_ins_rw, kIbexExcInstrAccessFault));
255 }
256 
257 /**
258  * Test that eFlash is not executable.
259  */
260 static void test_noexec_eflash(void) {
261  // Ideally we'd check all of eFlash but that takes a very long time in
262  // simulation. Instead, check the first and last words are not executable and
263  // check a sample of other addresses.
264  uint32_t *eflash = (uint32_t *)TOP_EARLGREY_EFLASH_BASE_ADDR;
265  size_t eflash_len = TOP_EARLGREY_EFLASH_SIZE_BYTES / sizeof(eflash[0]);
266  CHECK(execute(&eflash[0], kIbexExcInstrAccessFault));
267  CHECK(execute(&eflash[eflash_len - 1], kIbexExcInstrAccessFault));
268 
269  // Step size is picked arbitrarily but should provide a reasonable sample of
270  // addresses.
271  size_t step = eflash_len / 999;
272  for (size_t i = step; i < eflash_len; i += step) {
273  if (!execute(&eflash[i], kIbexExcInstrAccessFault)) {
274  LOG_ERROR("eflash execution not blocked @ %p", &eflash[i]);
275  passed = false;
276  break;
277  }
278  }
279 }
280 
281 /**
282  * Test that the MMIO address space (specifically the retention RAM) is not
283  * executable.
284  */
285 static void test_noexec_mmio(void) {
286  // Note: execution of retention RAM always fails regardless of controller or
287  // ePMP configurations however it doesn't hurt to check it anyway.
288  dif_sram_ctrl_t ret_ram_ctrl;
289  CHECK(dif_sram_ctrl_init(mmio_region_from_addr(
291  &ret_ram_ctrl) == kDifOk);
292  CHECK(dif_sram_ctrl_exec_set_enabled(&ret_ram_ctrl, kDifToggleEnabled) ==
293  kDifOk);
294  uint32_t *ret_ram = (uint32_t *)TOP_EARLGREY_RAM_RET_AON_BASE_ADDR;
295  size_t ret_ram_len = TOP_EARLGREY_RAM_RET_AON_SIZE_BYTES / sizeof(ret_ram[0]);
296  ret_ram[0] = kUnimpInstruction;
297  CHECK(execute(&ret_ram[0], kIbexExcInstrAccessFault));
298  ret_ram[ret_ram_len - 1] = kUnimpInstruction;
299  CHECK(execute(&ret_ram[ret_ram_len - 1], kIbexExcInstrAccessFault));
300 }
301 
302 /**
303  * Test the function used to unlock execution of the ROM extension.
304  *
305  * Unlock a section of eFlash to simulate the unlocking of the ROM_EXT text.
306  * Accesses within the unlocked region should execute (and generate an illegal
307  * instruction exception in this case) while accesses outside the unlocked
308  * region should still fail with an instruction access fault exception.
309  *
310  * @param epmp The ePMP state to update.
311  */
312 static void test_unlock_exec_eflash(void) {
313  // Define a region to unlock (this is somewhat arbitrary but must be word-
314  // aligned and beyond the ROM region, since this same image is placed in the
315  // flash).
316  uint32_t *eflash = (uint32_t *)TOP_EARLGREY_EFLASH_BASE_ADDR;
317  size_t eflash_len = TOP_EARLGREY_EFLASH_SIZE_BYTES / sizeof(eflash[0]);
318  uint32_t *image = &eflash[eflash_len / 5];
319  size_t image_len = eflash_len / 7;
320  epmp_region_t region = {.start = (uintptr_t)&image[0],
321  .end = (uintptr_t)&image[image_len]};
322 
323  // Unlock execution of the region and check that the same changes are made
324  // to the ePMP state.
325  rom_epmp_unlock_rom_ext_rx(region);
326  CHECK(epmp_state_check() == kErrorOk);
327 
328  // Verify that execution within the region succeeds.
329  // The image must consist of `unimp` instructions so that an illegal
330  // instruction exception is generated. Because the region is not written and
331  // tests begin with the flash erased, this instruction is expected to be
332  // UINT32_MAX.
333  CHECK(image[0] == kUnimpInstruction);
334  CHECK(execute(&image[0], kIbexExcIllegalInstrFault));
335  CHECK(image[image_len - 1] == kUnimpInstruction);
336  CHECK(execute(&image[image_len - 1], kIbexExcIllegalInstrFault));
337 
338  // Verify that execution just outside the region still fails.
339  CHECK(execute(&image[-1], kIbexExcInstrAccessFault));
340  CHECK(execute(&image[image_len], kIbexExcInstrAccessFault));
341 }
342 
343 void rom_main(void) {
344  // Initialize global variables here so that they don't end up in the .data
345  // section since OpenTitan ROM does not have one.
346  passed = true;
347  exception_received = kIbexExcMax;
348  illegal_ins_rw[0] = kUnimpInstruction;
349 
350  // Initialize sec_mmio.
351  sec_mmio_init();
352 
353  // Configure debug ROM ePMP entry.
354  rom_epmp_config_debug_rom(kLcStateProd);
355 
356  // Initialize pinmux configuration so we can use the UART.
357  dif_pinmux_t pinmux;
358  OT_DISCARD(dif_pinmux_init(
360  pinmux_testutils_init(&pinmux);
361 
362  // Enable execution of code in flash.
363  flash_ctrl_init();
364  flash_ctrl_exec_set(FLASH_CTRL_PARAM_EXEC_EN);
365  SEC_MMIO_WRITE_INCREMENT(kFlashCtrlSecMmioInit + kFlashCtrlSecMmioExecSet);
366 
367  // Configure UART0 as stdout.
368  uart_init(kUartNCOValue);
370  .data = NULL,
371  .sink = uart_sink,
372  });
373 
374  // Start the tests.
375  LOG_INFO("Starting ROM ePMP functional test.");
376 
377  // Initialize shadow copy of the ePMP register configuration.
378  memset(&epmp_state, 0, sizeof(epmp_state));
379  rom_epmp_state_init(kLcStateProd);
380  CHECK(epmp_state_check() == kErrorOk);
381 
382  // Test that execution outside the ROM text is blocked by default.
383  test_noexec_rodata();
384  test_noexec_rwdata();
385  test_noexec_eflash();
386  test_noexec_mmio();
387 
388  // Test that execution is unlocked for a sub-region of eFlash correctly.
389  // Simulates the unlocking of the ROM extension text.
390  test_unlock_exec_eflash();
391 
392  // The test of the ROM's ePMP configuration is now complete. Unlock the
393  // DV address space so that the test result can be reported. Assumes that PMP
394  // entry 6 is allocated for this purpose.
395  CHECK(epmp_unlock_test_status());
396 
397  // Report the test status.
398  //
399  // Note that it is only now, after the DV address space has been unlocked that
400  // we can signal that the test has started unfortunately.
401  test_status_set(kTestStatusInTest);
402  test_status_set(passed ? kTestStatusPassed : kTestStatusFailed);
403 
404  // Unreachable if reporting the test status correctly caused the
405  // test to stop.
406  while (true) {
408  }
409 }