1 /*
2  * Copyright (c) 2018 Linaro Limited.
3  * Copyright (c) 2018 Nordic Semiconductor ASA.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef _ASMLANGUAGE
9 
10 /* Convenience macros to represent the ARMv8-M-specific
11  * configuration for memory access permission and
12  * cache-ability attribution.
13  */
14 #if defined(CONFIG_AARCH32_ARMV8_R)
15 #define MPU_IR_REGION_Msk       (0xFFU)
16 #define MPU_IR_REGION_Pos       8U
17 /* MPU RBAR Register attribute msk Definitions */
18 #define MPU_RBAR_BASE_Pos       6U
19 #define MPU_RBAR_BASE_Msk       (0x3FFFFFFFFFFFFFFUL << MPU_RBAR_BASE_Pos)
20 #define MPU_RBAR_SH_Pos         3U
21 #define MPU_RBAR_SH_Msk         (0x3UL << MPU_RBAR_SH_Pos)
22 #define MPU_RBAR_AP_Pos         1U
23 #define MPU_RBAR_AP_Msk         (0x3UL << MPU_RBAR_AP_Pos)
24 /* RBAR XN */
25 #define MPU_RBAR_XN_Pos         0U
26 #define MPU_RBAR_XN_Msk         (0x1UL << MPU_RBAR_XN_Pos)
27 
28 /* MPU PLBAR Register Definitions */
29 #define MPU_RLAR_LIMIT_Pos      6U
30 #define MPU_RLAR_LIMIT_Msk      (0x3FFFFFFFFFFFFFFUL << MPU_RLAR_LIMIT_Pos)
31 #define MPU_RLAR_AttrIndx_Pos   1U
32 #define MPU_RLAR_AttrIndx_Msk   (0x7UL << MPU_RLAR_AttrIndx_Pos)
33 #define MPU_RLAR_EN_Msk         (0x1UL)
34 #else
35 #include <cmsis_core.h>
36 #endif
37 
38 /* Privileged No Access, Unprivileged No Access */
39 /*#define NO_ACCESS       0x0 */
40 /*#define NO_ACCESS_Msk   ((NO_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) */
41 /* Privileged No Access, Unprivileged No Access */
42 /*#define P_NA_U_NA       0x0 */
43 /*#define P_NA_U_NA_Msk   ((P_NA_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) */
44 /* Privileged Read Write, Unprivileged No Access */
45 #define P_RW_U_NA       0x0
46 #define P_RW_U_NA_Msk   ((P_RW_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
47 /* Privileged Read Write, Unprivileged Read Only */
48 /*#define P_RW_U_RO       0x2 */
49 /*#define P_RW_U_RO_Msk   ((P_RW_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)*/
50 /* Privileged Read Write, Unprivileged Read Write */
51 #define P_RW_U_RW       0x1
52 #define P_RW_U_RW_Msk   ((P_RW_U_RW << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
53 /* Privileged Read Write, Unprivileged Read Write */
54 #define FULL_ACCESS     0x1
55 #define FULL_ACCESS_Msk ((FULL_ACCESS << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
56 /* Privileged Read Only, Unprivileged No Access */
57 #define P_RO_U_NA       0x2
58 #define P_RO_U_NA_Msk   ((P_RO_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
59 /* Privileged Read Only, Unprivileged Read Only */
60 #define P_RO_U_RO       0x3
61 #define P_RO_U_RO_Msk   ((P_RO_U_RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
62 /* Privileged Read Only, Unprivileged Read Only */
63 #define RO              0x3
64 #define RO_Msk          ((RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
65 
66 /* Attribute flag for not-allowing execution (eXecute Never) */
67 #define NOT_EXEC MPU_RBAR_XN_Msk
68 
69 /* Attribute flags for share-ability */
70 #define NON_SHAREABLE       0x0
71 #define NON_SHAREABLE_Msk \
72 	((NON_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
73 #define OUTER_SHAREABLE 0x2
74 #define OUTER_SHAREABLE_Msk \
75 	((OUTER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
76 #define INNER_SHAREABLE 0x3
77 #define INNER_SHAREABLE_Msk \
78 	((INNER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
79 
80 /* Helper define to calculate the region limit address. */
81 #define REGION_LIMIT_ADDR(base, size) \
82 	(((base & MPU_RBAR_BASE_Msk) + size - 1) & MPU_RLAR_LIMIT_Msk)
83 
84 /* Attribute flags for cache-ability */
85 
86 /* Memory Attributes for Device Memory
87  * 1.Gathering (G/nG)
88  *   Determines whether multiple accesses can be merged into a single
89  *   bus transaction.
90  *   nG: Number/size of accesses on the bus = number/size of accesses
91  *   in code.
92  *
93  * 2.Reordering (R/nR)
94  *   Determines whether accesses to the same device can be reordered.
95  *   nR: Accesses to the same IMPLEMENTATION DEFINED block size will
96  *   appear on the bus in program order.
97  *
98  * 3 Early Write Acknowledgment (E/nE)
99  *   Indicates to the memory system whether a buffer can send
100  *   acknowledgements.
101  *   nE: The response should come from the end slave, not buffering in
102  *   the interconnect.
103  */
104 #define DEVICE_nGnRnE	0x0U
105 #define DEVICE_nGnRE	0x4U
106 #define DEVICE_nGRE	0x8U
107 #define DEVICE_GRE	0xCU
108 
109 /* Read/Write Allocation Configurations for Cacheable Memory */
110 #define R_NON_W_NON     0x0 /* Do not allocate Read/Write */
111 #define R_NON_W_ALLOC   0x1 /* Do not allocate Read, Allocate Write */
112 #define R_ALLOC_W_NON   0x2 /* Allocate Read, Do not allocate Write */
113 #define R_ALLOC_W_ALLOC 0x3 /* Allocate Read/Write */
114 
115 /* Memory Attributes for Normal Memory */
116 #define NORMAL_O_WT_NT  0x80 /* Normal, Outer Write-through non-transient */
117 #define NORMAL_O_WB_NT  0xC0 /* Normal, Outer Write-back non-transient */
118 #define NORMAL_O_NON_C  0x40 /* Normal, Outer Non-Cacheable  */
119 
120 #define NORMAL_I_WT_NT  0x08 /* Normal, Inner Write-through non-transient */
121 #define NORMAL_I_WB_NT  0x0C /* Normal, Inner Write-back non-transient */
122 #define NORMAL_I_NON_C  0x04 /* Normal, Inner Non-Cacheable  */
123 
124 #define NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS \
125 	((NORMAL_O_WT_NT | (R_ALLOC_W_NON << 4)) \
126 	 | \
127 	 (NORMAL_I_WT_NT | R_ALLOC_W_NON)) \
128 
129 #define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS \
130 	((NORMAL_O_WB_NT | (R_ALLOC_W_ALLOC << 4)) \
131 	 | \
132 	 (NORMAL_I_WB_NT | R_ALLOC_W_ALLOC))
133 
134 #define NORMAL_OUTER_INNER_NON_CACHEABLE \
135 	((NORMAL_O_NON_C | (R_NON_W_NON << 4)) \
136 	 | \
137 	 (NORMAL_I_NON_C | R_NON_W_NON))
138 
139 /* Common cache-ability configuration for Flash, SRAM regions */
140 #define MPU_CACHE_ATTRIBUTES_FLASH \
141 	NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS
142 #define MPU_CACHE_ATTRIBUTES_SRAM \
143 	NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS
144 #define MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE \
145 	NORMAL_OUTER_INNER_NON_CACHEABLE
146 
147 /* Global MAIR configurations */
148 #define MPU_MAIR_ATTR_FLASH         MPU_CACHE_ATTRIBUTES_FLASH
149 #define MPU_MAIR_INDEX_FLASH        0
150 #define MPU_MAIR_ATTR_SRAM          MPU_CACHE_ATTRIBUTES_SRAM
151 #define MPU_MAIR_INDEX_SRAM         1
152 #define MPU_MAIR_ATTR_SRAM_NOCACHE  MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE
153 #define MPU_MAIR_INDEX_SRAM_NOCACHE 2
154 #define MPU_MAIR_ATTR_DEVICE        DEVICE_nGnRnE
155 #define MPU_MAIR_INDEX_DEVICE       3
156 /* Flash region(s): Attribute-0
157  * SRAM region(s): Attribute-1
158  * SRAM no cache-able regions(s): Attribute-2
159  * DEVICE no cache-able regions(s): Attribute-3
160  */
161 #define MPU_MAIR_ATTRS							     \
162 	((MPU_MAIR_ATTR_FLASH << (MPU_MAIR_INDEX_FLASH * 8)) |		     \
163 	 (MPU_MAIR_ATTR_SRAM << (MPU_MAIR_INDEX_SRAM * 8)) |		     \
164 	 (MPU_MAIR_ATTR_SRAM_NOCACHE << (MPU_MAIR_INDEX_SRAM_NOCACHE * 8)) | \
165 	 (MPU_MAIR_ATTR_DEVICE << (MPU_MAIR_INDEX_DEVICE * 8)))
166 
167 /* Some helper defines for common regions.
168  *
169  * Note that the ARMv8-M/R MPU architecture requires that the
170  * enabled MPU regions are non-overlapping. Therefore, it is
171  * recommended to use these helper defines only for configuring
172  * fixed MPU regions at build-time (i.e. regions that are not
173  * expected to be re-programmed or re-adjusted at run-time so
174  * that they do not overlap with other MPU regions).
175  */
176 #if defined(CONFIG_AARCH32_ARMV8_R)
177 
178 #define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr)	\
179 	{ .name = p_name,					\
180 	  .base = p_base,					\
181 	  .attr = p_attr(p_base + p_size),			\
182 	}
183 
184 #define REGION_RAM_ATTR(limit)						    \
185 	{								    \
186 		.rbar = NOT_EXEC |					    \
187 			P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
188 		/* Cache-ability */					    \
189 		.mair_idx = MPU_MAIR_INDEX_SRAM,			    \
190 		.r_limit = limit - 1,  /* Region Limit */		    \
191 	}
192 
193 #define REGION_RAM_TEXT_ATTR(limit)					    \
194 	{								    \
195 		.rbar = P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
196 		/* Cache-ability */					    \
197 		.mair_idx = MPU_MAIR_INDEX_SRAM,			    \
198 		.r_limit = limit - 1,  /* Region Limit */		    \
199 	}
200 
201 #define REGION_RAM_RO_ATTR(limit)					    \
202 	{								    \
203 		.rbar = NOT_EXEC |					    \
204 			P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
205 		/* Cache-ability */					    \
206 		.mair_idx = MPU_MAIR_INDEX_SRAM,			    \
207 		.r_limit = limit - 1,  /* Region Limit */		    \
208 	}
209 #define REGION_RAM_NOCACHE_ATTR(limit)					    \
210 	{								    \
211 		.rbar = NOT_EXEC |					    \
212 			P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
213 		/* Cache-ability */					    \
214 		.mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE,		    \
215 		.r_limit = limit - 1,  /* Region Limit */		    \
216 	}
217 #if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
218 /* Note that the access permissions allow for un-privileged writes, contrary
219  * to ARMv7-M where un-privileged code has Read-Only permissions.
220  */
221 #define REGION_FLASH_ATTR(limit)					    \
222 	{								    \
223 		.rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
224 		/* Cache-ability */					    \
225 		.mair_idx = MPU_MAIR_INDEX_FLASH,			    \
226 		.r_limit = limit - 1,  /* Region Limit */		    \
227 	}
228 #else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
229 #define REGION_FLASH_ATTR(limit)				     \
230 	{							     \
231 		.rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
232 		/* Cache-ability */				     \
233 		.mair_idx = MPU_MAIR_INDEX_FLASH,		     \
234 		.r_limit = limit - 1,  /* Region Limit */	     \
235 	}
236 #endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
237 
238 #define REGION_DEVICE_ATTR(limit)				      \
239 	{							      \
240 		/* AP, XN, SH */				      \
241 		.rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \
242 		/* Cache-ability */				      \
243 		.mair_idx = MPU_MAIR_INDEX_DEVICE,		      \
244 		/* Region Limit */				      \
245 		.r_limit = limit - 1,				      \
246 	}
247 #else
248 
249 #define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr)	\
250 	{ .name = p_name,					\
251 	  .base = p_base,					\
252 	  .attr = p_attr(p_base, p_size),			\
253 	}
254 
255 /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When
256  * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep
257  * the SRAM region XN bit clear or the application code will not be executable.
258  */
259 #define REGION_RAM_ATTR(base, size) \
260 	{\
261 		.rbar = IF_ENABLED(CONFIG_XIP, (NOT_EXEC |)) \
262 			P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
263 		/* Cache-ability */ \
264 		.mair_idx = MPU_MAIR_INDEX_SRAM, \
265 		.r_limit = REGION_LIMIT_ADDR(base, size),  /* Region Limit */ \
266 	}
267 
268 #define REGION_RAM_NOCACHE_ATTR(base, size) \
269 	{\
270 		.rbar = NOT_EXEC | \
271 			P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
272 		/* Cache-ability */ \
273 		.mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \
274 		.r_limit = REGION_LIMIT_ADDR(base, size),  /* Region Limit */ \
275 	}
276 
277 #if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
278 /* Note that the access permissions allow for un-privileged writes, contrary
279  * to ARMv7-M where un-privileged code has Read-Only permissions.
280  */
281 #define REGION_FLASH_ATTR(base, size) \
282 	{\
283 		.rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
284 		/* Cache-ability */ \
285 		.mair_idx = MPU_MAIR_INDEX_FLASH, \
286 		.r_limit = REGION_LIMIT_ADDR(base, size),  /* Region Limit */ \
287 	}
288 #else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
289 #define REGION_FLASH_ATTR(base, size) \
290 	{\
291 		.rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
292 		/* Cache-ability */ \
293 		.mair_idx = MPU_MAIR_INDEX_FLASH, \
294 		.r_limit = REGION_LIMIT_ADDR(base, size),  /* Region Limit */ \
295 	}
296 #endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
297 
298 #define REGION_DEVICE_ATTR(base, size)                                                             \
299 	{                                                                                          \
300 		/* AP, XN, SH */                                                                   \
301 		.rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* Cache-ability */          \
302 		.mair_idx = MPU_MAIR_INDEX_DEVICE,                                                 \
303 		.r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */                       \
304 	}
305 #endif
306 
307 struct arm_mpu_region_attr {
308 	/* Attributes belonging to RBAR */
309 	uint8_t rbar: 5;
310 	/* MAIR index for attribute indirection */
311 	uint8_t mair_idx: 3;
312 	/* Region Limit Address value to be written to the RLAR register. */
313 	uint32_t r_limit;
314 };
315 
316 typedef struct arm_mpu_region_attr arm_mpu_region_attr_t;
317 
318 /* Typedef for the k_mem_partition attribute */
319 typedef struct {
320 	uint16_t rbar;
321 	uint16_t mair_idx;
322 } k_mem_partition_attr_t;
323 
324 /* Kernel macros for memory attribution
325  * (access permissions and cache-ability).
326  *
327  * The macros are to be stored in k_mem_partition_attr_t
328  * objects. The format of a k_mem_partition_attr_t object
329  * is as follows: field <rbar> contains a direct mapping
330  * of the <XN> and <AP> bit-fields of the RBAR register;
331  * field <mair_idx> contains a direct mapping of AttrIdx
332  * bit-field, stored in RLAR register.
333  */
334 
335 /* Read-Write access permission attributes */
336 #define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \
337 	{(P_RW_U_RW_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
338 #define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \
339 	{(P_RW_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
340 #define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \
341 	{(P_RO_U_RO_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
342 #define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \
343 	{(P_RO_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
344 
345 /* Execution-allowed attributes */
346 #define K_MEM_PARTITION_P_RWX_U_RWX ((k_mem_partition_attr_t) \
347 	{(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM})
348 #define K_MEM_PARTITION_P_RX_U_RX ((k_mem_partition_attr_t) \
349 	{(P_RO_U_RO_Msk), MPU_MAIR_INDEX_SRAM})
350 
351 /*
352  * @brief Evaluate Write-ability
353  *
354  * Evaluate whether the access permissions include write-ability.
355  *
356  * @param attr The k_mem_partition_attr_t object holding the
357  *             MPU attributes to be checked against write-ability.
358  */
359 #define K_MEM_PARTITION_IS_WRITABLE(attr) \
360 	({ \
361 		int __is_writable__; \
362 		switch (attr.rbar & MPU_RBAR_AP_Msk) { \
363 		case P_RW_U_RW_Msk: \
364 		case P_RW_U_NA_Msk: \
365 			__is_writable__ = 1; \
366 			break; \
367 		default: \
368 			__is_writable__ = 0; \
369 		} \
370 		__is_writable__; \
371 	})
372 
373 /*
374  * @brief Evaluate Execution allowance
375  *
376  * Evaluate whether the access permissions include execution.
377  *
378  * @param attr The k_mem_partition_attr_t object holding the
379  *             MPU attributes to be checked against execution
380  *             allowance.
381  */
382 #define K_MEM_PARTITION_IS_EXECUTABLE(attr) \
383 	(!((attr.rbar) & (NOT_EXEC)))
384 
385 /* Attributes for no-cache enabling (share-ability is selected by default) */
386 
387 /* Read-Write access permission attributes */
388 #define K_MEM_PARTITION_P_RW_U_RW_NOCACHE ((k_mem_partition_attr_t) \
389 	{(P_RW_U_RW_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
390 		MPU_MAIR_INDEX_SRAM_NOCACHE})
391 #define K_MEM_PARTITION_P_RW_U_NA_NOCACHE ((k_mem_partition_attr_t) \
392 	{(P_RW_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
393 		MPU_MAIR_INDEX_SRAM_NOCACHE})
394 #define K_MEM_PARTITION_P_RO_U_RO_NOCACHE ((k_mem_partition_attr_t) \
395 	{(P_RO_U_RO_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
396 		MPU_MAIR_INDEX_SRAM_NOCACHE})
397 #define K_MEM_PARTITION_P_RO_U_NA_NOCACHE ((k_mem_partition_attr_t) \
398 	{(P_RO_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
399 		MPU_MAIR_INDEX_SRAM_NOCACHE})
400 
401 /* Execution-allowed attributes */
402 #define K_MEM_PARTITION_P_RWX_U_RWX_NOCACHE ((k_mem_partition_attr_t) \
403 	{(P_RW_U_RW_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
404 #define K_MEM_PARTITION_P_RX_U_RX_NOCACHE ((k_mem_partition_attr_t) \
405 	{(P_RO_U_RO_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
406 
407 #endif /* _ASMLANGUAGE */
408 
409 #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \
410 	BUILD_ASSERT((size > 0) && ((uint32_t)start % \
411 			CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0U) && \
412 		((size) % CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0), \
413 		" the start and size of the partition must align " \
414 		"with the minimum MPU region size.")
415