Line data Source code
1 0 : /*
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 0 : #define P_RW_U_NA 0x0
46 0 : #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 0 : #define P_RW_U_RW 0x1
52 0 : #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 0 : #define FULL_ACCESS 0x1
55 0 : #define FULL_ACCESS_Msk ((FULL_ACCESS << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
56 : /* Privileged Read Only, Unprivileged No Access */
57 0 : #define P_RO_U_NA 0x2
58 0 : #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 0 : #define P_RO_U_RO 0x3
61 0 : #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 0 : #define RO 0x3
64 0 : #define RO_Msk ((RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
65 :
66 : /* Attribute flag for not-allowing execution (eXecute Never) */
67 0 : #define NOT_EXEC MPU_RBAR_XN_Msk
68 :
69 : /* Attribute flags for share-ability */
70 0 : #define NON_SHAREABLE 0x0
71 0 : #define NON_SHAREABLE_Msk \
72 : ((NON_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
73 0 : #define OUTER_SHAREABLE 0x2
74 0 : #define OUTER_SHAREABLE_Msk \
75 : ((OUTER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
76 0 : #define INNER_SHAREABLE 0x3
77 0 : #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 0 : #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 0 : #define DEVICE_nGnRnE 0x0U
105 0 : #define DEVICE_nGnRE 0x4U
106 0 : #define DEVICE_nGRE 0x8U
107 0 : #define DEVICE_GRE 0xCU
108 :
109 : /* Read/Write Allocation Configurations for Cacheable Memory */
110 0 : #define R_NON_W_NON 0x0 /* Do not allocate Read/Write */
111 0 : #define R_NON_W_ALLOC 0x1 /* Do not allocate Read, Allocate Write */
112 0 : #define R_ALLOC_W_NON 0x2 /* Allocate Read, Do not allocate Write */
113 0 : #define R_ALLOC_W_ALLOC 0x3 /* Allocate Read/Write */
114 :
115 : /* Memory Attributes for Normal Memory */
116 0 : #define NORMAL_O_WT_NT 0x80 /* Normal, Outer Write-through non-transient */
117 0 : #define NORMAL_O_WB_NT 0xC0 /* Normal, Outer Write-back non-transient */
118 0 : #define NORMAL_O_NON_C 0x40 /* Normal, Outer Non-Cacheable */
119 :
120 0 : #define NORMAL_I_WT_NT 0x08 /* Normal, Inner Write-through non-transient */
121 0 : #define NORMAL_I_WB_NT 0x0C /* Normal, Inner Write-back non-transient */
122 0 : #define NORMAL_I_NON_C 0x04 /* Normal, Inner Non-Cacheable */
123 :
124 0 : #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 0 : #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 0 : #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 0 : #define MPU_CACHE_ATTRIBUTES_FLASH \
141 : NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS
142 0 : #define MPU_CACHE_ATTRIBUTES_SRAM \
143 : NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS
144 0 : #define MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE \
145 : NORMAL_OUTER_INNER_NON_CACHEABLE
146 :
147 : /* Global MAIR configurations */
148 0 : #define MPU_MAIR_ATTR_FLASH MPU_CACHE_ATTRIBUTES_FLASH
149 0 : #define MPU_MAIR_INDEX_FLASH 0
150 0 : #define MPU_MAIR_ATTR_SRAM MPU_CACHE_ATTRIBUTES_SRAM
151 0 : #define MPU_MAIR_INDEX_SRAM 1
152 0 : #define MPU_MAIR_ATTR_SRAM_NOCACHE MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE
153 0 : #define MPU_MAIR_INDEX_SRAM_NOCACHE 2
154 0 : #define MPU_MAIR_ATTR_DEVICE DEVICE_nGnRnE
155 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : uint8_t rbar: 5;
310 : /* MAIR index for attribute indirection */
311 0 : uint8_t mair_idx: 3;
312 : /* Region Limit Address value to be written to the RLAR register. */
313 0 : 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 0 : uint16_t rbar;
321 0 : 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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #define K_MEM_PARTITION_P_RWX_U_RWX ((k_mem_partition_attr_t) \
347 : {(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM})
348 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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 0 : #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.")
|