Software APIs
rom_epmp.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 
10 
12 
13 // Symbols defined in linker script.
14 extern char _stack_start[]; // Lowest stack address.
15 extern char _text_start[]; // Start of executable code.
16 extern char _text_end[]; // End of executable code.
17 
18 // Note: Hardcoding these values since the way we generate this range is not
19 // very robust at the moment. See #14345 and #14336.
20 static_assert(TOP_EARLGREY_MMIO_BASE_ADDR == 0x40000000,
21  "MMIO region changed, update ePMP configuration if needed");
22 static_assert(TOP_EARLGREY_MMIO_SIZE_BYTES == 0x10000000,
23  "MMIO region changed, update ePMP configuration if needed");
24 
30  TOP_EARLGREY_MMIO_SIZE_BYTES,
31  "Retention SRAM must be in the MMIO address space.");
32 
33 void rom_epmp_state_init(lifecycle_state_t lc_state) {
34  // Address space definitions.
35  //
36  // Note that the stack guard is placed at _stack_start because the stack
37  // grows downward from _stack_end.
38  const epmp_region_t rom_text = {.start = (uintptr_t)_text_start,
39  .end = (uintptr_t)_text_end};
43  const epmp_region_t eflash = {
46  const epmp_region_t mmio = {
48  .end = TOP_EARLGREY_MMIO_BASE_ADDR + TOP_EARLGREY_MMIO_SIZE_BYTES};
49  const epmp_region_t debug_rom = {.start = TOP_EARLGREY_RV_DM_MEM_BASE_ADDR,
52  const epmp_region_t stack_guard = {.start = (uintptr_t)_stack_start,
53  .end = (uintptr_t)_stack_start + 4};
54  const epmp_region_t ram = {.start = TOP_EARLGREY_RAM_MAIN_BASE_ADDR,
57 
58  epmp_perm_t debug_rom_access = kEpmpPermLockedNoAccess;
59  switch (launder32(lc_state)) {
60  case kLcStateTest:
61  HARDENED_CHECK_EQ(lc_state, kLcStateTest);
62  debug_rom_access = kEpmpPermLockedReadWriteExecute;
63  break;
64  case kLcStateDev:
65  HARDENED_CHECK_EQ(lc_state, kLcStateDev);
66  debug_rom_access = kEpmpPermLockedReadWriteExecute;
67  break;
68  case kLcStateProd:
69  HARDENED_CHECK_EQ(lc_state, kLcStateProd);
70  debug_rom_access = kEpmpPermLockedNoAccess;
71  break;
72  case kLcStateProdEnd:
73  HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
74  debug_rom_access = kEpmpPermLockedNoAccess;
75  break;
76  case kLcStateRma:
77  HARDENED_CHECK_EQ(lc_state, kLcStateRma);
78  debug_rom_access = kEpmpPermLockedReadWriteExecute;
79  break;
80  default:
81  HARDENED_TRAP();
82  }
83 
84  // Initialize in-memory copy of ePMP register state.
85  //
86  // The actual hardware configuration is performed separately, either by reset
87  // logic or in assembly. This code must be kept in sync with any changes
88  // to the hardware configuration.
89  memset(&epmp_state, 0, sizeof(epmp_state));
90  epmp_state_configure_tor(1, rom_text, kEpmpPermLockedReadExecute);
91  epmp_state_configure_napot(2, rom, kEpmpPermLockedReadOnly);
92  epmp_state_configure_napot(5, eflash, kEpmpPermLockedReadOnly);
93  epmp_state_configure_tor(11, mmio, kEpmpPermLockedReadWrite);
94  epmp_state_configure_napot(13, debug_rom, debug_rom_access);
95  epmp_state_configure_na4(14, stack_guard, kEpmpPermLockedNoAccess);
96  epmp_state_configure_napot(15, ram, kEpmpPermLockedReadWrite);
97  epmp_state.mseccfg = EPMP_MSECCFG_MMWP | EPMP_MSECCFG_RLB;
98 }
99 
100 void rom_epmp_unlock_rom_ext_rx(epmp_region_t region) {
101  // Update the in-memory copy of ePMP register state.
102  const int kEntry = 4;
103  epmp_state_configure_tor(kEntry, region, kEpmpPermLockedReadExecute);
104 
105  // Update the hardware configuration (CSRs).
106  //
107  // Entry is hardcoded as 4. Make sure to modify hardcoded values if changing
108  // kEntry.
109  //
110  // The `pmp4cfg` configuration is the first field in `pmpcfg1`.
111  //
112  // 32 24 16 8 0
113  // +-----------+-----------+-----------+-----------+
114  // `pmpcfg1` = | `pmp7cfg` | `pmp6cfg` | `pmp5cfg` | `pmp4cfg` |
115  // +-----------+-----------+-----------+-----------+
116  CSR_WRITE(CSR_REG_PMPADDR3, region.start >> 2);
117  CSR_WRITE(CSR_REG_PMPADDR4, region.end >> 2);
118  CSR_CLEAR_BITS(CSR_REG_PMPCFG1, 0xff);
119  CSR_SET_BITS(CSR_REG_PMPCFG1, kEpmpModeTor | kEpmpPermLockedReadExecute);
120 }
121 
122 void rom_epmp_unlock_rom_ext_r(epmp_region_t region) {
123  const int kEntry = 6;
124  epmp_state_configure_napot(kEntry, region, kEpmpPermLockedReadOnly);
125 
126  // Update the hardware configuration (CSRs).
127  //
128  // Entry is hardcoded as 6. Make sure to modify hardcoded values if changing
129  // kEntry.
130  //
131  // The `pmp6cfg` configuration is the second field in `pmpcfg1`.
132  //
133  // 32 24 16 8 0
134  // +-----------+-----------+-----------+-----------+
135  // `pmpcfg1` = | `pmp7cfg` | `pmp6cfg` | `pmp5cfg` | `pmp4cfg` |
136  // +-----------+-----------+-----------+-----------+
137 
138  CSR_WRITE(CSR_REG_PMPADDR6,
139  region.start >> 2 | (region.end - region.start - 1) >> 3);
140  CSR_CLEAR_BITS(CSR_REG_PMPCFG1, 0xff << 16);
141  CSR_SET_BITS(CSR_REG_PMPCFG1,
142  ((kEpmpModeNapot | kEpmpPermLockedReadOnly) << 16));
143 }
144 
145 void rom_epmp_config_debug_rom(lifecycle_state_t lc_state) {
146  const uint32_t pmpaddr = (TOP_EARLGREY_RV_DM_MEM_BASE_ADDR >> 2) |
148  // Update the hardware configuration (CSRs).
149  //
150  // Entry is hardcoded as 13. Make sure to modify hardcoded values if changing
151  // kEntry.
152  //
153  // The `pmp13cfg` configuration is the second field in `pmpcfg3`.
154  //
155  // 32 24 16 8 0
156  // +------------+------------+------------+------------+
157  // `pmpcfg3` = | `pmp15cfg` | `pmp14cfg` | `pmp13cfg` | `pmp12cfg` |
158  // +------------+------------+------------+------------+
159  CSR_WRITE(CSR_REG_PMPADDR13, pmpaddr);
160  CSR_CLEAR_BITS(CSR_REG_PMPCFG3, 0xff00);
161  uint32_t pmpcfg = 0;
162  switch (launder32(lc_state)) {
163  case kLcStateTest:
164  HARDENED_CHECK_EQ(lc_state, kLcStateTest);
165  pmpcfg = (kEpmpModeNapot | kEpmpPermLockedReadWriteExecute) << 8;
166  break;
167  case kLcStateDev:
168  HARDENED_CHECK_EQ(lc_state, kLcStateDev);
169  pmpcfg = (kEpmpModeNapot | kEpmpPermLockedReadWriteExecute) << 8;
170  break;
171  case kLcStateProd:
172  HARDENED_CHECK_EQ(lc_state, kLcStateProd);
173  pmpcfg = (kEpmpModeNapot | kEpmpPermLockedNoAccess) << 8;
174  break;
175  case kLcStateProdEnd:
176  HARDENED_CHECK_EQ(lc_state, kLcStateProdEnd);
177  pmpcfg = (kEpmpModeNapot | kEpmpPermLockedNoAccess) << 8;
178  break;
179  case kLcStateRma:
180  HARDENED_CHECK_EQ(lc_state, kLcStateRma);
181  pmpcfg = (kEpmpModeNapot | kEpmpPermLockedReadWriteExecute) << 8;
182  break;
183  default:
184  HARDENED_TRAP();
185  }
186  CSR_SET_BITS(CSR_REG_PMPCFG3, pmpcfg);
187 }