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