1 /*
2  * Copyright (c) 2018 Linaro Limited.
3  * Copyright (c) 2018 Nordic Semiconductor ASA.
4  * Copyright (c) 2021-2023 Arm Limited (or its affiliates). All rights reserved.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_CORTEX_R_MPU_ARM_MPU_H_
9 #define ZEPHYR_INCLUDE_ARCH_ARM64_CORTEX_R_MPU_ARM_MPU_H_
10 
11 /*
12  * Convenience macros to represent the ARMv8-R64-specific configuration
13  * for memory access permission and cache-ability attribution.
14  */
15 /* MPU MPUIR Register Definitions */
16 #define MPU_IR_REGION_Msk	(0xFFU)
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		4U
21 #define MPU_RBAR_SH_Msk		(0x3UL << MPU_RBAR_SH_Pos)
22 #define MPU_RBAR_AP_Pos		2U
23 #define MPU_RBAR_AP_Msk		(0x3UL << MPU_RBAR_AP_Pos)
24 /* RBAR_EL1 XN */
25 #define MPU_RBAR_XN_Pos		1U
26 #define MPU_RBAR_XN_Msk		(0x1UL << MPU_RBAR_XN_Pos)
27 
28 /* MPU PLBAR_ELx 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 
35 /* PRBAR_ELx: Attribute flag for not-allowing execution (eXecute Never) */
36 #define NOT_EXEC	MPU_RBAR_XN_Msk /* PRBAR_EL1 */
37 
38 /* PRBAR_ELx: Attribute flag for access permissions */
39 /* Privileged Read Write, Unprivileged No Access */
40 #define P_RW_U_NA	0x0U
41 #define P_RW_U_NA_Msk	((P_RW_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
42 /* Privileged Read Write, Unprivileged Read Write */
43 #define P_RW_U_RW	0x1U
44 #define P_RW_U_RW_Msk	((P_RW_U_RW << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
45 /* Privileged Read Only, Unprivileged No Access */
46 #define P_RO_U_NA	0x2U
47 #define P_RO_U_NA_Msk	((P_RO_U_NA << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
48 /* Privileged Read Only, Unprivileged Read Only */
49 #define P_RO_U_RO	0x3U
50 #define P_RO_U_RO_Msk	((P_RO_U_RO << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk)
51 
52 /* PRBAR_ELx: Attribute flags for share-ability */
53 #define NON_SHAREABLE	0x0U
54 #define NON_SHAREABLE_Msk	\
55 	((NON_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
56 #define OUTER_SHAREABLE 0x2U
57 #define OUTER_SHAREABLE_Msk	\
58 	((OUTER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
59 #define INNER_SHAREABLE 0x3U
60 #define INNER_SHAREABLE_Msk	\
61 	((INNER_SHAREABLE << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk)
62 
63 /* MPIR_ELx Attribute flags for cache-ability */
64 
65 /* Memory Attributes for Device Memory
66  * 1.Gathering (G/nG)
67  *   Determines whether multiple accesses can be merged into a single
68  *   bus transaction.
69  *   nG: Number/size of accesses on the bus = number/size of accesses
70  *   in code.
71  *
72  * 2.Reordering (R/nR)
73  *   Determines whether accesses to the same device can be reordered.
74  *   nR: Accesses to the same IMPLEMENTATION DEFINED block size will
75  *   appear on the bus in program order.
76  *
77  * 3 Early Write Acknowledgment (E/nE)
78  *   Indicates to the memory system whether a buffer can send
79  *   acknowledgements.
80  *   nE: The response should come from the end slave, not buffering in
81  *   the interconnect.
82  */
83 #define DEVICE_nGnRnE	0x0U
84 #define DEVICE_nGnRE	0x4U
85 #define DEVICE_nGRE	0x8U
86 #define DEVICE_GRE	0xCU
87 
88 /* Read/Write Allocation Configurations for Cacheable Memory */
89 #define R_NON_W_NON	0x0U	/* Do not allocate Read/Write */
90 #define R_NON_W_ALLOC	0x1U	/* Do not allocate Read, Allocate Write */
91 #define R_ALLOC_W_NON	0x2U	/* Allocate Read, Do not allocate Write */
92 #define R_ALLOC_W_ALLOC 0x3U	/* Allocate Read/Write */
93 
94 /* Memory Attributes for Normal Memory */
95 #define NORMAL_O_WT_NT	0x80U	/* Normal, Outer Write-through non-transient */
96 #define NORMAL_O_WB_NT	0xC0U	/* Normal, Outer Write-back non-transient */
97 #define NORMAL_O_NON_C	0x40U	/* Normal, Outer Non-Cacheable	*/
98 
99 #define NORMAL_I_WT_NT	0x08U	/* Normal, Inner Write-through non-transient */
100 #define NORMAL_I_WB_NT	0x0CU	/* Normal, Inner Write-back non-transient */
101 #define NORMAL_I_NON_C	0x04U	/* Normal, Inner Non-Cacheable	*/
102 
103 /* Global MAIR configurations */
104 #define MPU_MAIR_INDEX_DEVICE		0U
105 #define MPU_MAIR_ATTR_DEVICE		(DEVICE_nGnRnE)
106 
107 #define MPU_MAIR_INDEX_FLASH		1U
108 #define MPU_MAIR_ATTR_FLASH				\
109 	((NORMAL_O_WT_NT | (R_ALLOC_W_NON << 4)) |	\
110 	 (NORMAL_I_WT_NT | R_ALLOC_W_NON))
111 
112 #define MPU_MAIR_INDEX_SRAM		2U
113 #define MPU_MAIR_ATTR_SRAM				\
114 	((NORMAL_O_WB_NT | (R_ALLOC_W_ALLOC << 4)) |	\
115 	 (NORMAL_I_WB_NT | R_ALLOC_W_ALLOC))
116 
117 #define MPU_MAIR_INDEX_SRAM_NOCACHE	3U
118 #define MPU_MAIR_ATTR_SRAM_NOCACHE			\
119 	((NORMAL_O_NON_C | (R_NON_W_NON << 4)) |	\
120 	 (NORMAL_I_NON_C | R_NON_W_NON))
121 
122 #define MPU_MAIR_ATTRS						 \
123 	((MPU_MAIR_ATTR_DEVICE << (MPU_MAIR_INDEX_DEVICE * 8)) | \
124 	 (MPU_MAIR_ATTR_FLASH << (MPU_MAIR_INDEX_FLASH * 8)) |	 \
125 	 (MPU_MAIR_ATTR_SRAM << (MPU_MAIR_INDEX_SRAM * 8)) |	 \
126 	 (MPU_MAIR_ATTR_SRAM_NOCACHE << (MPU_MAIR_INDEX_SRAM_NOCACHE * 8)))
127 
128 /* Some helper defines for common regions.
129  *
130  * Note that the ARMv8-R MPU architecture requires that the
131  * enabled MPU regions are non-overlapping. Therefore, it is
132  * recommended to use these helper defines only for configuring
133  * fixed MPU regions at build-time.
134  */
135 #define REGION_IO_ATTR						      \
136 	{							      \
137 		/* AP, XN, SH */				      \
138 		.rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \
139 		/* Cache-ability */				      \
140 		.mair_idx = MPU_MAIR_INDEX_DEVICE,		      \
141 	}
142 
143 #define REGION_RAM_ATTR							\
144 	{								\
145 		/* AP, XN, SH */					\
146 		.rbar = NOT_EXEC | P_RW_U_NA_Msk | OUTER_SHAREABLE_Msk, \
147 		/* Cache-ability */					\
148 		.mair_idx = MPU_MAIR_INDEX_SRAM,			\
149 	}
150 
151 #define REGION_RAM_NOCACHE_ATTR					      \
152 	{							      \
153 		/* AP, XN, SH */				      \
154 		.rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \
155 		/* Cache-ability */				      \
156 		.mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE,	      \
157 	}
158 
159 #define REGION_RAM_TEXT_ATTR					\
160 	{							\
161 		/* AP, XN, SH */				\
162 		.rbar = P_RO_U_RO_Msk | INNER_SHAREABLE_Msk,	\
163 		/* Cache-ability */				\
164 		.mair_idx = MPU_MAIR_INDEX_SRAM,		\
165 	}
166 
167 #define REGION_RAM_RO_ATTR						\
168 	{								\
169 		/* AP, XN, SH */					\
170 		.rbar = NOT_EXEC | P_RO_U_RO_Msk | INNER_SHAREABLE_Msk, \
171 		/* Cache-ability */					\
172 		.mair_idx = MPU_MAIR_INDEX_SRAM,			\
173 	}
174 
175 #if defined(CONFIG_MPU_ALLOW_FLASH_WRITE)
176 /* Note that the access permissions allow for un-privileged writes
177  */
178 #define REGION_FLASH_ATTR						    \
179 	{								    \
180 		.rbar = P_RW_U_RW_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
181 		/* Cache-ability */					    \
182 		.mair_idx = MPU_MAIR_INDEX_FLASH,			    \
183 	}
184 #else /* CONFIG_MPU_ALLOW_FLASH_WRITE */
185 #define REGION_FLASH_ATTR						    \
186 	{								    \
187 		.rbar = P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \
188 		/* Cache-ability */					    \
189 		.mair_idx = MPU_MAIR_INDEX_FLASH,			    \
190 	}
191 #endif /* CONFIG_MPU_ALLOW_FLASH_WRITE */
192 
193 #ifndef _ASMLANGUAGE
194 
195 struct arm_mpu_region_attr {
196 	/* Attributes belonging to PRBAR */
197 	uint8_t rbar : 6;
198 	/* MAIR index for attribute indirection */
199 	uint8_t mair_idx : 3;
200 };
201 
202 /* Region definition data structure */
203 struct arm_mpu_region {
204 	/* Region Base Address */
205 	uint64_t base;
206 	/* Region limit Address */
207 	uint64_t limit;
208 	/* Region Name */
209 	const char *name;
210 	/* Region Attributes */
211 	struct arm_mpu_region_attr attr;
212 };
213 
214 /* MPU configuration data structure */
215 struct arm_mpu_config {
216 	/* Number of regions */
217 	uint32_t num_regions;
218 	/* Regions */
219 	const struct arm_mpu_region *mpu_regions;
220 };
221 
222 #define MPU_REGION_ENTRY(_name, _base, _limit, _attr) \
223 	{					      \
224 		.name = _name,			      \
225 		.base = _base,			      \
226 		.limit = _limit,		      \
227 		.attr = _attr,			      \
228 	}
229 
230 #define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \
231 	{(P_RW_U_RW_Msk), MPU_MAIR_INDEX_SRAM})
232 #define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \
233 	{(P_RW_U_NA_Msk), MPU_MAIR_INDEX_SRAM})
234 #define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \
235 	{(P_RO_U_RO_Msk), MPU_MAIR_INDEX_SRAM})
236 #define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \
237 	{(P_RO_U_NA_Msk), MPU_MAIR_INDEX_SRAM})
238 
239 typedef struct arm_mpu_region_attr k_mem_partition_attr_t;
240 
241 /* Reference to the MPU configuration.
242  *
243  * This struct is defined and populated for each SoC (in the SoC definition),
244  * and holds the build-time configuration information for the fixed MPU
245  * regions enabled during kernel initialization. Dynamic MPU regions (e.g.
246  * for Thread Stack, Stack Guards, etc.) are programmed during runtime, thus,
247  * not kept here.
248  */
249 extern const struct arm_mpu_config mpu_config;
250 
251 struct dynamic_region_info {
252 	int index;
253 	struct arm_mpu_region region_conf;
254 };
255 
256 #define ARM64_MPU_MAX_DYNAMIC_REGIONS						\
257 	1 + /* data section */							\
258 	(CONFIG_MAX_DOMAIN_PARTITIONS + 2) +					\
259 	(IS_ENABLED(CONFIG_ARM64_STACK_PROTECTION) ? 2 : 0) +			\
260 	(IS_ENABLED(CONFIG_USERSPACE) ? 2 : 0)
261 
262 #endif	/* _ASMLANGUAGE */
263 
264 #endif	/* ZEPHYR_INCLUDE_ARCH_ARM64_CORTEX_R_MPU_ARM_MPU_H_ */
265