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