1 /*
2  * Copyright 2019 Broadcom
3  * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #ifndef ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_
8 #define ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_
9 
10 #ifndef _ASMLANGUAGE
11 #include <stdint.h>
12 #include <stdlib.h>
13 #endif
14 
15 /* Following Memory types supported through MAIR encodings can be passed
16  * by user through "attrs"(attributes) field of specified memory region.
17  * As MAIR supports such 8 encodings, we will reserve attrs[2:0];
18  * so that we can provide encodings upto 7 if needed in future.
19  */
20 #define MT_TYPE_MASK		0x7U
21 #define MT_TYPE(attr)		(attr & MT_TYPE_MASK)
22 #define MT_DEVICE_nGnRnE	0U
23 #define MT_DEVICE_nGnRE		1U
24 #define MT_DEVICE_GRE		2U
25 #define MT_NORMAL_NC		3U
26 #define MT_NORMAL		4U
27 #define MT_NORMAL_WT		5U
28 
29 #define MEMORY_ATTRIBUTES	((0x00 << (MT_DEVICE_nGnRnE * 8)) |	\
30 				(0x04 << (MT_DEVICE_nGnRE * 8))   |	\
31 				(0x0c << (MT_DEVICE_GRE * 8))     |	\
32 				(0x44 << (MT_NORMAL_NC * 8))      |	\
33 				(0xffUL << (MT_NORMAL * 8))	  |	\
34 				(0xbbUL << (MT_NORMAL_WT * 8)))
35 
36 /* More flags from user's perspective are supported using remaining bits
37  * of "attrs" field, i.e. attrs[31:3], underlying code will take care
38  * of setting PTE fields correctly.
39  *
40  * current usage of attrs[31:3] is:
41  * attrs[3] : Access Permissions
42  * attrs[4] : Memory access from secure/ns state
43  * attrs[5] : Execute Permissions privileged mode (PXN)
44  * attrs[6] : Execute Permissions unprivileged mode (UXN)
45  * attrs[7] : Mirror RO/RW permissions to EL0
46  * attrs[8] : Overwrite existing mapping if any
47  * attrs[9] : non-Global mapping (nG)
48  * attrs[10]: Paged-out mapping
49  *
50  */
51 #define MT_PERM_SHIFT		3U
52 #define MT_SEC_SHIFT		4U
53 #define MT_P_EXECUTE_SHIFT	5U
54 #define MT_U_EXECUTE_SHIFT	6U
55 #define MT_RW_AP_SHIFT		7U
56 #define MT_NO_OVERWRITE_SHIFT	8U
57 #define MT_NON_GLOBAL_SHIFT	9U
58 #define MT_PAGED_OUT_SHIFT	10U
59 
60 #define MT_RO			(0U << MT_PERM_SHIFT)
61 #define MT_RW			(1U << MT_PERM_SHIFT)
62 
63 #define MT_RW_AP_ELx		(1U << MT_RW_AP_SHIFT)
64 #define MT_RW_AP_EL_HIGHER	(0U << MT_RW_AP_SHIFT)
65 
66 #define MT_SECURE		(0U << MT_SEC_SHIFT)
67 #define MT_NS			(1U << MT_SEC_SHIFT)
68 
69 #define MT_P_EXECUTE		(0U << MT_P_EXECUTE_SHIFT)
70 #define MT_P_EXECUTE_NEVER	(1U << MT_P_EXECUTE_SHIFT)
71 
72 #define MT_U_EXECUTE		(0U << MT_U_EXECUTE_SHIFT)
73 #define MT_U_EXECUTE_NEVER	(1U << MT_U_EXECUTE_SHIFT)
74 
75 #define MT_NO_OVERWRITE		(1U << MT_NO_OVERWRITE_SHIFT)
76 
77 #define MT_G			(0U << MT_NON_GLOBAL_SHIFT)
78 #define MT_NG			(1U << MT_NON_GLOBAL_SHIFT)
79 
80 #define MT_PAGED_OUT		(1U << MT_PAGED_OUT_SHIFT)
81 
82 #define MT_P_RW_U_RW		(MT_RW | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER)
83 #define MT_P_RW_U_NA		(MT_RW | MT_RW_AP_EL_HIGHER  | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER)
84 #define MT_P_RO_U_RO		(MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER)
85 #define MT_P_RO_U_NA		(MT_RO | MT_RW_AP_EL_HIGHER  | MT_P_EXECUTE_NEVER | MT_U_EXECUTE_NEVER)
86 #define MT_P_RO_U_RX		(MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE_NEVER | MT_U_EXECUTE)
87 #define MT_P_RX_U_RX		(MT_RO | MT_RW_AP_ELx | MT_P_EXECUTE | MT_U_EXECUTE)
88 #define MT_P_RX_U_NA		(MT_RO | MT_RW_AP_EL_HIGHER  | MT_P_EXECUTE | MT_U_EXECUTE_NEVER)
89 
90 #ifdef CONFIG_ARMV8_A_NS
91 #define MT_DEFAULT_SECURE_STATE	MT_NS
92 #else
93 #define MT_DEFAULT_SECURE_STATE	MT_SECURE
94 #endif
95 
96 /* Definitions used by arch_page_info_get() */
97 #define ARCH_DATA_PAGE_LOADED		BIT(0)
98 #define ARCH_DATA_PAGE_ACCESSED		BIT(1)
99 #define ARCH_DATA_PAGE_DIRTY		BIT(2)
100 #define ARCH_DATA_PAGE_NOT_MAPPED	BIT(3)
101 
102 /*
103  * Special unpaged "location" tags (highest possible descriptor physical
104  * address values unlikely to conflict with backing store locations)
105  */
106 #define ARCH_UNPAGED_ANON_ZERO		0x0000fffffffff000
107 #define ARCH_UNPAGED_ANON_UNINIT	0x0000ffffffffe000
108 
109 #ifndef _ASMLANGUAGE
110 
111 /* Region definition data structure */
112 struct arm_mmu_region {
113 	/* Region Base Physical Address */
114 	uintptr_t base_pa;
115 	/* Region Base Virtual Address */
116 	uintptr_t base_va;
117 	/* Region size */
118 	size_t size;
119 	/* Region Name */
120 	const char *name;
121 	/* Region Attributes */
122 	uint32_t attrs;
123 };
124 
125 /* MMU configuration data structure */
126 struct arm_mmu_config {
127 	/* Number of regions */
128 	unsigned int num_regions;
129 	/* Regions */
130 	const struct arm_mmu_region *mmu_regions;
131 };
132 
133 struct arm_mmu_ptables {
134 	uint64_t *base_xlat_table;
135 	uint64_t ttbr0;
136 };
137 
138 /* Convenience macros to represent the ARMv8-A-specific
139  * configuration for memory access permission and
140  * cache-ability attribution.
141  */
142 
143 #define MMU_REGION_ENTRY(_name, _base_pa, _base_va, _size, _attrs) \
144 	{\
145 		.name = _name, \
146 		.base_pa = _base_pa, \
147 		.base_va = _base_va, \
148 		.size = _size, \
149 		.attrs = _attrs, \
150 	}
151 
152 #define MMU_REGION_FLAT_ENTRY(name, adr, sz, attrs) \
153 	MMU_REGION_ENTRY(name, adr, adr, sz, attrs)
154 
155 /*
156  * @brief Auto generate mmu region entry for node_id
157  *
158  * Example usage:
159  *
160  * @code{.c}
161  *      DT_FOREACH_STATUS_OKAY_VARGS(nxp_imx_gpio,
162  *				  MMU_REGION_DT_FLAT_ENTRY,
163  *				 (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS))
164  * @endcode
165  *
166  * @note  Since devicetree_generated.h does not include
167  *        node_id##_P_reg_FOREACH_PROP_ELEM* definitions,
168  *        we can't automate dts node with multiple reg
169  *        entries.
170  */
171 #define MMU_REGION_DT_FLAT_ENTRY(node_id, attrs)  \
172 	MMU_REGION_FLAT_ENTRY(DT_NODE_FULL_NAME(node_id), \
173 				  DT_REG_ADDR(node_id), \
174 				  DT_REG_SIZE(node_id), \
175 				  attrs),
176 
177 /*
178  * @brief Auto generate mmu region entry for status = "okay"
179  *        nodes compatible to a driver
180  *
181  * Example usage:
182  *
183  * @code{.c}
184  *      MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(nxp_imx_gpio,
185  *				 (MT_DEVICE_nGnRnE | MT_P_RW_U_NA | MT_NS))
186  * @endcode
187  *
188  * @note  This is a wrapper of @ref MMU_REGION_DT_FLAT_ENTRY
189  */
190 #define MMU_REGION_DT_COMPAT_FOREACH_FLAT_ENTRY(compat, attr) \
191 	DT_FOREACH_STATUS_OKAY_VARGS(compat, \
192 	MMU_REGION_DT_FLAT_ENTRY, attr)
193 
194 /* Kernel macros for memory attribution
195  * (access permissions and cache-ability).
196  *
197  * The macros are to be stored in k_mem_partition_attr_t
198  * objects. The format of a k_mem_partition_attr_t object
199  * is an uint32_t composed by permission and attribute flags
200  * located in include/arch/arm64/arm_mmu.h
201  */
202 
203 /* Read-Write access permission attributes */
204 #define K_MEM_PARTITION_P_RW_U_RW ((k_mem_partition_attr_t) \
205 			{MT_P_RW_U_RW})
206 #define K_MEM_PARTITION_P_RW_U_NA ((k_mem_partition_attr_t) \
207 			{MT_P_RW_U_NA})
208 #define K_MEM_PARTITION_P_RO_U_RO ((k_mem_partition_attr_t) \
209 			{MT_P_RO_U_RO})
210 #define K_MEM_PARTITION_P_RO_U_NA ((k_mem_partition_attr_t) \
211 			{MT_P_RO_U_NA})
212 /* Execution-allowed attributes */
213 #define K_MEM_PARTITION_P_RX_U_RX ((k_mem_partition_attr_t) \
214 			{MT_P_RX_U_RX})
215 /* Typedef for the k_mem_partition attribute */
216 typedef struct { uint32_t attrs; } k_mem_partition_attr_t;
217 
218 /* Reference to the MMU configuration.
219  *
220  * This struct is defined and populated for each SoC (in the SoC definition),
221  * and holds the build-time configuration information for the fixed MMU
222  * regions enabled during kernel initialization.
223  */
224 extern const struct arm_mmu_config mmu_config;
225 
226 #endif /* _ASMLANGUAGE */
227 
228 #endif /* ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MMU_H_ */
229