blob: f0f6c0966170ff284fcc3dd6e6e54b0618b3d6d4 [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
* SPDX-FileCopyrightText: Copyright Arm Limited and Contributors.
*/
/* This file is derived from xlat_table_v2 library in TF-A project */
#ifndef XLAT_CONTEXTS_H
#define XLAT_CONTEXTS_H
#ifndef __ASSEMBLER__
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <utils_def.h>
#include <xlat_defs.h>
/* Forward declaration */
struct xlat_mmap_region;
/* Enumerator to identify the right address space within a context */
typedef enum xlat_addr_region_id {
VA_LOW_REGION = 0,
VA_HIGH_REGION,
VA_REGIONS
} xlat_addr_region_id_t;
/*
* Structure to hold all the xlat tables and related information within a
* context. This allows to reuse the same xlat_ctx_cfg part of the context
* on several PEs that share the same memory map region whilst keeping
* private tables for each PE.
*/
struct xlat_ctx_tbls {
/*
* Array of finer-grain translation tables.
* For example, if the initial lookup level is 1 then this array would
* contain both level-2 and level-3 entries.
*/
uint64_t (*tables)[XLAT_TABLE_ENTRIES];
unsigned int tables_num;
unsigned int next_table;
/*
* Base translation table.
* It has the same number of entries as the ones used for other levels
* although it is possible that not all the entries are used.
*
* If, as an example, the translation tables for the current context
* start at L1, then the *tables field will contain the L2 and L3
* tables.
*/
uint64_t *base_table;
unsigned int max_base_table_entries;
/* Set to true when the translation tables are initialized. */
bool initialized;
};
/* Struct that holds the context configuration */
struct xlat_ctx_cfg {
/*
* Maximum size allowed for the VA space handled by the context.
*/
uintptr_t max_va_size;
/*
* Array of all memory regions stored in order of ascending base_va.
* The list is terminated by the first entry with
* size == 0 or when all entries are used (as specified by mmap_num).
*/
struct xlat_mmap_region *mmap;
unsigned int mmap_num;
/*
* Base address for the virtual space on this context.
*/
uintptr_t base_va;
/*
* Max Physical and Virtual addresses currently in use by the
* current context. These will get updated as we map memory
* regions but it will never go beyond the maximum physical address
* or max_va_size respectively.
*
* max_mapped_pa is an absolute Physical Address.
*/
uintptr_t max_mapped_pa;
uintptr_t max_mapped_va_offset;
/* Level of the base translation table. */
unsigned int base_level;
/*
* Virtual address region handled by this context.
*/
xlat_addr_region_id_t region;
bool initialized;
};
/*
* Struct that holds the context itself, composed of
* a pointer to the context config and a pointer to the
* translation tables associated to it.
*/
struct xlat_ctx {
struct xlat_ctx_cfg *cfg;
struct xlat_ctx_tbls *tbls;
};
/*
* The translation tables are aligned to their size. For 4KB graularity, this
* is aligned to 4KB as well.
*/
#define XLAT_TABLES_ALIGNMENT XLAT_TABLE_SIZE
/*
* Align the base tables to page boundary. This migh generate larger tables
* than needed, but it simplifies the code, which is a good trade-off
* since we have enough memory.
*/
#define BASE_XLAT_TABLES_ALIGNMENT XLAT_TABLE_SIZE
/*
* Compute the number of entries required at the initial lookup level to
* address the whole virtual address space.
*/
#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size) \
((addr_space_size) >> \
XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size)))
/*
* Macro to check if the xlat_ctx_cfg part of a context is valid.
*/
#define XLAT_TABLES_CTX_CFG_VALID(_ctx) ((_ctx)->cfg != NULL)
/*
* Macro to check if the xlat_ctx_tbls part of a context is valid.
*/
#define XLAT_TABLES_CTX_TBL_VALID(_ctx) ((_ctx)->tbls != NULL)
/*
* Macro to allocate translation tables to be used within a context.
*/
#define XLAT_CREATE_TABLES(_tblset_name, \
_xlat_tables_count, \
_virt_addr_space_size, \
_tables_section) \
\
static uint64_t _tblset_name##_base_xlat_table \
[(XLAT_TABLE_ENTRIES)] \
__aligned((BASE_XLAT_TABLES_ALIGNMENT)) \
__section((_tables_section)); \
\
static uint64_t _tblset_name##_xlat_tables[(_xlat_tables_count)]\
[(XLAT_TABLE_ENTRIES)] \
__aligned((XLAT_TABLES_ALIGNMENT)) \
__section((_tables_section)); \
\
static struct xlat_ctx_tbls _tblset_name##_tbls = { \
.tables = _tblset_name##_xlat_tables, \
.tables_num = (_xlat_tables_count), \
.next_table = 0, \
.base_table = _tblset_name##_base_xlat_table, \
.max_base_table_entries = \
GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size),\
.initialized = false \
} \
/*
* Macro used to define the xlat_ctx_cfg and xlat_mmap_region array
* associated with a context.
*/
#define XLAT_REGISTER_VA_SPACE(_ctx_name, _region, _mmap_count, \
_virt_addr_space_size) \
COMPILER_ASSERT(((_region) < VA_REGIONS)); \
COMPILER_ASSERT(((unsigned long)(_virt_addr_space_size) \
% GRANULE_SIZE) == UL(0)); \
COMPILER_ASSERT((unsigned long)(_virt_addr_space_size) \
<= (MAX_VIRT_ADDR_SPACE_SIZE)); \
\
static struct xlat_mmap_region _ctx_name##_mmap[(_mmap_count)]; \
\
static struct xlat_ctx_cfg _ctx_name##_xlat_ctx_cfg = { \
.max_va_size = (_virt_addr_space_size), \
.base_va = 0ULL, \
.mmap = _ctx_name##_mmap, \
.mmap_num = (_mmap_count), \
.max_mapped_va_offset = 0ULL, \
.max_mapped_pa = 0ULL, \
.base_level = \
(GET_XLAT_TABLE_LEVEL_BASE((_virt_addr_space_size))),\
.region = (_region), \
.initialized = false \
}
/*
* Macro to generate a context and associate the translation table set passed
* to it by ref.
*/
#define XLAT_REGISTER_CONTEXT_FULL_SPEC(_ctx_name, _region, _mmap_count,\
_virt_addr_space_size, \
_tables_set) \
XLAT_REGISTER_VA_SPACE(_ctx_name, (_region), \
(_mmap_count), (_virt_addr_space_size)); \
\
static struct xlat_ctx _ctx_name##_xlat_ctx = { \
.cfg = &(_ctx_name##_xlat_ctx_cfg), \
.tbls = (_tables_set) \
}
/*
* Statically allocate a translation context and associated translation
* tables. Also initialize them.
*
* _ctx_name:
* Prefix for the translation context variable.
* E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'.
* Useful to distinguish multiple contexts from one another.
*
* _region:
* Region mapped by this context (high or low address region).
* See @xlat_ctx_region_id_t for more info.
*
* _mmap_count:
* Number ofstruct xlat_mmap_region to allocate.
* Would be defined during the context creation.
*
* _xlat_tables_count:
* Number of non-base tables to allocate at level others than the
* initial lookup.
*
* _virt_addr_space_size:
* Size (in bytes) of the virtual address space that can be accessed by this
* context.
*
* _section_name:
* Specify the name of the section where the translation tables have to be
* placed by the linker.
*/
#define XLAT_REGISTER_CONTEXT(_ctx_name, _region, _mmap_count, \
_xlat_tables_count, \
_virt_addr_space_size, \
_section_name) \
XLAT_CREATE_TABLES(_ctx_name, (_xlat_tables_count), \
(_virt_addr_space_size), \
(_section_name)); \
\
XLAT_REGISTER_CONTEXT_FULL_SPEC(_ctx_name, (_region), \
(_mmap_count), \
(_virt_addr_space_size),\
&(_ctx_name##_tbls))
#endif /*__ASSEMBLER__*/
#endif /* XLAT_CONTEXTS_H */