Software APIs
imm_section_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_ext/imm_section/imm_section_epmp.h"
6 
9 #include "sw/device/silicon_creator/lib/drivers/epmp.h"
10 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
11 #include "sw/device/silicon_creator/lib/epmp_state.h"
12 #include "sw/device/silicon_creator/lib/error.h"
13 #include "sw/device/silicon_creator/lib/manifest.h"
14 
15 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
16 
17 // Address populated by the linker.
18 extern char _rom_ext_immutable_start[];
19 extern char _rom_ext_immutable_end[];
20 extern char _text_end[];
21 extern char _stack_start[]; // Lowest stack address.
22 
23 static const epmp_region_t kMmioRegion = {
25  .end = TOP_EARLGREY_MMIO_BASE_ADDR + TOP_EARLGREY_MMIO_SIZE_BYTES,
26 };
27 
28 static const epmp_region_t kFlashRegion = {
31 };
32 
33 static const epmp_region_t kRvDmRegion = {
36 };
37 
38 static const epmp_region_t kStackGuard = {.start = (uintptr_t)_stack_start,
39  .end = (uintptr_t)_stack_start + 4};
40 
41 static const epmp_region_t kImmTextRegion = {
42  .start = (uintptr_t)_rom_ext_immutable_start,
43  .end = (uintptr_t)_text_end,
44 };
45 
46 rom_error_t imm_section_epmp_reconfigure(void) {
47  // ePMP region 15 gives read/write access to RAM.
48  // Leave it unchanged.
49 
50  // Reconfigure the ePMP MMIO region to be NAPOT region 14, thus freeing
51  // up an ePMP entry for use elsewhere.
52  epmp_set_napot(14, kMmioRegion, kEpmpPermLockedReadWrite);
53 
54  // ePMP region 11 protects the stack from overflow.
55  // This stack guard was in ePMP region 14.
56  epmp_set_napot(11, kStackGuard, kEpmpPermLockedNoAccess);
57 
58  // ePMP region 12 allows RvDM access.
59  // This RvDM region was in ePMP region 13.
60  if (lifecycle_is_prod() == kHardenedBoolTrue) {
61  // No RvDM access in Prod states, so we can clear the entry.
62  epmp_clear(12);
63  } else {
64  epmp_set_napot(12, kRvDmRegion, kEpmpPermLockedReadWriteExecute);
65  }
66 
67  // ePMP region 13 gives read access to all of flash for both M and U modes.
68  // This flash region was in ePMP region 5.
69  epmp_set_napot(13, kFlashRegion, kEpmpPermLockedReadOnly);
70 
71  // Move the ROM_EXT virtual region from entry 6 to 10.
72  uint32_t virtual_napot;
73  CSR_READ(CSR_REG_PMPADDR6, &virtual_napot);
74  epmp_clear(10);
75  if (virtual_napot) {
76  epmp_set_napot(10, epmp_decode_napot(virtual_napot),
77  kEpmpPermLockedReadOnly);
78  }
79 
80  // Clear mutable ROM_EXT entries (8 & 9).
81  epmp_clear(9);
82  epmp_clear(8);
83 
84  // Immutable ROM_EXT TOR (6 & 7).
85  epmp_set_tor(6, kImmTextRegion, kEpmpPermLockedReadExecute);
86 
87  // Clear entries from 5 ~ 3.
88  epmp_clear(5);
89  epmp_clear(4);
90  epmp_clear(3);
91 
92  // 3 ~ 0 are ROM ePMP entries.
93  // Leave them unchanged.
94 
95  HARDENED_RETURN_IF_ERROR(epmp_state_check());
96 
97  return kErrorOk;
98 }
99 
100 rom_error_t imm_section_epmp_mutable_rx(const manifest_t *manifest) {
101  // Immutable ROM_EXT TOR (8 & 9).
102  epmp_region_t mutable_code_region = manifest_code_region_get(manifest);
103 
104  // Manifest code_region includes immutable data segment. Move the start
105  // address to exclude.
106  mutable_code_region.start = (uintptr_t)_rom_ext_immutable_end;
107 
108  epmp_set_tor(8, mutable_code_region, kEpmpPermLockedReadExecute);
109 
110  HARDENED_RETURN_IF_ERROR(epmp_state_check());
111 
112  return kErrorOk;
113 }