blob: f0f6c0966170ff284fcc3dd6e6e54b0618b3d6d4 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
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 */
21struct xlat_mmap_region;
22
23/* Enumerator to identify the right address space within a context */
24typedef 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 */
36struct 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 */
63struct 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 */
109struct 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 */