Zephyr Project API 3.7.0
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
arm_mpu_v8.h
Go to the documentation of this file.
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#if defined(CONFIG_AARCH32_ARMV8_R)
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#endif
109
110/* Read/Write Allocation Configurations for Cacheable Memory */
111#define R_NON_W_NON 0x0 /* Do not allocate Read/Write */
112#define R_NON_W_ALLOC 0x1 /* Do not allocate Read, Allocate Write */
113#define R_ALLOC_W_NON 0x2 /* Allocate Read, Do not allocate Write */
114#define R_ALLOC_W_ALLOC 0x3 /* Allocate Read/Write */
115
116/* Memory Attributes for Normal Memory */
117#define NORMAL_O_WT_NT 0x80 /* Normal, Outer Write-through non-transient */
118#define NORMAL_O_WB_NT 0xC0 /* Normal, Outer Write-back non-transient */
119#define NORMAL_O_NON_C 0x40 /* Normal, Outer Non-Cacheable */
120
121#define NORMAL_I_WT_NT 0x08 /* Normal, Inner Write-through non-transient */
122#define NORMAL_I_WB_NT 0x0C /* Normal, Inner Write-back non-transient */
123#define NORMAL_I_NON_C 0x04 /* Normal, Inner Non-Cacheable */
124
125#define NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS \
126 ((NORMAL_O_WT_NT | (R_ALLOC_W_NON << 4)) \
127 | \
128 (NORMAL_I_WT_NT | R_ALLOC_W_NON)) \
129
130#define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS \
131 ((NORMAL_O_WB_NT | (R_ALLOC_W_ALLOC << 4)) \
132 | \
133 (NORMAL_I_WB_NT | R_ALLOC_W_ALLOC))
134
135#define NORMAL_OUTER_INNER_NON_CACHEABLE \
136 ((NORMAL_O_NON_C | (R_NON_W_NON << 4)) \
137 | \
138 (NORMAL_I_NON_C | R_NON_W_NON))
139
140/* Common cache-ability configuration for Flash, SRAM regions */
141#define MPU_CACHE_ATTRIBUTES_FLASH \
142 NORMAL_OUTER_INNER_WRITE_THROUGH_READ_ALLOCATE_NON_TRANS
143#define MPU_CACHE_ATTRIBUTES_SRAM \
144 NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_TRANS
145#define MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE \
146 NORMAL_OUTER_INNER_NON_CACHEABLE
147
148/* Global MAIR configurations */
149#define MPU_MAIR_ATTR_FLASH MPU_CACHE_ATTRIBUTES_FLASH
150#define MPU_MAIR_INDEX_FLASH 0
151#define MPU_MAIR_ATTR_SRAM MPU_CACHE_ATTRIBUTES_SRAM
152#define MPU_MAIR_INDEX_SRAM 1
153#define MPU_MAIR_ATTR_SRAM_NOCACHE MPU_CACHE_ATTRIBUTES_SRAM_NOCACHE
154#define MPU_MAIR_INDEX_SRAM_NOCACHE 2
155
156#if defined(CONFIG_AARCH32_ARMV8_R)
157#define MPU_MAIR_ATTR_DEVICE DEVICE_nGnRnE
158#define MPU_MAIR_INDEX_DEVICE 3
159/* Flash region(s): Attribute-0
160 * SRAM region(s): Attribute-1
161 * SRAM no cache-able regions(s): Attribute-2
162 * DEVICE no cache-able regions(s): Attribute-3
163 */
164#define MPU_MAIR_ATTRS \
165 ((MPU_MAIR_ATTR_FLASH << (MPU_MAIR_INDEX_FLASH * 8)) | \
166 (MPU_MAIR_ATTR_SRAM << (MPU_MAIR_INDEX_SRAM * 8)) | \
167 (MPU_MAIR_ATTR_SRAM_NOCACHE << (MPU_MAIR_INDEX_SRAM_NOCACHE * 8)) | \
168 (MPU_MAIR_ATTR_DEVICE << (MPU_MAIR_INDEX_DEVICE * 8)))
169#else
170/* Flash region(s): Attribute-0
171 * SRAM region(s): Attribute-1
172 * SRAM no cache-able regions(s): Attribute-2
173 */
174#define MPU_MAIR_ATTRS \
175 (((MPU_MAIR_ATTR_FLASH << MPU_MAIR0_Attr0_Pos) & MPU_MAIR0_Attr0_Msk) | \
176 ((MPU_MAIR_ATTR_SRAM << MPU_MAIR0_Attr1_Pos) & MPU_MAIR0_Attr1_Msk) | \
177 ((MPU_MAIR_ATTR_SRAM_NOCACHE << MPU_MAIR0_Attr2_Pos) & \
178 MPU_MAIR0_Attr2_Msk))
179#endif
180
181/* Some helper defines for common regions.
182 *
183 * Note that the ARMv8-M/R MPU architecture requires that the
184 * enabled MPU regions are non-overlapping. Therefore, it is
185 * recommended to use these helper defines only for configuring
186 * fixed MPU regions at build-time (i.e. regions that are not
187 * expected to be re-programmed or re-adjusted at run-time so
188 * that they do not overlap with other MPU regions).
189 */
190#if defined(CONFIG_AARCH32_ARMV8_R)
191
192#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \
193 { .name = p_name, \
194 .base = p_base, \
195 .attr = p_attr(p_base + p_size), \
196 }
197
198#define REGION_RAM_ATTR(limit) \
199 { \
200 .rbar = NOT_EXEC | \
201 P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
202 /* Cache-ability */ \
203 .mair_idx = MPU_MAIR_INDEX_SRAM, \
204 .r_limit = limit - 1, /* Region Limit */ \
205 }
206
207#define REGION_RAM_TEXT_ATTR(limit) \
208 { \
209 .rbar = P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
210 /* Cache-ability */ \
211 .mair_idx = MPU_MAIR_INDEX_SRAM, \
212 .r_limit = limit - 1, /* Region Limit */ \
213 }
214
215#define REGION_RAM_RO_ATTR(limit) \
216 { \
217 .rbar = NOT_EXEC | \
218 P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
219 /* Cache-ability */ \
220 .mair_idx = MPU_MAIR_INDEX_SRAM, \
221 .r_limit = limit - 1, /* Region Limit */ \
222 }
223#define REGION_RAM_NOCACHE_ATTR(limit) \
224 { \
225 .rbar = NOT_EXEC | \
226 P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
227 /* Cache-ability */ \
228 .mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \
229 .r_limit = limit - 1, /* Region Limit */ \
230 }
231#if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
232/* Note that the access permissions allow for un-privileged writes, contrary
233 * to ARMv7-M where un-privileged code has Read-Only permissions.
234 */
235#define REGION_FLASH_ATTR(limit) \
236 { \
237 .rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
238 /* Cache-ability */ \
239 .mair_idx = MPU_MAIR_INDEX_FLASH, \
240 .r_limit = limit - 1, /* Region Limit */ \
241 }
242#else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
243#define REGION_FLASH_ATTR(limit) \
244 { \
245 .rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
246 /* Cache-ability */ \
247 .mair_idx = MPU_MAIR_INDEX_FLASH, \
248 .r_limit = limit - 1, /* Region Limit */ \
249 }
250#endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
251
252#define REGION_DEVICE_ATTR(limit) \
253 { \
254 /* AP, XN, SH */ \
255 .rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \
256 /* Cache-ability */ \
257 .mair_idx = MPU_MAIR_INDEX_DEVICE, \
258 /* Region Limit */ \
259 .r_limit = limit - 1, \
260 }
261#else
262
263#define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr) \
264 { .name = p_name, \
265 .base = p_base, \
266 .attr = p_attr(p_base, p_size), \
267 }
268
269/* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When
270 * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep
271 * the SRAM region XN bit clear or the application code will not be executable.
272 */
273#define REGION_RAM_ATTR(base, size) \
274 {\
275 .rbar = IF_ENABLED(CONFIG_XIP, (NOT_EXEC |)) \
276 P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
277 /* Cache-ability */ \
278 .mair_idx = MPU_MAIR_INDEX_SRAM, \
279 .r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
280 }
281
282#define REGION_RAM_NOCACHE_ATTR(base, size) \
283 {\
284 .rbar = NOT_EXEC | \
285 P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
286 /* Cache-ability */ \
287 .mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \
288 .r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
289 }
290
291#if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
292/* Note that the access permissions allow for un-privileged writes, contrary
293 * to ARMv7-M where un-privileged code has Read-Only permissions.
294 */
295#define REGION_FLASH_ATTR(base, size) \
296 {\
297 .rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
298 /* Cache-ability */ \
299 .mair_idx = MPU_MAIR_INDEX_FLASH, \
300 .r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
301 }
302#else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
303#define REGION_FLASH_ATTR(base, size) \
304 {\
305 .rbar = RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
306 /* Cache-ability */ \
307 .mair_idx = MPU_MAIR_INDEX_FLASH, \
308 .r_limit = REGION_LIMIT_ADDR(base, size), /* Region Limit */ \
309 }
310#endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
311
312#endif
313
314struct arm_mpu_region_attr {
315 /* Attributes belonging to RBAR */
317 /* MAIR index for attribute indirection */
319 /* Region Limit Address value to be written to the RLAR register. */
321};
322
324
325/* Typedef for the k_mem_partition attribute */
326typedef struct {
330
331/* Kernel macros for memory attribution
332 * (access permissions and cache-ability).
333 *
334 * The macros are to be stored in k_mem_partition_attr_t
335 * objects. The format of a k_mem_partition_attr_t object
336 * is as follows: field <rbar> contains a direct mapping
337 * of the <XN> and <AP> bit-fields of the RBAR register;
338 * field <mair_idx> contains a direct mapping of AttrIdx
339 * bit-field, stored in RLAR register.
340 */
341
342/* Read-Write access permission attributes */
343#define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \
344 {(P_RW_U_RW_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
345#define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \
346 {(P_RW_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
347#define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \
348 {(P_RO_U_RO_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
349#define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \
350 {(P_RO_U_NA_Msk | NOT_EXEC), MPU_MAIR_INDEX_SRAM})
351
352/* Execution-allowed attributes */
353#define K_MEM_PARTITION_P_RWX_U_RWX ((k_mem_partition_attr_t) \
354 {(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM})
355#define K_MEM_PARTITION_P_RX_U_RX ((k_mem_partition_attr_t) \
356 {(P_RO_U_RO_Msk), MPU_MAIR_INDEX_SRAM})
357
358/*
359 * @brief Evaluate Write-ability
360 *
361 * Evaluate whether the access permissions include write-ability.
362 *
363 * @param attr The k_mem_partition_attr_t object holding the
364 * MPU attributes to be checked against write-ability.
365 */
366#define K_MEM_PARTITION_IS_WRITABLE(attr) \
367 ({ \
368 int __is_writable__; \
369 switch (attr.rbar & MPU_RBAR_AP_Msk) { \
370 case P_RW_U_RW_Msk: \
371 case P_RW_U_NA_Msk: \
372 __is_writable__ = 1; \
373 break; \
374 default: \
375 __is_writable__ = 0; \
376 } \
377 __is_writable__; \
378 })
379
380/*
381 * @brief Evaluate Execution allowance
382 *
383 * Evaluate whether the access permissions include execution.
384 *
385 * @param attr The k_mem_partition_attr_t object holding the
386 * MPU attributes to be checked against execution
387 * allowance.
388 */
389#define K_MEM_PARTITION_IS_EXECUTABLE(attr) \
390 (!((attr.rbar) & (NOT_EXEC)))
391
392/* Attributes for no-cache enabling (share-ability is selected by default) */
393
394/* Read-Write access permission attributes */
395#define K_MEM_PARTITION_P_RW_U_RW_NOCACHE ((k_mem_partition_attr_t) \
396 {(P_RW_U_RW_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
397 MPU_MAIR_INDEX_SRAM_NOCACHE})
398#define K_MEM_PARTITION_P_RW_U_NA_NOCACHE ((k_mem_partition_attr_t) \
399 {(P_RW_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
400 MPU_MAIR_INDEX_SRAM_NOCACHE})
401#define K_MEM_PARTITION_P_RO_U_RO_NOCACHE ((k_mem_partition_attr_t) \
402 {(P_RO_U_RO_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
403 MPU_MAIR_INDEX_SRAM_NOCACHE})
404#define K_MEM_PARTITION_P_RO_U_NA_NOCACHE ((k_mem_partition_attr_t) \
405 {(P_RO_U_NA_Msk | NOT_EXEC | OUTER_SHAREABLE_Msk), \
406 MPU_MAIR_INDEX_SRAM_NOCACHE})
407
408/* Execution-allowed attributes */
409#define K_MEM_PARTITION_P_RWX_U_RWX_NOCACHE ((k_mem_partition_attr_t) \
410 {(P_RW_U_RW_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
411#define K_MEM_PARTITION_P_RX_U_RX_NOCACHE ((k_mem_partition_attr_t) \
412 {(P_RO_U_RO_Msk | OUTER_SHAREABLE_Msk), MPU_MAIR_INDEX_SRAM_NOCACHE})
413
414#endif /* _ASMLANGUAGE */
415
416#define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size) \
417 BUILD_ASSERT((size > 0) && ((uint32_t)start % \
418 CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0U) && \
419 ((size) % CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE == 0), \
420 " the start and size of the partition must align " \
421 "with the minimum MPU region size.")
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
__UINT16_TYPE__ uint16_t
Definition stdint.h:89
Definition arm_mpu_v7m.h:152
uint8_t rbar
Definition arm_mpu_v8.h:316
uint32_t r_limit
Definition arm_mpu_v8.h:320
uint8_t mair_idx
Definition arm_mpu_v8.h:318
Definition arm_mpu_v7m.h:160
uint16_t rbar
Definition arm_mpu_v8.h:327
uint16_t mair_idx
Definition arm_mpu_v8.h:328