1 /* 2 * Copyright (c) 2017, 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 __ASSEMBLY__ 20 21 #include <cassert.h> 22 #include <platform_def.h> 23 #include <stddef.h> 24 #include <xlat_tables_arch.h> 25 #include <xlat_tables_defs.h> 26 27 /* Forward declaration */ 28 struct mmap_region; 29 30 /* 31 * Helper macro to define an mmap_region_t. This macro allows to specify all 32 * the fields of the structure but its parameter list is not guaranteed to 33 * remain stable as we add members to mmap_region_t. 34 */ 35 #define _MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \ 36 { \ 37 .base_pa = (_pa), \ 38 .base_va = (_va), \ 39 .size = (_sz), \ 40 .attr = (_attr), \ 41 .granularity = (_gr), \ 42 } 43 44 /* Struct that holds all information about the translation tables. */ 45 struct xlat_ctx { 46 /* 47 * Max allowed Virtual and Physical Addresses. 48 */ 49 unsigned long long pa_max_address; 50 uintptr_t va_max_address; 51 52 /* 53 * Array of all memory regions stored in order of ascending end address 54 * and ascending size to simplify the code that allows overlapping 55 * regions. The list is terminated by the first entry with size == 0. 56 * The max size of the list is stored in `mmap_num`. `mmap` points to an 57 * array of mmap_num + 1 elements, so that there is space for the final 58 * null entry. 59 */ 60 struct mmap_region *mmap; 61 unsigned int mmap_num; 62 63 /* 64 * Array of finer-grain translation tables. 65 * For example, if the initial lookup level is 1 then this array would 66 * contain both level-2 and level-3 entries. 67 */ 68 uint64_t (*tables)[XLAT_TABLE_ENTRIES]; 69 unsigned int tables_num; 70 /* 71 * Keep track of how many regions are mapped in each table. The base 72 * table can't be unmapped so it isn't needed to keep track of it. 73 */ 74 #if PLAT_XLAT_TABLES_DYNAMIC 75 int *tables_mapped_regions; 76 #endif /* PLAT_XLAT_TABLES_DYNAMIC */ 77 78 unsigned int next_table; 79 80 /* 81 * Base translation table. It doesn't need to have the same amount of 82 * entries as the ones used for other levels. 83 */ 84 uint64_t *base_table; 85 unsigned int base_table_entries; 86 87 /* 88 * Max Physical and Virtual addresses currently in use by the 89 * translation tables. These might get updated as we map/unmap memory 90 * regions but they will never go beyond pa/va_max_address. 91 */ 92 unsigned long long max_pa; 93 uintptr_t max_va; 94 95 /* Level of the base translation table. */ 96 unsigned int base_level; 97 98 /* Set to 1 when the translation tables are initialized. */ 99 unsigned int initialized; 100 101 /* 102 * Translation regime managed by this xlat_ctx_t. It takes the values of 103 * the enumeration xlat_regime_t. The type is "int" to avoid a circular 104 * dependency on xlat_tables_v2.h, but this member must be treated as 105 * xlat_regime_t. 106 */ 107 int xlat_regime; 108 }; 109 110 #if PLAT_XLAT_TABLES_DYNAMIC 111 #define _ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ 112 static int _ctx_name##_mapped_regions[_xlat_tables_count]; 113 114 #define _REGISTER_DYNMAP_STRUCT(_ctx_name) \ 115 .tables_mapped_regions = _ctx_name##_mapped_regions, 116 #else 117 #define _ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ 118 /* do nothing */ 119 120 #define _REGISTER_DYNMAP_STRUCT(_ctx_name) \ 121 /* do nothing */ 122 #endif /* PLAT_XLAT_TABLES_DYNAMIC */ 123 124 #define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count, \ 125 _virt_addr_space_size, _phy_addr_space_size, \ 126 _xlat_regime) \ 127 CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \ 128 assert_invalid_virtual_addr_space_size_for_##_ctx_name); \ 129 \ 130 CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \ 131 assert_invalid_physical_addr_space_sizefor_##_ctx_name); \ 132 \ 133 static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ 134 \ 135 static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ 136 [XLAT_TABLE_ENTRIES] \ 137 __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); \ 138 \ 139 static uint64_t _ctx_name##_base_xlat_table \ 140 [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ 141 __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size) \ 142 * sizeof(uint64_t)); \ 143 \ 144 _ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ 145 \ 146 static xlat_ctx_t _ctx_name##_xlat_ctx = { \ 147 .va_max_address = (_virt_addr_space_size) - 1, \ 148 .pa_max_address = (_phy_addr_space_size) - 1, \ 149 .mmap = _ctx_name##_mmap, \ 150 .mmap_num = _mmap_count, \ 151 .base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size), \ 152 .base_table = _ctx_name##_base_xlat_table, \ 153 .base_table_entries = \ 154 GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size), \ 155 .tables = _ctx_name##_xlat_tables, \ 156 .tables_num = _xlat_tables_count, \ 157 _REGISTER_DYNMAP_STRUCT(_ctx_name) \ 158 .xlat_regime = (_xlat_regime), \ 159 .max_pa = 0, \ 160 .max_va = 0, \ 161 .next_table = 0, \ 162 .initialized = 0, \ 163 } 164 165 #if AARCH64 166 167 /* 168 * This IMAGE_EL macro must not to be used outside the library, and it is only 169 * used in AArch64. 170 */ 171 #if defined(IMAGE_BL1) || defined(IMAGE_BL31) 172 # define IMAGE_EL 3 173 # define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME 174 #else 175 # define IMAGE_EL 1 176 # define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME 177 #endif 178 179 #else /* if AARCH32 */ 180 181 /* 182 * The PL1&0 translation regime in AArch32 behaves like the EL1&0 regime in 183 * AArch64 except for the XN bits, but we set and unset them at the same time, 184 * so there's no difference in practice. 185 */ 186 #define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME 187 188 #endif /* AARCH64 */ 189 190 #endif /*__ASSEMBLY__*/ 191 192 #endif /* __XLAT_TABLES_V2_HELPERS_H__ */ 193