Home | History | Annotate | Download | only in xlat_tables
      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