Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame] | 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 */ |