xref: /rk3399_ARM-atf/include/lib/xlat_tables/xlat_tables_v2_helpers.h (revision 60e8f3cfd5910c59c9a573ce05bd61091336b09a)
1 /*
2  * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /*
8  * This header file contains internal definitions that are not supposed to be
9  * used outside of this library code.
10  */
11 
12 #ifndef XLAT_TABLES_V2_HELPERS_H
13 #define XLAT_TABLES_V2_HELPERS_H
14 
15 #ifndef XLAT_TABLES_V2_H
16 #error "Do not include this header file directly. Include xlat_tables_v2.h instead."
17 #endif
18 
19 #ifndef __ASSEMBLER__
20 
21 #include <stdbool.h>
22 #include <stddef.h>
23 
24 #include <platform_def.h>
25 
26 #include <lib/cassert.h>
27 #include <lib/xlat_tables/xlat_tables_arch.h>
28 #include <lib/xlat_tables/xlat_tables_defs.h>
29 
30 /* Forward declaration */
31 struct mmap_region;
32 
33 /*
34  * Helper macro to define an mmap_region_t.  This macro allows to specify all
35  * the fields of the structure but its parameter list is not guaranteed to
36  * remain stable as we add members to mmap_region_t.
37  */
38 #define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr)		\
39 	{							\
40 		.base_pa = (_pa),				\
41 		.base_va = (_va),				\
42 		.size = (_sz),					\
43 		.attr = (_attr),				\
44 		.granularity = (_gr),				\
45 	}
46 
47 /* Struct that holds all information about the translation tables. */
48 struct xlat_ctx {
49 	/*
50 	 * Max allowed Virtual and Physical Addresses.
51 	 */
52 	unsigned long long pa_max_address;
53 	uintptr_t va_max_address;
54 
55 	/*
56 	 * Array of all memory regions stored in order of ascending end address
57 	 * and ascending size to simplify the code that allows overlapping
58 	 * regions. The list is terminated by the first entry with size == 0.
59 	 * The max size of the list is stored in `mmap_num`. `mmap` points to an
60 	 * array of mmap_num + 1 elements, so that there is space for the final
61 	 * null entry.
62 	 */
63 	struct mmap_region *mmap;
64 	int mmap_num;
65 
66 	/*
67 	 * Array of finer-grain translation tables.
68 	 * For example, if the initial lookup level is 1 then this array would
69 	 * contain both level-2 and level-3 entries.
70 	 */
71 	uint64_t (*tables)[XLAT_TABLE_ENTRIES];
72 	int tables_num;
73 #if PLAT_RO_XLAT_TABLES
74 	bool readonly_tables;
75 #endif
76 	/*
77 	 * Keep track of how many regions are mapped in each table. The base
78 	 * table can't be unmapped so it isn't needed to keep track of it.
79 	 */
80 #if PLAT_XLAT_TABLES_DYNAMIC
81 	int *tables_mapped_regions;
82 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
83 
84 	int next_table;
85 
86 	/*
87 	 * Base translation table. It doesn't need to have the same amount of
88 	 * entries as the ones used for other levels.
89 	 */
90 	uint64_t *base_table;
91 	unsigned int base_table_entries;
92 
93 	/*
94 	* Max Physical and Virtual addresses currently in use by the
95 	* translation tables. These might get updated as we map/unmap memory
96 	* regions but they will never go beyond pa/va_max_address.
97 	*/
98 	unsigned long long max_pa;
99 	uintptr_t max_va;
100 
101 	/* Level of the base translation table. */
102 	unsigned int base_level;
103 
104 	/* Set to true when the translation tables are initialized. */
105 	bool initialized;
106 
107 	/*
108 	 * Translation regime managed by this xlat_ctx_t. It should be one of
109 	 * the EL*_REGIME defines.
110 	 */
111 	int xlat_regime;
112 };
113 
114 #if PLAT_XLAT_TABLES_DYNAMIC
115 #define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
116 	static int _ctx_name##_mapped_regions[_xlat_tables_count];
117 
118 #define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)				\
119 	.tables_mapped_regions = _ctx_name##_mapped_regions,
120 #else
121 #define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
122 	/* do nothing */
123 
124 #define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)				\
125 	/* do nothing */
126 #endif /* PLAT_XLAT_TABLES_DYNAMIC */
127 
128 #if PLAT_RO_XLAT_TABLES
129 #define XLAT_CTX_INIT_TABLE_ATTR()					\
130 	.readonly_tables = false,
131 #else
132 #define XLAT_CTX_INIT_TABLE_ATTR()
133 	/* do nothing */
134 #endif
135 
136 #define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count,		\
137 			_xlat_tables_count, _virt_addr_space_size,	\
138 			_phy_addr_space_size, _xlat_regime, _section_name)\
139 	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
140 		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
141 									\
142 	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];		\
143 									\
144 	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
145 		[XLAT_TABLE_ENTRIES]					\
146 		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
147 									\
148 	static uint64_t _ctx_name##_base_xlat_table			\
149 		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
150 		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
151 			* sizeof(uint64_t));				\
152 									\
153 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
154 									\
155 	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
156 		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
157 		.va_max_address = (_virt_addr_space_size) - 1UL,	\
158 		.mmap = _ctx_name##_mmap,				\
159 		.mmap_num = (_mmap_count),				\
160 		.tables = _ctx_name##_xlat_tables,			\
161 		.tables_num = _xlat_tables_count,			\
162 		 XLAT_CTX_INIT_TABLE_ATTR()				\
163 		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
164 		.next_table = 0,					\
165 		.base_table = _ctx_name##_base_xlat_table,		\
166 		.base_table_entries =					\
167 			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
168 		.max_pa = 0U,						\
169 		.max_va = 0U,						\
170 		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
171 		.initialized = false,					\
172 		.xlat_regime = (_xlat_regime)				\
173 	}
174 
175 #define REGISTER_XLAT_CONTEXT_RO_BASE_TABLE(_ctx_name, _mmap_count,	\
176 			_xlat_tables_count, _virt_addr_space_size,	\
177 			_phy_addr_space_size, _xlat_regime, _section_name)\
178 	CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size),	\
179 		assert_invalid_physical_addr_space_sizefor_##_ctx_name);\
180 									\
181 	static mmap_region_t _ctx_name##_mmap[_mmap_count + 1];		\
182 									\
183 	static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count]	\
184 		[XLAT_TABLE_ENTRIES]					\
185 		__aligned(XLAT_TABLE_SIZE) __section(_section_name);	\
186 									\
187 	static uint64_t _ctx_name##_base_xlat_table			\
188 		[GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)]	\
189 		__aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\
190 			* sizeof(uint64_t))				\
191 		__section(".rodata");					\
192 									\
193 	XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count)		\
194 									\
195 	static xlat_ctx_t _ctx_name##_xlat_ctx = {			\
196 		.pa_max_address = (_phy_addr_space_size) - 1ULL,	\
197 		.va_max_address = (_virt_addr_space_size) - 1UL,	\
198 		.mmap = _ctx_name##_mmap,				\
199 		.mmap_num = (_mmap_count),				\
200 		.tables = _ctx_name##_xlat_tables,			\
201 		.tables_num = _xlat_tables_count,			\
202 		 XLAT_CTX_INIT_TABLE_ATTR()				\
203 		 XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name)			\
204 		.next_table = 0,					\
205 		.base_table = _ctx_name##_base_xlat_table,		\
206 		.base_table_entries =					\
207 			GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
208 		.max_pa = 0U,						\
209 		.max_va = 0U,						\
210 		.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\
211 		.initialized = false,					\
212 		.xlat_regime = (_xlat_regime)				\
213 	}
214 
215 #endif /*__ASSEMBLER__*/
216 
217 #endif /* XLAT_TABLES_V2_HELPERS_H */
218