diff options
author | johpow01 <john.powell@arm.com> | 2021-06-16 17:57:28 -0500 |
---|---|---|
committer | johpow01 <john.powell@arm.com> | 2021-10-05 16:24:57 -0500 |
commit | f19dc624a17c9df6aa444e33568b1f70ff4e9341 (patch) | |
tree | 971ffe9a2948af46edf4ee3ff3fceaf0a50f9d87 /include/lib | |
parent | 07e96d1d2958b6f121476fd391ac67bf8c2c4735 (diff) | |
download | arm-trusted-firmware-f19dc624a17c9df6aa444e33568b1f70ff4e9341.tar.gz |
refactor(gpt): productize and refactor GPT library
This patch updates and refactors the GPT library and fixes bugs.
- Support all combinations of PGS, PPS, and L0GPTSZ parameters.
- PPS and PGS are set at runtime, L0GPTSZ is read from GPCCR_EL3.
- Use compiler definitions to simplify code.
- Renaming functions to better suit intended uses.
- MMU enabled before GPT APIs called.
- Add comments to make function usage more clear in GPT library.
- Added _rme suffix to file names to differentiate better from the
GPT file system code.
- Renamed gpt_defs.h to gpt_rme_private.h to better separate private
and public code.
- Renamed gpt_core.c to gpt_rme.c to better conform to TF-A precedent.
Signed-off-by: John Powell <john.powell@arm.com>
Change-Id: I4cbb23b0f81e697baa9fb23ba458aa3f7d1ed919
Diffstat (limited to 'include/lib')
-rw-r--r-- | include/lib/gpt/gpt.h | 86 | ||||
-rw-r--r-- | include/lib/gpt/gpt_defs.h | 76 | ||||
-rw-r--r-- | include/lib/gpt_rme/gpt_rme.h | 276 |
3 files changed, 276 insertions, 162 deletions
diff --git a/include/lib/gpt/gpt.h b/include/lib/gpt/gpt.h deleted file mode 100644 index 89d30177d..000000000 --- a/include/lib/gpt/gpt.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef GPT_H -#define GPT_H - -#include <stdint.h> - -#include <arch.h> - -#include "gpt_defs.h" - -#define GPT_DESC_ATTRS(_type, _gpi) \ - ((((_type) & PAS_REG_DESC_TYPE_MASK) \ - << PAS_REG_DESC_TYPE_SHIFT) | \ - (((_gpi) & PAS_REG_GPI_MASK) \ - << PAS_REG_GPI_SHIFT)) - -/* - * Macro to create a GPT entry for this PAS range either as a L0 block - * descriptor or L1 table descriptor depending upon the size of the range. - */ -#define MAP_GPT_REGION(_pa, _sz, _gpi) \ - { \ - .base_pa = (_pa), \ - .size = (_sz), \ - .attrs = GPT_DESC_ATTRS(PAS_REG_DESC_TYPE_ANY, (_gpi)), \ - } - -/* - * Special macro to create a L1 table descriptor at L0 for a 1GB region as - * opposed to creating a block mapping by default. - */ -#define MAP_GPT_REGION_TBL(_pa, _sz, _gpi) \ - { \ - .base_pa = (_pa), \ - .size = (_sz), \ - .attrs = GPT_DESC_ATTRS(PAS_REG_DESC_TYPE_TBL, (_gpi)), \ - } - -/* - * Structure for specifying a Granule range and its properties - */ -typedef struct pas_region { - unsigned long long base_pa; /**< Base address for PAS. */ - size_t size; /**< Size of the PAS. */ - unsigned int attrs; /**< PAS GPI and entry type. */ -} pas_region_t; - -/* - * Structure to initialise the Granule Protection Tables. - */ -typedef struct gpt_init_params { - unsigned int pgs; /**< Address Width of Phisical Granule Size. */ - unsigned int pps; /**< Protected Physical Address Size. */ - unsigned int l0gptsz; /**< Granule size on L0 table entry. */ - pas_region_t *pas_regions; /**< PAS regions to protect. */ - unsigned int pas_count; /**< Number of PAS regions to initialise. */ - uintptr_t l0_mem_base; /**< L0 Table base address. */ - size_t l0_mem_size; /**< Size of memory reserved for L0 tables. */ - uintptr_t l1_mem_base; /**< L1 Table base address. */ - size_t l1_mem_size; /**< Size of memory reserved for L1 tables. */ -} gpt_init_params_t; - -/** @brief Initialise the Granule Protection tables. - */ -int gpt_init(gpt_init_params_t *params); - -/** @brief Enable the Granule Protection Checks. - */ -void gpt_enable(void); - -/** @brief Disable the Granule Protection Checks. - */ -void gpt_disable(void); - -/** @brief Transition a granule between security states. - */ -int gpt_transition_pas(uint64_t pa, - unsigned int src_sec_state, - unsigned int target_pas); - -#endif /* GPT_H */ diff --git a/include/lib/gpt/gpt_defs.h b/include/lib/gpt/gpt_defs.h deleted file mode 100644 index 6122a126f..000000000 --- a/include/lib/gpt/gpt_defs.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2021, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef GPT_DEFS_H -#define GPT_DEFS_H - -#include <arch.h> -#include <lib/utils_def.h> - -#include "gpt.h" - -/* GPI values */ -#define GPI_NO_ACCESS U(0x0) -#define GPI_SECURE U(0x8) -#define GPI_NS U(0x9) -#define GPI_ROOT U(0xa) -#define GPI_REALM U(0xb) -#define GPI_ANY U(0xf) -#define GPI_VAL_MASK ULL(0xf) - -/* GPT descriptor bit definitions */ -#define GPT_L1_INDEX_MASK ULL(0xf) -#define GPT_L1_INDEX_SHIFT ULL(0x0) - -#define GPT_TBL_DESC ULL(0x3) -#define GPT_BLK_DESC ULL(0x1) - -#define GPT_TBL_DESC_ADDR_SHIFT ULL(12) -#define GPT_TBL_DESC_ADDR_MASK (((ULL(1) << \ - (51 - GPT_TBL_DESC_ADDR_SHIFT)) - 1) \ - << GPT_TBL_DESC_ADDR_SHIFT) - -#define GPT_BLOCK_DESC_GPI_VAL_SHIFT ULL(4) - -/* Each descriptor is 8 bytes long. */ -#define GPT_DESC_SIZE ULL(8) - -#define PPS_MAX_VAL PSTCR_EL3_PPS_4PB -#define PPS_NUM_1GB_ENTRIES ULL(1024) -#define PGS_4K_1GB_L1_TABLE_SZ (U(2) << 17) - -/* 2 << LOG2_8K = Bytes in 8K */ -#define LOG2_8K U(13) - -#define GPT_L1_SIZE ULL(0x40000) /* 256K */ -#define SZ_1G (ULL(0x1) << 30) /* 1GB */ - -#define GPT_MIN_PGS_SHIFT U(12) /* 4K */ - -#define L1_GPT_INDEX_MASK U(0x3fffffff) -#define GPT_GRAN_DESC_NUM_GPIS U(4) - -#define PAS_REG_GPI_SHIFT U(0) -#define PAS_REG_GPI_MASK U(0xf) - -/* .attrs field definitions */ -#define PAS_REG_DESC_TYPE_ANY U(0) -#define PAS_REG_DESC_TYPE_BLK U(1) -#define PAS_REG_DESC_TYPE_TBL U(2) -#define PAS_REG_DESC_TYPE_SHIFT U(4) -#define PAS_REG_DESC_TYPE_MASK U(0x3) -#define PAS_REG_DESC_TYPE(_attrs) (((_attrs) \ - >> PAS_REG_DESC_TYPE_SHIFT) \ - & PAS_REG_DESC_TYPE_MASK) - -#define PAS_REG_GPI(_attrs) (((_attrs) \ - >> PAS_REG_GPI_SHIFT) \ - & PAS_REG_GPI_MASK) - -#define SZ_1G_MASK (SZ_1G - U(1)) -#define IS_1GB_ALIGNED(addr) (((addr) & SZ_1G_MASK) == U(0)) - -#endif /* GPT_DEFS */ diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h new file mode 100644 index 000000000..379b91562 --- /dev/null +++ b/include/lib/gpt_rme/gpt_rme.h @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_RME_H +#define GPT_RME_H + +#include <stdint.h> + +#include <arch.h> + +/******************************************************************************/ +/* GPT helper macros and definitions */ +/******************************************************************************/ + +/* + * Structure for specifying a mapping range and it's properties. This should not + * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as + * to avoid potential incompatibilities in the future. + */ +typedef struct pas_region { + uintptr_t base_pa; /* Base address for PAS. */ + size_t size; /* Size of the PAS. */ + unsigned int attrs; /* PAS GPI and entry type. */ +} pas_region_t; + +/* GPT GPI definitions */ +#define GPT_GPI_NO_ACCESS U(0x0) +#define GPT_GPI_SECURE U(0x8) +#define GPT_GPI_NS U(0x9) +#define GPT_GPI_ROOT U(0xA) +#define GPT_GPI_REALM U(0xB) +#define GPT_GPI_ANY U(0xF) +#define GPT_GPI_VAL_MASK UL(0xF) + +/* PAS attribute GPI definitions. */ +#define GPT_PAS_ATTR_GPI_SHIFT U(0) +#define GPT_PAS_ATTR_GPI_MASK U(0xF) +#define GPT_PAS_ATTR_GPI(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_GPI_SHIFT) \ + & GPT_PAS_ATTR_GPI_MASK) + +/* PAS attribute mapping type definitions */ +#define GPT_PAS_ATTR_MAP_TYPE_BLOCK U(0x0) +#define GPT_PAS_ATTR_MAP_TYPE_GRANULE U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE_SHIFT U(4) +#define GPT_PAS_ATTR_MAP_TYPE_MASK U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_MAP_TYPE_SHIFT) \ + & GPT_PAS_ATTR_MAP_TYPE_MASK) + +/* + * Macro to initialize the attributes field in the pas_region_t structure. + * [31:5] Reserved + * [4] Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions) + * [3:0] PAS GPI type (GPT_GPI_x definitions) + */ +#define GPT_PAS_ATTR(_type, _gpi) \ + ((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK) \ + << GPT_PAS_ATTR_MAP_TYPE_SHIFT) | \ + (((_gpi) & GPT_PAS_ATTR_GPI_MASK) \ + << GPT_PAS_ATTR_GPI_SHIFT)) + +/* + * Macro to create a GPT entry for this PAS range as a block descriptor. If this + * region does not fit the requirements for a block descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \ + } + +/* + * Macro to create a GPT entry for this PAS range as a table descriptor. If this + * region does not fit the requirements for a table descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \ + } + +/******************************************************************************/ +/* GPT register field definitions */ +/******************************************************************************/ + +/* + * Least significant address bits protected by each entry in level 0 GPT. This + * field is read-only. + */ +#define GPCCR_L0GPTSZ_SHIFT U(20) +#define GPCCR_L0GPTSZ_MASK U(0xF) + +typedef enum { + GPCCR_L0GPTSZ_30BITS = U(0x0), + GPCCR_L0GPTSZ_34BITS = U(0x4), + GPCCR_L0GPTSZ_36BITS = U(0x6), + GPCCR_L0GPTSZ_39BITS = U(0x9) +} gpccr_l0gptsz_e; + +/* Granule protection check priority bit definitions */ +#define GPCCR_GPCP_SHIFT U(17) +#define GPCCR_GPCP_BIT (ULL(1) << GPCCR_EL3_GPCP_SHIFT) + +/* Granule protection check bit definitions */ +#define GPCCR_GPC_SHIFT U(16) +#define GPCCR_GPC_BIT (ULL(1) << GPCCR_GPC_SHIFT) + +/* Physical granule size bit definitions */ +#define GPCCR_PGS_SHIFT U(14) +#define GPCCR_PGS_MASK U(0x3) +#define SET_GPCCR_PGS(x) (((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT) + +typedef enum { + GPCCR_PGS_4K = U(0x0), + GPCCR_PGS_64K = U(0x1), + GPCCR_PGS_16K = U(0x2) +} gpccr_pgs_e; + +/* GPT fetch shareability attribute bit definitions */ +#define GPCCR_SH_SHIFT U(12) +#define GPCCR_SH_MASK U(0x3) +#define SET_GPCCR_SH(x) (((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT) + +typedef enum { + GPCCR_SH_NS = U(0x0), + GPCCR_SH_OS = U(0x2), + GPCCR_SH_IS = U(0x3) +} gpccr_sh_e; + +/* GPT fetch outer cacheability attribute bit definitions */ +#define GPCCR_ORGN_SHIFT U(10) +#define GPCCR_ORGN_MASK U(0x3) +#define SET_GPCCR_ORGN(x) (((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT) + +typedef enum { + GPCCR_ORGN_NC = U(0x0), + GPCCR_ORGN_WB_RA_WA = U(0x1), + GPCCR_ORGN_WT_RA_NWA = U(0x2), + GPCCR_ORGN_WB_RA_NWA = U(0x3) +} gpccr_orgn_e; + +/* GPT fetch inner cacheability attribute bit definitions */ +#define GPCCR_IRGN_SHIFT U(8) +#define GPCCR_IRGN_MASK U(0x3) +#define SET_GPCCR_IRGN(x) (((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT) + +typedef enum { + GPCCR_IRGN_NC = U(0x0), + GPCCR_IRGN_WB_RA_WA = U(0x1), + GPCCR_IRGN_WT_RA_NWA = U(0x2), + GPCCR_IRGN_WB_RA_NWA = U(0x3) +} gpccr_irgn_e; + +/* Protected physical address size bit definitions */ +#define GPCCR_PPS_SHIFT U(0) +#define GPCCR_PPS_MASK U(0x7) +#define SET_GPCCR_PPS(x) (((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT) + +typedef enum { + GPCCR_PPS_4GB = U(0x0), + GPCCR_PPS_64GB = U(0x1), + GPCCR_PPS_1TB = U(0x2), + GPCCR_PPS_4TB = U(0x3), + GPCCR_PPS_16TB = U(0x4), + GPCCR_PPS_256TB = U(0x5), + GPCCR_PPS_4PB = U(0x6) +} gpccr_pps_e; + +/* Base Address for the GPT bit definitions */ +#define GPTBR_BADDR_SHIFT U(0) +#define GPTBR_BADDR_VAL_SHIFT U(12) +#define GPTBR_BADDR_MASK ULL(0xffffffffff) + +/******************************************************************************/ +/* GPT public APIs */ +/******************************************************************************/ + +/* + * Public API that initializes the entire protected space to GPT_GPI_ANY using + * the L0 tables (block descriptors). Ideally, this function is invoked prior + * to DDR discovery and initialization. The MMU must be initialized before + * calling this function. + * + * Parameters + * pps PPS value to use for table generation + * l0_mem_base Base address of L0 tables in memory. + * l0_mem_size Total size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_l0_tables(gpccr_pps_e pps, + uintptr_t l0_mem_base, + size_t l0_mem_size); + +/* + * Public API that carves out PAS regions from the L0 tables and builds any L1 + * tables that are needed. This function ideally is run after DDR discovery and + * initialization. The L0 tables must have already been initialized to GPI_ANY + * when this function is called. + * + * Parameters + * pgs PGS value to use for table generation. + * l1_mem_base Base address of memory used for L1 tables. + * l1_mem_size Total size of memory available for L1 tables. + * *pas_regions Pointer to PAS regions structure array. + * pas_count Total number of PAS regions. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, + uintptr_t l1_mem_base, + size_t l1_mem_size, + pas_region_t *pas_regions, + unsigned int pas_count); + +/* + * Public API to initialize the runtime gpt_config structure based on the values + * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization + * typically happens in a bootloader stage prior to setting up the EL3 runtime + * environment for the granule transition service so this function detects the + * initialization from a previous stage. Granule protection checks must be + * enabled already or this function will return an error. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_runtime_init(void); + +/* + * Public API to enable granule protection checks once the tables have all been + * initialized. This function is called at first initialization and then again + * later during warm boots of CPU cores. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_enable(void); + +/* + * Public API to disable granule protection checks. + */ +void gpt_disable(void); + +/* + * This function is the core of the granule transition service. When a granule + * transition request occurs it is routed to this function where the request is + * validated then fulfilled if possible. + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base: Base address of the region to transition, must be aligned to granule + * size. + * size: Size of region to transition, must be aligned to granule size. + * src_sec_state: Security state of the caller. + * target_pas: Target PAS of the specified memory region. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_transition_pas(uint64_t base, + size_t size, + unsigned int src_sec_state, + unsigned int target_pas); + +#endif /* GPT_RME_H */ |