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 #include <cmsis_core.h>
11 
12 /* Convenience macros to represent the ARMv7-M-specific
13  * configuration for memory access permission and
14  * cache-ability attribution.
15  */
16 
17 /* Privileged No Access, Unprivileged No Access */
18 #define NO_ACCESS       0x0
19 #define NO_ACCESS_Msk   ((NO_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
20 /* Privileged No Access, Unprivileged No Access */
21 #define P_NA_U_NA       0x0
22 #define P_NA_U_NA_Msk   ((P_NA_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
23 /* Privileged Read Write, Unprivileged No Access */
24 #define P_RW_U_NA       0x1
25 #define P_RW_U_NA_Msk   ((P_RW_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
26 /* Privileged Read Write, Unprivileged Read Only */
27 #define P_RW_U_RO       0x2
28 #define P_RW_U_RO_Msk   ((P_RW_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
29 /* Privileged Read Write, Unprivileged Read Write */
30 #define P_RW_U_RW       0x3U
31 #define P_RW_U_RW_Msk   ((P_RW_U_RW << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
32 /* Privileged Read Write, Unprivileged Read Write */
33 #define FULL_ACCESS     0x3
34 #define FULL_ACCESS_Msk ((FULL_ACCESS << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
35 /* Privileged Read Only, Unprivileged No Access */
36 #define P_RO_U_NA       0x5
37 #define P_RO_U_NA_Msk   ((P_RO_U_NA << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
38 /* Privileged Read Only, Unprivileged Read Only */
39 #define P_RO_U_RO       0x6
40 #define P_RO_U_RO_Msk   ((P_RO_U_RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
41 /* Privileged Read Only, Unprivileged Read Only */
42 #define RO              0x7
43 #define RO_Msk          ((RO << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk)
44 
45 /* Attribute flag for not-allowing execution (eXecute Never) */
46 #define NOT_EXEC MPU_RASR_XN_Msk
47 
48 /* The following definitions are for internal use in arm_mpu.h. */
49 #define STRONGLY_ORDERED_SHAREABLE                     MPU_RASR_S_Msk
50 #define DEVICE_SHAREABLE                               (MPU_RASR_B_Msk | MPU_RASR_S_Msk)
51 #define NORMAL_OUTER_INNER_WRITE_THROUGH_SHAREABLE     (MPU_RASR_C_Msk | MPU_RASR_S_Msk)
52 #define NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE MPU_RASR_C_Msk
53 /* clang-format off */
54 #define NORMAL_OUTER_INNER_WRITE_BACK_SHAREABLE                                                    \
55 	(MPU_RASR_C_Msk | MPU_RASR_B_Msk | MPU_RASR_S_Msk)
56 /* clang-format on */
57 #define NORMAL_OUTER_INNER_WRITE_BACK_NON_SHAREABLE    (MPU_RASR_C_Msk | MPU_RASR_B_Msk)
58 #define NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE     ((1 << MPU_RASR_TEX_Pos) | MPU_RASR_S_Msk)
59 #define NORMAL_OUTER_INNER_NON_CACHEABLE_NON_SHAREABLE (1 << MPU_RASR_TEX_Pos)
60 #define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_SHAREABLE                                \
61 	((1 << MPU_RASR_TEX_Pos) | MPU_RASR_C_Msk | MPU_RASR_B_Msk | MPU_RASR_S_Msk)
62 #define NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE                            \
63 	((1 << MPU_RASR_TEX_Pos) | MPU_RASR_C_Msk | MPU_RASR_B_Msk)
64 #define DEVICE_NON_SHAREABLE (2 << MPU_RASR_TEX_Pos)
65 
66 /* Bit-masks to disable sub-regions. */
67 #define SUB_REGION_0_DISABLED ((0x01 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
68 #define SUB_REGION_1_DISABLED ((0x02 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
69 #define SUB_REGION_2_DISABLED ((0x04 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
70 #define SUB_REGION_3_DISABLED ((0x08 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
71 #define SUB_REGION_4_DISABLED ((0x10 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
72 #define SUB_REGION_5_DISABLED ((0x20 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
73 #define SUB_REGION_6_DISABLED ((0x40 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
74 #define SUB_REGION_7_DISABLED ((0x80 << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk)
75 
76 #define REGION_SIZE(size) ((ARM_MPU_REGION_SIZE_##size << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk)
77 
78 #define REGION_32B  REGION_SIZE(32B)
79 #define REGION_64B  REGION_SIZE(64B)
80 #define REGION_128B REGION_SIZE(128B)
81 #define REGION_256B REGION_SIZE(256B)
82 #define REGION_512B REGION_SIZE(512B)
83 #define REGION_1K   REGION_SIZE(1KB)
84 #define REGION_2K   REGION_SIZE(2KB)
85 #define REGION_4K   REGION_SIZE(4KB)
86 #define REGION_8K   REGION_SIZE(8KB)
87 #define REGION_16K  REGION_SIZE(16KB)
88 #define REGION_32K  REGION_SIZE(32KB)
89 #define REGION_64K  REGION_SIZE(64KB)
90 #define REGION_128K REGION_SIZE(128KB)
91 #define REGION_256K REGION_SIZE(256KB)
92 #define REGION_512K REGION_SIZE(512KB)
93 #define REGION_1M   REGION_SIZE(1MB)
94 #define REGION_2M   REGION_SIZE(2MB)
95 #define REGION_4M   REGION_SIZE(4MB)
96 #define REGION_8M   REGION_SIZE(8MB)
97 #define REGION_16M  REGION_SIZE(16MB)
98 #define REGION_32M  REGION_SIZE(32MB)
99 #define REGION_64M  REGION_SIZE(64MB)
100 #define REGION_128M REGION_SIZE(128MB)
101 #define REGION_256M REGION_SIZE(256MB)
102 #define REGION_512M REGION_SIZE(512MB)
103 #define REGION_1G   REGION_SIZE(1GB)
104 #define REGION_2G   REGION_SIZE(2GB)
105 #define REGION_4G   REGION_SIZE(4GB)
106 
107 #define ARM_MPU_REGION_INIT(p_name, p_base, p_size, p_attr)                                        \
108 	{                                                                                          \
109 		.name = p_name,                                                                    \
110 		.base = p_base,                                                                    \
111 		.attr = p_attr(size_to_mpu_rasr_size(p_size)),                                     \
112 	}
113 
114 /* Some helper defines for common regions */
115 
116 /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When
117  * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep
118  * the SRAM region XN bit clear or the application code will not be executable.
119  */
120 #define REGION_RAM_ATTR(size)                                                                      \
121 	{(NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE |                        \
122 	  IF_ENABLED(CONFIG_XIP, (MPU_RASR_XN_Msk |)) size | P_RW_U_NA_Msk)}
123 #define REGION_RAM_NOCACHE_ATTR(size)                                                              \
124 	{(NORMAL_OUTER_INNER_NON_CACHEABLE_NON_SHAREABLE | MPU_RASR_XN_Msk | size | P_RW_U_NA_Msk)}
125 #if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
126 #define REGION_FLASH_ATTR(size)                                                                    \
127 	{(NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE | size | P_RW_U_RO_Msk)}
128 #else
129 #define REGION_FLASH_ATTR(size) {(NORMAL_OUTER_INNER_WRITE_THROUGH_NON_SHAREABLE | size | RO_Msk)}
130 #endif
131 #define REGION_PPB_ATTR(size)    {(STRONGLY_ORDERED_SHAREABLE | size | P_RW_U_NA_Msk)}
132 #define REGION_IO_ATTR(size)     {(DEVICE_NON_SHAREABLE | size | P_RW_U_NA_Msk)}
133 #define REGION_EXTMEM_ATTR(size) {(STRONGLY_ORDERED_SHAREABLE | size | NO_ACCESS_Msk)}
134 
135 struct arm_mpu_region_attr {
136 	/* Attributes belonging to RASR (including the encoded region size) */
137 	uint32_t rasr;
138 };
139 
140 typedef struct arm_mpu_region_attr arm_mpu_region_attr_t;
141 
142 /* Typedef for the k_mem_partition attribute */
143 typedef struct {
144 	uint32_t rasr_attr;
145 } k_mem_partition_attr_t;
146 
147 /* Read-Write access permission attributes */
148 #define _K_MEM_PARTITION_P_NA_U_NA (NO_ACCESS_Msk | NOT_EXEC)
149 #define _K_MEM_PARTITION_P_RW_U_RW (P_RW_U_RW_Msk | NOT_EXEC)
150 #define _K_MEM_PARTITION_P_RW_U_RO (P_RW_U_RO_Msk | NOT_EXEC)
151 #define _K_MEM_PARTITION_P_RW_U_NA (P_RW_U_NA_Msk | NOT_EXEC)
152 #define _K_MEM_PARTITION_P_RO_U_RO (P_RO_U_RO_Msk | NOT_EXEC)
153 #define _K_MEM_PARTITION_P_RO_U_NA (P_RO_U_NA_Msk | NOT_EXEC)
154 
155 /* Execution-allowed attributes */
156 #define _K_MEM_PARTITION_P_RWX_U_RWX (P_RW_U_RW_Msk)
157 #define _K_MEM_PARTITION_P_RWX_U_RX  (P_RW_U_RO_Msk)
158 #define _K_MEM_PARTITION_P_RX_U_RX   (P_RO_U_RO_Msk)
159 
160 /* Kernel macros for memory attribution
161  * (access permissions and cache-ability).
162  *
163  * The macros are to be stored in k_mem_partition_attr_t
164  * objects. The format of k_mem_partition_attr_t is an
165  * "1-1" mapping of the ARMv7-M MPU RASR attribute register
166  * fields (excluding the <size> and <enable> bit-fields).
167  */
168 
169 /* Read-Write access permission attributes (default cache-ability) */
170 #define K_MEM_PARTITION_P_NA_U_NA                                                                  \
171 	((k_mem_partition_attr_t){                                                                 \
172 		_K_MEM_PARTITION_P_NA_U_NA |                                                       \
173 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
174 #define K_MEM_PARTITION_P_RW_U_RW                                                                  \
175 	((k_mem_partition_attr_t){                                                                 \
176 		_K_MEM_PARTITION_P_RW_U_RW |                                                       \
177 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
178 #define K_MEM_PARTITION_P_RW_U_RO                                                                  \
179 	((k_mem_partition_attr_t){                                                                 \
180 		_K_MEM_PARTITION_P_RW_U_RO |                                                       \
181 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
182 #define K_MEM_PARTITION_P_RW_U_NA                                                                  \
183 	((k_mem_partition_attr_t){                                                                 \
184 		_K_MEM_PARTITION_P_RW_U_NA |                                                       \
185 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
186 #define K_MEM_PARTITION_P_RO_U_RO                                                                  \
187 	((k_mem_partition_attr_t){                                                                 \
188 		_K_MEM_PARTITION_P_RO_U_RO |                                                       \
189 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
190 #define K_MEM_PARTITION_P_RO_U_NA                                                                  \
191 	((k_mem_partition_attr_t){                                                                 \
192 		_K_MEM_PARTITION_P_RO_U_NA |                                                       \
193 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
194 
195 /* Execution-allowed attributes (default-cacheability) */
196 #define K_MEM_PARTITION_P_RWX_U_RWX                                                                \
197 	((k_mem_partition_attr_t){                                                                 \
198 		_K_MEM_PARTITION_P_RWX_U_RWX |                                                     \
199 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
200 #define K_MEM_PARTITION_P_RWX_U_RX                                                                 \
201 	((k_mem_partition_attr_t){                                                                 \
202 		_K_MEM_PARTITION_P_RWX_U_RX |                                                      \
203 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
204 #define K_MEM_PARTITION_P_RX_U_RX                                                                  \
205 	((k_mem_partition_attr_t){                                                                 \
206 		_K_MEM_PARTITION_P_RX_U_RX |                                                       \
207 		NORMAL_OUTER_INNER_WRITE_BACK_WRITE_READ_ALLOCATE_NON_SHAREABLE})
208 
209 /*
210  * @brief Evaluate Write-ability
211  *
212  * Evaluate whether the access permissions include write-ability.
213  *
214  * @param attr The k_mem_partition_attr_t object holding the
215  *             MPU attributes to be checked against write-ability.
216  */
217 #define K_MEM_PARTITION_IS_WRITABLE(attr)                                                          \
218 	({                                                                                         \
219 		int __is_writable__;                                                               \
220 		switch (attr.rasr_attr & MPU_RASR_AP_Msk) {                                        \
221 		case P_RW_U_RW_Msk:                                                                \
222 		case P_RW_U_RO_Msk:                                                                \
223 		case P_RW_U_NA_Msk:                                                                \
224 			__is_writable__ = 1;                                                       \
225 			break;                                                                     \
226 		default:                                                                           \
227 			__is_writable__ = 0;                                                       \
228 		}                                                                                  \
229 		__is_writable__;                                                                   \
230 	})
231 
232 /*
233  * @brief Evaluate Execution allowance
234  *
235  * Evaluate whether the access permissions include execution.
236  *
237  * @param attr The k_mem_partition_attr_t object holding the
238  *             MPU attributes to be checked against execution
239  *             allowance.
240  */
241 #define K_MEM_PARTITION_IS_EXECUTABLE(attr) (!((attr.rasr_attr) & (NOT_EXEC)))
242 
243 /* Attributes for no-cache enabling (share-ability is selected by default) */
244 
245 #define K_MEM_PARTITION_P_NA_U_NA_NOCACHE                                                          \
246 	((k_mem_partition_attr_t){                                                                 \
247 		(_K_MEM_PARTITION_P_NA_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
248 #define K_MEM_PARTITION_P_RW_U_RW_NOCACHE                                                          \
249 	((k_mem_partition_attr_t){                                                                 \
250 		(_K_MEM_PARTITION_P_RW_U_RW | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
251 #define K_MEM_PARTITION_P_RW_U_RO_NOCACHE                                                          \
252 	((k_mem_partition_attr_t){                                                                 \
253 		(_K_MEM_PARTITION_P_RW_U_RO | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
254 #define K_MEM_PARTITION_P_RW_U_NA_NOCACHE                                                          \
255 	((k_mem_partition_attr_t){                                                                 \
256 		(_K_MEM_PARTITION_P_RW_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
257 #define K_MEM_PARTITION_P_RO_U_RO_NOCACHE                                                          \
258 	((k_mem_partition_attr_t){                                                                 \
259 		(_K_MEM_PARTITION_P_RO_U_RO | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
260 #define K_MEM_PARTITION_P_RO_U_NA_NOCACHE                                                          \
261 	((k_mem_partition_attr_t){                                                                 \
262 		(_K_MEM_PARTITION_P_RO_U_NA | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
263 
264 #define K_MEM_PARTITION_P_RWX_U_RWX_NOCACHE                                                        \
265 	((k_mem_partition_attr_t){                                                                 \
266 		(_K_MEM_PARTITION_P_RWX_U_RWX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
267 #define K_MEM_PARTITION_P_RWX_U_RX_NOCACHE                                                         \
268 	((k_mem_partition_attr_t){                                                                 \
269 		(_K_MEM_PARTITION_P_RWX_U_RX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
270 #define K_MEM_PARTITION_P_RX_U_RX_NOCACHE                                                          \
271 	((k_mem_partition_attr_t){                                                                 \
272 		(_K_MEM_PARTITION_P_RX_U_RX | NORMAL_OUTER_INNER_NON_CACHEABLE_SHAREABLE)})
273 
274 #endif /* _ASMLANGUAGE */
275 
276 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_SIZE(size)                                                 \
277 	BUILD_ASSERT(!(((size) & ((size) - 1))) &&                                                 \
278 		     (size) >= CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE,                           \
279 		     "The size of the partition must be power of 2 and greater than or equal to "  \
280 		     "the minimum MPU region size.\n")
281 
282 /* Some compilers do not handle BUILD_ASSERT on the values of pointers.*/
283 #if defined(__IAR_SYSTEMS_ICC__)
284 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size)
285 #else
286 #define _ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size)                                         \
287 	BUILD_ASSERT(!((uint32_t)(start) & ((size) - 1)),                                          \
288 		     "The start address of the partition must align with size.")
289 #endif
290 
291 #define _ARCH_MEM_PARTITION_ALIGN_CHECK(start, size)                                               \
292 	_ARCH_MEM_PARTITION_ALIGN_CHECK_SIZE(size);                                                \
293 	_ARCH_MEM_PARTITION_ALIGN_CHECK_START(start, size)
294