1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8
9 #include <zephyr/toolchain.h>
10 #include <zephyr/sys/util_macro.h>
11
12 #include <xtensa/config/core-isa.h>
13
14 #ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H
15 #define ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H
16
17 /**
18 * @defgroup xtensa_mpu_apis Xtensa Memory Protection Unit (MPU) APIs
19 * @ingroup xtensa_apis
20 * @{
21 */
22
23 /** Number of available entries in the MPU table. */
24 #define XTENSA_MPU_NUM_ENTRIES XCHAL_MPU_ENTRIES
25
26 /**
27 * @name MPU memory region access rights.
28 *
29 * @note These are NOT bit masks, and must be used as whole value.
30 *
31 * @{
32 */
33
34 /** Kernel and user modes no access. */
35 #define XTENSA_MPU_ACCESS_P_NA_U_NA (0)
36
37 /** Kernel mode execution only. */
38 #define XTENSA_MPU_ACCESS_P_X_U_NA (2)
39
40 /** User mode execution only. */
41 #define XTENSA_MPU_ACCESS_P_NA_U_X (3)
42
43 /** Kernel mode read only. */
44 #define XTENSA_MPU_ACCESS_P_RO_U_NA (4)
45
46 /** Kernel mode read and execution. */
47 #define XTENSA_MPU_ACCESS_P_RX_U_NA (5)
48
49 /** Kernel mode read and write. */
50 #define XTENSA_MPU_ACCESS_P_RW_U_NA (6)
51
52 /** Kernel mode read, write and execution. */
53 #define XTENSA_MPU_ACCESS_P_RWX_U_NA (7)
54
55 /** Kernel and user modes write only. */
56 #define XTENSA_MPU_ACCESS_P_WO_U_WO (8)
57
58 /** Kernel mode read, write. User mode read, write and execution. */
59 #define XTENSA_MPU_ACCESS_P_RW_U_RWX (9)
60
61 /** Kernel mode read and write. User mode read only. */
62 #define XTENSA_MPU_ACCESS_P_RW_U_RO (10)
63
64 /** Kernel mode read, write and execution. User mode read and execution. */
65 #define XTENSA_MPU_ACCESS_P_RWX_U_RX (11)
66
67 /** Kernel and user modes read only. */
68 #define XTENSA_MPU_ACCESS_P_RO_U_RO (12)
69
70 /** Kernel and user modes read and execution. */
71 #define XTENSA_MPU_ACCESS_P_RX_U_RX (13)
72
73 /** Kernel and user modes read and write. */
74 #define XTENSA_MPU_ACCESS_P_RW_U_RW (14)
75
76 /** Kernel and user modes read, write and execution. */
77 #define XTENSA_MPU_ACCESS_P_RWX_U_RWX (15)
78
79 /**
80 * @}
81 */
82
83 /**
84 * @brief Foreground MPU Entry.
85 *
86 * This holds the as, at register values for one MPU entry which can be
87 * used directly by WPTLB.
88 */
89 struct xtensa_mpu_entry {
90 /**
91 * Content of as register for WPTLB.
92 *
93 * This contains the start address, the enable bit, and the lock bit.
94 */
95 union {
96 /** Raw value. */
97 uint32_t raw;
98
99 /** Individual parts. */
100 struct {
101 /**
102 * Enable bit for this entry.
103 *
104 * Modifying this will also modify the corresponding bit of
105 * the MPUENB register.
106 */
107 uint32_t enable:1;
108
109 /**
110 * Lock bit for this entry.
111 *
112 * Usable only if MPULOCKABLE parameter is enabled in
113 * processor configuration.
114 *
115 * Once set:
116 * - This cannot be cleared until reset.
117 * - This entry can no longer be modified.
118 * - The start address of the next entry also
119 * cannot be modified.
120 */
121 uint32_t lock:1;
122
123 /** Must be zero. */
124 uint32_t mbz:3;
125
126 /**
127 * Start address of this MPU entry.
128 *
129 * Effective bits in this portion are affected by the minimum
130 * segment size of each MPU entry, ranging from 32 bytes to 4GB.
131 */
132 uint32_t start_addr:27;
133 } p;
134 } as;
135
136 /**
137 * Content of at register for WPTLB.
138 *
139 * This contains the memory type, access rights, and the segment number.
140 */
141 union {
142 /** Raw value. */
143 uint32_t raw;
144
145 /** Individual parts. */
146 struct {
147 /** The segment number of this MPU entry. */
148 uint32_t segment:5;
149
150 /** Must be zero (part 1). */
151 uint32_t mbz1:3;
152
153 /**
154 * Access rights associated with this MPU entry.
155 *
156 * This dictates the access right from the start address of
157 * this entry, to the start address of next entry.
158 *
159 * Refer to XTENSA_MPU_ACCESS_* macros for available rights.
160 */
161 uint32_t access_rights:4;
162
163 /**
164 * Memory type associated with this MPU entry.
165 *
166 * This dictates the memory type from the start address of
167 * this entry, to the start address of next entry.
168 *
169 * This affects how the hardware treats the memory, for example,
170 * cacheable vs non-cacheable, shareable vs non-shareable.
171 * Refer to the Xtensa Instruction Set Architecture (ISA) manual
172 * for general description, and the processor manual for processor
173 * specific information.
174 */
175 uint32_t memory_type:9;
176
177 /** Must be zero (part 2). */
178 uint32_t mbz2:11;
179 } p;
180 } at;
181 };
182
183 /**
184 * @brief Struct to hold foreground MPU map and its entries.
185 */
186 struct xtensa_mpu_map {
187 /**
188 * Array of MPU entries.
189 */
190 struct xtensa_mpu_entry entries[XTENSA_MPU_NUM_ENTRIES];
191 };
192
193 /**
194 * @name Memory domain and partitions
195 * @{
196 */
197
198 typedef uint32_t k_mem_partition_attr_t;
199
xtensa_mem_partition_is_executable(k_mem_partition_attr_t access_rights)200 static inline bool xtensa_mem_partition_is_executable(k_mem_partition_attr_t access_rights)
201 {
202 bool is_exec;
203
204 switch (access_rights) {
205 case XTENSA_MPU_ACCESS_P_X_U_NA:
206 case XTENSA_MPU_ACCESS_P_NA_U_X:
207 case XTENSA_MPU_ACCESS_P_RX_U_NA:
208 case XTENSA_MPU_ACCESS_P_RWX_U_NA:
209 case XTENSA_MPU_ACCESS_P_RW_U_RWX:
210 case XTENSA_MPU_ACCESS_P_RWX_U_RX:
211 case XTENSA_MPU_ACCESS_P_RX_U_RX:
212 case XTENSA_MPU_ACCESS_P_RWX_U_RWX:
213 is_exec = true;
214 break;
215 default:
216 is_exec = false;
217 break;
218 };
219
220 return is_exec;
221 }
222
xtensa_mem_partition_is_writable(k_mem_partition_attr_t access_rights)223 static inline bool xtensa_mem_partition_is_writable(k_mem_partition_attr_t access_rights)
224 {
225 bool is_writable;
226
227 switch (access_rights) {
228 case XTENSA_MPU_ACCESS_P_RW_U_NA:
229 case XTENSA_MPU_ACCESS_P_RWX_U_NA:
230 case XTENSA_MPU_ACCESS_P_WO_U_WO:
231 case XTENSA_MPU_ACCESS_P_RW_U_RWX:
232 case XTENSA_MPU_ACCESS_P_RW_U_RO:
233 case XTENSA_MPU_ACCESS_P_RWX_U_RX:
234 case XTENSA_MPU_ACCESS_P_RW_U_RW:
235 case XTENSA_MPU_ACCESS_P_RWX_U_RWX:
236 is_writable = true;
237 break;
238 default:
239 is_writable = false;
240 break;
241 };
242
243 return is_writable;
244 }
245
246 #define K_MEM_PARTITION_IS_EXECUTABLE(access_rights) \
247 (xtensa_mem_partition_is_executable(access_rights))
248
249 #define K_MEM_PARTITION_IS_WRITABLE(access_rights) \
250 (xtensa_mem_partition_is_writable(access_rights))
251
252 /* Read-Write access permission attributes */
253 #define K_MEM_PARTITION_P_RW_U_RW \
254 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RW_U_RW})
255 #define K_MEM_PARTITION_P_RW_U_NA \
256 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RW_U_NA})
257 #define K_MEM_PARTITION_P_RO_U_RO \
258 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RO_U_RO})
259 #define K_MEM_PARTITION_P_RO_U_NA \
260 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RO_U_NA})
261 #define K_MEM_PARTITION_P_NA_U_NA \
262 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_NA_U_NA})
263
264 /* Execution-allowed attributes */
265 #define K_MEM_PARTITION_P_RX_U_RX \
266 ((k_mem_partition_attr_t) {XTENSA_MPU_ACCESS_P_RX_U_RX})
267
268 /**
269 * @}
270 */
271
272 /**
273 * Struct to describe a memory region [start, end).
274 */
275 struct xtensa_mpu_range {
276 /** Start address (inclusive) of the memory region. */
277 const uintptr_t start;
278
279 /**
280 * End address (exclusive) of the memory region.
281 *
282 * Use 0xFFFFFFFF for the end of memory.
283 */
284 const uintptr_t end;
285
286 /** Access rights for the memory region. */
287 const uint8_t access_rights:4;
288
289 /**
290 * Memory type for the region.
291 *
292 * Refer to the Xtensa Instruction Set Architecture (ISA) manual
293 * for general description, and the processor manual for processor
294 * specific information.
295 */
296 const uint16_t memory_type:9;
297 } __packed;
298
299 /**
300 * @brief Additional memory regions required by SoC.
301 *
302 * These memory regions will be setup by MPU initialization code at boot.
303 *
304 * Must be defined in the SoC layer.
305 */
306 extern const struct xtensa_mpu_range xtensa_soc_mpu_ranges[];
307
308 /**
309 * @brief Number of SoC additional memory regions.
310 *
311 * Must be defined in the SoC layer.
312 */
313 extern const int xtensa_soc_mpu_ranges_num;
314
315 /**
316 * @brief Initialize hardware MPU.
317 *
318 * This initializes the MPU hardware and setup the memory regions at boot.
319 */
320 void xtensa_mpu_init(void);
321
322 /**
323 * @}
324 */
325
326 #endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_XTENSA_MPU_H */
327