1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  * SPDX-FileCopyrightText: Copyright Arm Limited and Contributors.
5  */
6 
7 /* This file is derived from xlat_table_v2 library in TF-A project */
8 
9 #ifndef XLAT_CONTEXTS_H
10 #define XLAT_CONTEXTS_H
11 
12 #ifndef __ASSEMBLER__
13 
14 #include <assert.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <utils_def.h>
18 #include <xlat_defs.h>
19 
20 /* Forward declaration */
21 struct xlat_mmap_region;
22 
23 /* Enumerator to identify the right address space within a context */
24 typedef enum xlat_addr_region_id {
25 	VA_LOW_REGION = 0,
26 	VA_HIGH_REGION,
27 	VA_REGIONS
28 } xlat_addr_region_id_t;
29 
30 /*
31  * Structure to hold all the xlat tables and related information within a
32  * context. This allows to reuse the same xlat_ctx_cfg part of the context
33  * on several PEs that share the same memory map region whilst keeping
34  * private tables for each PE.
35  */
36 struct xlat_ctx_tbls {
37 	/*
38 	 * Array of finer-grain translation tables.
39 	 * For example, if the initial lookup level is 1 then this array would
40 	 * contain both level-2 and level-3 entries.
41 	 */
42 	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
43 	unsigned int tables_num;
44 	unsigned int next_table;
45 
46 	/*
47 	 * Base translation table.
48 	 * It has the same number of entries as the ones used for other levels
49 	 * although it is possible that not all the entries are used.
50 	 *
51 	 * If, as an example, the translation tables for the current context
52 	 * start at L1, then the *tables field will contain the L2 and L3
53 	 * tables.
54 	 */
55 	uint64_t *base_table;
56 	unsigned int max_base_table_entries;
57 
58 	/* Set to true when the translation tables are initialized. */
59 	bool initialized;
60 };
61 
62 /* Struct that holds the context configuration */
63 struct xlat_ctx_cfg {
64 	/*
65 	 * Maximum size allowed for the VA space handled by the context.
66 	 */
67 	uintptr_t max_va_size;
68 
69 	/*
70 	 * Array of all memory regions stored in order of ascending base_va.
71 	 * The list is terminated by the first entry with
72 	 * size == 0 or when all entries are used (as specified by mmap_num).
73 	 */
74 	struct xlat_mmap_region *mmap;
75 	unsigned int mmap_num;
76 
77 	/*
78 	 * Base address for the virtual space on this context.
79 	 */
80 	uintptr_t base_va;
81 
82 	/*
83 	 * Max Physical and Virtual addresses currently in use by the
84 	 * current context. These will get updated as we map memory
85 	 * regions but it will never go beyond the maximum physical address
86 	 * or max_va_size respectively.
87 	 *
88 	 * max_mapped_pa is an absolute Physical Address.
89 	 */
90 	uintptr_t max_mapped_pa;
91 	uintptr_t max_mapped_va_offset;
92 
93 	/* Level of the base translation table. */
94 	unsigned int base_level;
95 
96 	/*
97 	 * Virtual address region handled by this context.
98 	 */
99 	xlat_addr_region_id_t region;
100 
101 	bool initialized;
102 };
103 
104 /*
105  * Struct that holds the context itself, composed of
106  * a pointer to the context config and a pointer to the
107  * translation tables associated to it.
108  */
109 struct xlat_ctx {
110 	struct xlat_ctx_cfg *cfg;
111 	struct xlat_ctx_tbls *tbls;
112 };
113 
114 /*
115  * The translation tables are aligned to their size. For 4KB graularity, this
116  * is aligned to 4KB as well.
117  */
118 #define XLAT_TABLES_ALIGNMENT		XLAT_TABLE_SIZE
119 
120 /*
121  * Align the base tables to page boundary. This migh generate larger tables
122  * than needed, but it simplifies the code, which is a good trade-off
123  * since we have enough memory.
124  */
125 #define BASE_XLAT_TABLES_ALIGNMENT	XLAT_TABLE_SIZE
126 
127 /*
128  * Compute the number of entries required at the initial lookup level to
129  * address the whole virtual address space.
130  */
131 #define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size)			\
132 	((addr_space_size) >>						\
133 		XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size)))
134 
135 /*
136  * Macro to check if the xlat_ctx_cfg part of a context is valid.
137  */
138 #define XLAT_TABLES_CTX_CFG_VALID(_ctx)	((_ctx)->cfg != NULL)
139 
140 /*
141  * Macro to check if the xlat_ctx_tbls part of a context is valid.
142  */
143 #define XLAT_TABLES_CTX_TBL_VALID(_ctx)		((_ctx)->tbls != NULL)
144 
145 /*
146  * Macro to allocate translation tables to be used within a context.
147  */
148 #define XLAT_CREATE_TABLES(_tblset_name,				\
149 			   _xlat_tables_count,				\
150 			   _virt_addr_space_size,			\
151 			   _tables_section)				\
152 									\
153 	static uint64_t _tblset_name##_base_xlat_table			\
154 		[(XLAT_TABLE_ENTRIES)]					\
155 		__aligned((BASE_XLAT_TABLES_ALIGNMENT))			\
156 		__section((_tables_section));				\
157 									\
158 	static uint64_t _tblset_name##_xlat_tables[(_xlat_tables_count)]\
159 		[(XLAT_TABLE_ENTRIES)]					\
160 		__aligned((XLAT_TABLES_ALIGNMENT))			\
161 		__section((_tables_section));				\
162 									\
163 	static struct xlat_ctx_tbls _tblset_name##_tbls = {		\
164 		.tables = _tblset_name##_xlat_tables,			\
165 		.tables_num = (_xlat_tables_count),			\
166 		.next_table = 0,					\
167 		.base_table = _tblset_name##_base_xlat_table,		\
168 		.max_base_table_entries =				\
169 			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
170 		.initialized = false					\
171 	}								\
172 
173 /*
174  * Macro used to define the xlat_ctx_cfg and xlat_mmap_region array
175  * associated with a context.
176  */
177 #define XLAT_REGISTER_VA_SPACE(_ctx_name, _region, _mmap_count,		\
178 			_virt_addr_space_size)				\
179 	COMPILER_ASSERT(((_region) < VA_REGIONS));			\
180 	COMPILER_ASSERT(((unsigned long)(_virt_addr_space_size)		\
181 					% GRANULE_SIZE) == UL(0));	\
182 	COMPILER_ASSERT((unsigned long)(_virt_addr_space_size)		\
183 					<= (MAX_VIRT_ADDR_SPACE_SIZE));	\
184 									\
185 	static struct xlat_mmap_region _ctx_name##_mmap[(_mmap_count)];	\
186 									\
187 	static struct xlat_ctx_cfg _ctx_name##_xlat_ctx_cfg = {		\
188 		.max_va_size = (_virt_addr_space_size),			\
189 		.base_va = 0ULL,					\
190 		.mmap = _ctx_name##_mmap,				\
191 		.mmap_num = (_mmap_count),				\
192 		.max_mapped_va_offset = 0ULL,				\
193 		.max_mapped_pa = 0ULL,					\
194 		.base_level =						\
195 			(GET_XLAT_TABLE_LEVEL_BASE((_virt_addr_space_size))),\
196 		.region = (_region),					\
197 		.initialized = false					\
198 	}
199 
200 /*
201  * Macro to generate a context and associate the translation table set passed
202  * to it by ref.
203  */
204 #define XLAT_REGISTER_CONTEXT_FULL_SPEC(_ctx_name, _region, _mmap_count,\
205 			_virt_addr_space_size,				\
206 			_tables_set)					\
207 	XLAT_REGISTER_VA_SPACE(_ctx_name, (_region),			\
208 			       (_mmap_count), (_virt_addr_space_size));	\
209 									\
210 	static struct xlat_ctx _ctx_name##_xlat_ctx = {			\
211 		.cfg = &(_ctx_name##_xlat_ctx_cfg),			\
212 		.tbls = (_tables_set)					\
213 	}
214 
215 /*
216  * Statically allocate a translation context and associated translation
217  * tables. Also initialize them.
218  *
219  * _ctx_name:
220  *   Prefix for the translation context variable.
221  *   E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'.
222  *   Useful to distinguish multiple contexts from one another.
223  *
224  * _region:
225  *   Region mapped by this context (high or low address region).
226  *   See @xlat_ctx_region_id_t for more info.
227  *
228  * _mmap_count:
229  *   Number ofstruct xlat_mmap_region to allocate.
230  *   Would be defined during the context creation.
231  *
232  * _xlat_tables_count:
233  *   Number of non-base tables to allocate at level others than the
234  *   initial lookup.
235  *
236  * _virt_addr_space_size:
237  *   Size (in bytes) of the virtual address space that can be accessed by this
238  *   context.
239  *
240  * _section_name:
241  *   Specify the name of the section where the translation tables have to be
242  *   placed by the linker.
243  */
244 #define XLAT_REGISTER_CONTEXT(_ctx_name, _region, _mmap_count,		\
245 			      _xlat_tables_count,			\
246 			      _virt_addr_space_size,			\
247 			      _section_name)				\
248 		XLAT_CREATE_TABLES(_ctx_name, (_xlat_tables_count),	\
249 				   (_virt_addr_space_size),		\
250 				   (_section_name));			\
251 									\
252 		XLAT_REGISTER_CONTEXT_FULL_SPEC(_ctx_name, (_region),	\
253 						(_mmap_count),		\
254 						(_virt_addr_space_size),\
255 						&(_ctx_name##_tbls))
256 
257 #endif /*__ASSEMBLER__*/
258 
259 #endif /* XLAT_CONTEXTS_H */
260