/* * Copyright (c) 2022, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #ifndef GPT_RME_H #define GPT_RME_H #include #include /******************************************************************************/ /* 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) #define GPT_NSE_SECURE U(0b00) #define GPT_NSE_ROOT U(0b01) #define GPT_NSE_NS U(0b10) #define GPT_NSE_REALM U(0b11) #define GPT_NSE_SHIFT U(62) /* 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 originating SMC invoking the API. * * Return * Negative Linux error code in the event of a failure, 0 for success. */ int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); #endif /* GPT_RME_H */