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