From b0f1c84035fb25e331b21f08f3f3e8e643c3394d Mon Sep 17 00:00:00 2001 From: AlexeiFedorov Date: Fri, 24 Jan 2025 15:53:50 +0000 Subject: [PATCH] feat(gpt): statically allocate bitlocks array Statically allocate 'gpt_bitlock' array of fine-grained 'bitlock_t' data structures in arm_bl31_setup.c. The amount of memory needed for this array is controlled by 'RME_GPT_BITLOCK_BLOCK' build option and 'PLAT_ARM_PPS' macro defined in platform_def.h which specifies the size of protected physical address space in bytes. 'PLAT_ARM_PPS' takes values from 4GB to 4PB supported by Arm architecture. Change-Id: Icf620b5039e45df6828d58fca089cad83b0bc669 Signed-off-by: AlexeiFedorov --- .../granule-protection-tables-design.rst | 36 +++-- include/lib/gpt_rme/gpt_rme.h | 19 ++- lib/gpt_rme/gpt_rme.c | 152 ++++++++---------- lib/gpt_rme/gpt_rme.mk | 15 +- lib/gpt_rme/gpt_rme_private.h | 8 +- plat/arm/board/fvp/include/platform_def.h | 2 +- plat/arm/common/arm_bl31_setup.c | 24 ++- 7 files changed, 138 insertions(+), 118 deletions(-) diff --git a/docs/components/granule-protection-tables-design.rst b/docs/components/granule-protection-tables-design.rst index 78d2f12aa..91673c6fd 100644 --- a/docs/components/granule-protection-tables-design.rst +++ b/docs/components/granule-protection-tables-design.rst @@ -124,10 +124,7 @@ Level 0 and Level 1 Tables The GPT initialization APIs require memory to be passed in for the tables to be constructed. The ``gpt_init_l0_tables`` API takes a memory address and size for -building the level 0 tables and also memory for allocating the fine-grained bitlock -data structure. The amount of memory needed for bitlock structure is controlled via -``RME_GPT_BITLOCK_BLOCK`` config which defines the block size for each bit of the -the bitlock. +building the level 0 tables. The ``gpt_init_pas_l1_tables`` API takes an address and size for building the level 1 tables which are linked from level 0 descriptors. The @@ -156,7 +153,7 @@ Locking Scheme During Granule Transition access to L1 tables is controlled by a lock to ensure that no more than one CPU is allowed to make changes at any given time. The granularity of the lock is defined by ``RME_GPT_BITLOCK_BLOCK`` build option -which defines the size of the memory block protected by one bit of ``bitlock`` +which defines the size of the memory block protected by one bit of ``bitlock_t`` structure. Setting this option to 0 chooses a single spinlock for all GPT L1 table entries. @@ -185,6 +182,10 @@ process. #. In systems that make use of the granule transition service, runtime firmware must call ``gpt_runtime_init`` to set up the data structures needed by the GTSI to find the tables and transition granules between PAS types. + The base address of bitlocks array and its size are provided to this function + as arguments. These parameters are not used in case of a single spinlock for + all GPT L1 table entries(``RME_GPT_BITLOCK_BLOCK`` is 0) and are passed as zero + values. API Constraints ~~~~~~~~~~~~~~~ @@ -225,9 +226,6 @@ The L0 table memory has some constraints that must be taken into account. is greater. L0 table size is the total protected space (PPS) divided by the size of each L0 region (L0GPTSZ) multiplied by the size of each L0 descriptor (8 bytes). ((PPS / L0GPTSZ) * 8) -* The L0 memory size must be greater than the table size and have enough space - to allocate array of ``bitlock`` structures at the end of L0 table if - required (``RME_GPT_BITLOCK_BLOCK`` is not 0). * The L0 memory must fall within a PAS of type GPT_GPI_ROOT. The L1 memory also has some constraints. @@ -237,6 +235,10 @@ The L1 memory also has some constraints. the granules controlled in each byte (2). ((L0GPTSZ / PGS) / 2) * There must be enough L1 memory supplied to build all requested L1 tables. * The L1 memory must fall within a PAS of type GPT_GPI_ROOT. +* The platform allocates the bitlock array which contains fine-grained + ``bitlock_t`` data structures. The RME GPT library will check that the array + has at least the amount of memory defined by PPS and ``RME_GPT_BITLOCK_BLOCK`` + value. If an invalid combination of parameters is supplied, the APIs will print an error message and return a negative value. The return values of APIs should be @@ -245,7 +247,7 @@ checked to ensure successful configuration. Sample Calculation for L0 memory size and alignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Let PPS=GPCCR_PPS_4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS +Let PPS=4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS We can find the total L0 table size with ((PPS / L0GPTSZ) * 8) @@ -254,19 +256,19 @@ Substitute values to get this: ((0x100000000 / 0x40000000) * 8) And solve to get 32 bytes. In this case, 4096 is greater than 32, so the L0 tables must be aligned to 4096 bytes. -Sample calculation for bitlock array size -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Sample calculation for bitlocks array size +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Let PGS=GPCCR_PPS_256TB and RME_GPT_BITLOCK_BLOCK=1 +Let PPS=256TB and RME_GPT_BITLOCK_BLOCK=1 -The size of bit lock array in bits is the total protected space (PPS) divided +The size of bitlocks array in bits is the total protected space (PPS) divided by the size of memory block per bit. The size of memory block is ``RME_GPT_BITLOCK_BLOCK`` (number of 512MB blocks per bit) times -512MB (0x20000000). This is then divided by the number of bits in ``bitlock`` -structure (8) to get the size of bit array in bytes. +512MB (0x20000000). This is then divided by the number of bits in ``bitlock_t`` +structure (8) to get the size of array in bytes. -In other words, we can find the total size of ``bitlock`` array -in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8). +In other words, we can find the total size of ``bitlock_t`` array +in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8). Substitute values to get this: 0x1000000000000 / (1 * 0x20000000 * 8) diff --git a/include/lib/gpt_rme/gpt_rme.h b/include/lib/gpt_rme/gpt_rme.h index 94a88b0d5..135a94844 100644 --- a/include/lib/gpt_rme/gpt_rme.h +++ b/include/lib/gpt_rme/gpt_rme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2022-2025, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,13 +8,20 @@ #define GPT_RME_H #include - -#include +#include /******************************************************************************/ /* GPT helper macros and definitions */ /******************************************************************************/ +#if (RME_GPT_BITLOCK_BLOCK != 0) +#define LOCK_SIZE sizeof(((bitlock_t *)NULL)->lock) +#define LOCK_TYPE typeof(((bitlock_t *)NULL)->lock) +#define LOCK_BITS (LOCK_SIZE * UL(8)) + +CASSERT((UL(1) == LOCK_SIZE), assert_bitlock_type_not_uint8_t); +#endif /* RME_GPT_BITLOCK_BLOCK */ + /* * 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 @@ -238,10 +245,14 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, * initialization from a previous stage. Granule protection checks must be * enabled already or this function will return an error. * + * Parameters + * l1_bitlocks_base Base address of memory for L1 tables bitlocks. + * l1_bitlocks_size Total size of memory available for L1 tables bitlocks. + * * Return * Negative Linux error code in the event of a failure, 0 for success. */ -int gpt_runtime_init(void); +int gpt_runtime_init(uintptr_t l1_bitlocks_base, size_t l1_bitlocks_size); /* * Public API to enable granule protection checks once the tables have all been diff --git a/lib/gpt_rme/gpt_rme.c b/lib/gpt_rme/gpt_rme.c index 79c4ea5da..115f50dfd 100644 --- a/lib/gpt_rme/gpt_rme.c +++ b/lib/gpt_rme/gpt_rme.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024, Arm Limited. All rights reserved. + * Copyright (c) 2022-2025, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,14 +12,13 @@ #include #include -#include #include -#include "gpt_rme_private.h" #include #include -#include #include +#include "gpt_rme_private.h" + #if !ENABLE_RME #error "ENABLE_RME must be enabled to use the GPT library" #endif @@ -123,25 +122,19 @@ static uint64_t gpt_l1_index_mask; #define GPT_L1_INDEX(_pa) \ (((_pa) >> (unsigned int)GPT_L1_IDX_SHIFT(gpt_config.p)) & gpt_l1_index_mask) -/* These variables are used during initialization of the L1 tables */ +/* This variable is used during initialization of the L1 tables */ static uintptr_t gpt_l1_tbl; -/* These variable is used during runtime */ +/* These variables are used during runtime */ #if (RME_GPT_BITLOCK_BLOCK == 0) /* * The GPTs are protected by a global spinlock to ensure * that multiple CPUs do not attempt to change the descriptors at once. */ static spinlock_t gpt_lock; -#else -/* Bitlocks base address */ -static bitlock_t *gpt_bitlock_base; -#endif - -/* Lock/unlock macros for GPT entries */ -#if (RME_GPT_BITLOCK_BLOCK == 0) -/* +/* Lock/unlock macros for GPT entries + * * Access to GPT is controlled by a global lock to ensure * that no more than one CPU is allowed to make changes at any * given time. @@ -149,13 +142,17 @@ static bitlock_t *gpt_bitlock_base; #define GPT_LOCK spin_lock(&gpt_lock) #define GPT_UNLOCK spin_unlock(&gpt_lock) #else + +/* Base address of bitlocks array */ +static bitlock_t *gpt_bitlock; + /* * Access to a block of memory is controlled by a bitlock. * Size of block = RME_GPT_BITLOCK_BLOCK * 512MB. */ #define GPT_LOCK bit_lock(gpi_info.lock, gpi_info.mask) #define GPT_UNLOCK bit_unlock(gpi_info.lock, gpi_info.mask) -#endif +#endif /* RME_GPT_BITLOCK_BLOCK */ static void tlbi_page_dsbosh(uintptr_t base) { @@ -494,8 +491,8 @@ static int validate_pas_mappings(pas_region_t *pas_regions, * This function validates L0 initialization parameters. * * Parameters - * l0_mem_base Base address of memory used for L0 tables. - * l0_mem_size Size of memory available for L0 tables. + * l0_mem_base Base address of memory used for L0 table. + * l0_mem_size Size of memory available for L0 table. * * Return * Negative Linux error code in the event of a failure, 0 for success. @@ -503,7 +500,7 @@ static int validate_pas_mappings(pas_region_t *pas_regions, static int validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base, size_t l0_mem_size) { - size_t l0_alignment, locks_size = 0; + size_t l0_alignment; /* * Make sure PPS is valid and then store it since macros need this value @@ -516,8 +513,8 @@ static int validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base, gpt_config.pps = pps; gpt_config.t = gpt_t_lookup[pps]; - /* Alignment must be the greater of 4KB or l0 table size */ - l0_alignment = PAGE_SIZE_4KB; + /* Alignment must be the greater of 4KB or L0 table size */ + l0_alignment = SZ_4K; if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) { l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t); } @@ -529,28 +526,11 @@ static int validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base, return -EFAULT; } -#if (RME_GPT_BITLOCK_BLOCK != 0) - /* - * Size of bitlocks in bytes for the protected address space - * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock. - */ - locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) / - (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U); - - /* - * If protected space size is less than the size covered - * by 'bitlock' structure, check for a single bitlock. - */ - if (locks_size < LOCK_SIZE) { - locks_size = LOCK_SIZE; - } -#endif - /* Check size for L0 tables and bitlocks */ - if (l0_mem_size < (GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size)) { + /* Check memory size for L0 table */ + if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) { ERROR("GPT: Inadequate L0 memory\n"); - ERROR(" Expected 0x%lx bytes, got 0x%lx bytes\n", - GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size, - l0_mem_size); + ERROR(" Expected 0x%lx bytes, got 0x%lx\n", + GPT_L0_TABLE_SIZE(gpt_config.t), l0_mem_size); return -ENOMEM; } @@ -600,7 +580,7 @@ static int validate_l1_params(uintptr_t l1_mem_base, size_t l1_mem_size, if (l1_mem_size < l1_gpt_mem_sz) { ERROR("%sL1 GPTs%s", (const char *)"GPT: Inadequate ", (const char *)" memory\n"); - ERROR(" Expected 0x%lx bytes, got 0x%lx bytes\n", + ERROR(" Expected 0x%lx bytes, got 0x%lx\n", l1_gpt_mem_sz, l1_mem_size); return -ENOMEM; } @@ -623,7 +603,7 @@ static void generate_l0_blk_desc(pas_region_t *pas) unsigned long idx, end_idx; uint64_t *l0_gpt_arr; - assert(gpt_config.plat_gpt_l0_base != 0U); + assert(gpt_config.plat_gpt_l0_base != 0UL); assert(pas != NULL); /* @@ -928,7 +908,7 @@ static void generate_l0_tbl_desc(pas_region_t *pas) uint64_t *l1_gpt_arr; unsigned int l0_idx, gpi; - assert(gpt_config.plat_gpt_l0_base != 0U); + assert(gpt_config.plat_gpt_l0_base != 0UL); assert(pas != NULL); /* @@ -1121,12 +1101,10 @@ int gpt_init_l0_tables(gpccr_pps_e pps, uintptr_t l0_mem_base, size_t l0_mem_size) { uint64_t gpt_desc; - size_t locks_size = 0; - __unused bitlock_t *bit_locks; int ret; /* Ensure that MMU and Data caches are enabled */ - assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); /* Validate other parameters */ ret = validate_l0_params(pps, l0_mem_base, l0_mem_size); @@ -1142,31 +1120,8 @@ int gpt_init_l0_tables(gpccr_pps_e pps, uintptr_t l0_mem_base, ((uint64_t *)l0_mem_base)[i] = gpt_desc; } -#if (RME_GPT_BITLOCK_BLOCK != 0) - /* Initialise bitlocks at the end of L0 table */ - bit_locks = (bitlock_t *)(l0_mem_base + - GPT_L0_TABLE_SIZE(gpt_config.t)); - - /* Size of bitlocks in bytes */ - locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) / - (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U); - - /* - * If protected space size is less than the size covered - * by 'bitlock' structure, initialise a single bitlock. - */ - if (locks_size < LOCK_SIZE) { - locks_size = LOCK_SIZE; - } - - for (size_t i = 0UL; i < (locks_size/LOCK_SIZE); i++) { - bit_locks[i].lock = 0U; - } -#endif - - /* Flush updated L0 tables and bitlocks to memory */ - flush_dcache_range((uintptr_t)l0_mem_base, - GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size); + /* Flush updated L0 table to memory */ + flush_dcache_range((uintptr_t)l0_mem_base, GPT_L0_TABLE_SIZE(gpt_config.t)); /* Stash the L0 base address once initial setup is complete */ gpt_config.plat_gpt_l0_base = l0_mem_base; @@ -1202,7 +1157,7 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base, int l1_gpt_cnt, ret; /* Ensure that MMU and Data caches are enabled */ - assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); /* PGS is needed for validate_pas_mappings so check it now */ if (pgs > GPT_PGS_MAX) { @@ -1213,7 +1168,7 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base, gpt_config.p = gpt_p_lookup[pgs]; /* Make sure L0 tables have been initialized */ - if (gpt_config.plat_gpt_l0_base == 0U) { + if (gpt_config.plat_gpt_l0_base == 0UL) { ERROR("GPT: L0 tables must be initialized first!\n"); return -EPERM; } @@ -1295,18 +1250,23 @@ int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base, * initialization from a previous stage. Granule protection checks must be * enabled already or this function will return an error. * + * Parameters + * l1_bitlocks_base Base address of memory for L1 tables bitlocks. + * l1_bitlocks_size Total size of memory available for L1 tables bitlocks. + * * Return * Negative Linux error code in the event of a failure, 0 for success. */ -int gpt_runtime_init(void) +int gpt_runtime_init(uintptr_t l1_bitlocks_base, size_t l1_bitlocks_size) { u_register_t reg; + __unused size_t locks_size; /* Ensure that MMU and Data caches are enabled */ - assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); /* Ensure GPC are already enabled */ - if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) { + if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0UL) { ERROR("GPT: Granule protection checks are not enabled!\n"); return -EPERM; } @@ -1334,17 +1294,43 @@ int gpt_runtime_init(void) gpt_l1_index_mask = GPT_L1_IDX_MASK(gpt_config.p); #if (RME_GPT_BITLOCK_BLOCK != 0) - /* Bitlocks at the end of L0 table */ - gpt_bitlock_base = (bitlock_t *)(gpt_config.plat_gpt_l0_base + - GPT_L0_TABLE_SIZE(gpt_config.t)); -#endif + /* + * Size of GPT bitlocks in bytes for the protected address space + * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock. + */ + locks_size = GPT_PPS_ACTUAL_SIZE(gpt_config.t) / + (RME_GPT_BITLOCK_BLOCK * SZ_512M * 8U); + /* + * If protected space size is less than the size covered + * by 'bitlock' structure, check for a single bitlock. + */ + if (locks_size < LOCK_SIZE) { + locks_size = LOCK_SIZE; + /* Check bitlocks array size */ + } else if (locks_size > l1_bitlocks_size) { + ERROR("GPT: Inadequate GPT bitlocks memory\n"); + ERROR(" Expected 0x%lx bytes, got 0x%lx\n", + locks_size, l1_bitlocks_size); + return -ENOMEM; + } + + gpt_bitlock = (bitlock_t *)l1_bitlocks_base; + + /* Initialise GPT bitlocks */ + (void)memset((void *)gpt_bitlock, 0, locks_size); + + /* Flush GPT bitlocks to memory */ + flush_dcache_range((uintptr_t)gpt_bitlock, locks_size); +#endif /* RME_GPT_BITLOCK_BLOCK */ + VERBOSE("GPT: Runtime Configuration\n"); VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t); VERBOSE(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p); VERBOSE(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL); VERBOSE(" L0 base: 0x%"PRIxPTR"\n", gpt_config.plat_gpt_l0_base); #if (RME_GPT_BITLOCK_BLOCK != 0) - VERBOSE(" Bitlocks: 0x%"PRIxPTR"\n", (uintptr_t)gpt_bitlock_base); + VERBOSE(" Bitlocks: 0x%"PRIxPTR"/0x%lx\n", (uintptr_t)gpt_bitlock, + locks_size); #endif return 0; } @@ -1391,7 +1377,7 @@ static int get_gpi_params(uint64_t base, gpi_info_t *gpi_info) block_idx = (unsigned int)(base / (RME_GPT_BITLOCK_BLOCK * SZ_512M)); /* Bitlock address and mask */ - gpi_info->lock = &gpt_bitlock_base[block_idx / LOCK_BITS]; + gpi_info->lock = &gpt_bitlock[block_idx / LOCK_BITS]; gpi_info->mask = 1U << (block_idx & (LOCK_BITS - 1U)); #endif return 0; diff --git a/lib/gpt_rme/gpt_rme.mk b/lib/gpt_rme/gpt_rme.mk index 7d6b61f94..6878489e3 100644 --- a/lib/gpt_rme/gpt_rme.mk +++ b/lib/gpt_rme/gpt_rme.mk @@ -1,19 +1,24 @@ # -# Copyright (c) 2021-2024, Arm Limited. All rights reserved. +# Copyright (c) 2021-2025, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # +# RME_GPT_BITLOCK_BLOCK is the number of 512MB blocks +# per bit and the value must be power of 2. +BITLOCK_BLOCK_POWER_2=$(shell echo $$(( ${RME_GPT_BITLOCK_BLOCK} & (${RME_GPT_BITLOCK_BLOCK} - 1) ))) + # Process RME_GPT_BITLOCK_BLOCK value -ifeq ($(filter 0 1 2 4 8 16 32 64 128 256 512, ${RME_GPT_BITLOCK_BLOCK}),) - $(error "Invalid value for RME_GPT_BITLOCK_BLOCK: ${RME_GPT_BITLOCK_BLOCK}") +ifneq (${BITLOCK_BLOCK_POWER_2}, 0) + $(error "RME_GPT_BITLOCK_BLOCK must be power of 2. Invalid value ${RME_GPT_BITLOCK_BLOCK}.") endif ifeq (${RME_GPT_BITLOCK_BLOCK},0) - $(warning "GPT library uses global spinlock") + $(info "GPT library uses global spinlock") endif -# Process RME_GPT_MAX_BLOCK value +# Process the maximum size of supported contiguous blocks +# RME_GPT_MAX_BLOCK ifeq ($(filter 0 2 32 512, ${RME_GPT_MAX_BLOCK}),) $(error "Invalid value for RME_GPT_MAX_BLOCK: ${RME_GPT_MAX_BLOCK}") endif diff --git a/lib/gpt_rme/gpt_rme_private.h b/lib/gpt_rme/gpt_rme_private.h index 31dad20c7..78d1cecd7 100644 --- a/lib/gpt_rme/gpt_rme_private.h +++ b/lib/gpt_rme/gpt_rme_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024, Arm Limited. All rights reserved. + * Copyright (c) 2022-2025, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,9 +7,7 @@ #ifndef GPT_RME_PRIVATE_H #define GPT_RME_PRIVATE_H -#include #include -#include #include /******************************************************************************/ @@ -141,10 +139,6 @@ typedef enum { PGS_64KB_P = 16U } gpt_p_val_e; -#define LOCK_SIZE sizeof(((bitlock_t *)NULL)->lock) -#define LOCK_TYPE typeof(((bitlock_t *)NULL)->lock) -#define LOCK_BITS (LOCK_SIZE * 8U) - /* * Internal structure to retrieve the values from get_gpi_params(); */ diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 25848e490..f597f4b12 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -57,7 +57,7 @@ /* Protected physical address size */ #define PLAT_ARM_PPS (64 * SZ_1G) -#endif +#endif /* ENABLE_RME */ /* * Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index ce1545f5e..0503acf10 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -34,9 +34,31 @@ struct transfer_list_header *ns_tl __unused; */ static entry_point_info_t bl32_image_ep_info; static entry_point_info_t bl33_image_ep_info; + #if ENABLE_RME static entry_point_info_t rmm_image_ep_info; +#if (RME_GPT_BITLOCK_BLOCK == 0) +#define BITLOCK_BASE UL(0) +#define BITLOCK_SIZE UL(0) +#else +/* + * Number of bitlock_t entries in bitlocks array for PLAT_ARM_PPS + * with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock. + */ +#if (PLAT_ARM_PPS > (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8))) +#define BITLOCKS_NUM (PLAT_ARM_PPS) / \ + (RME_GPT_BITLOCK_BLOCK * SZ_512M * UL(8)) +#else +#define BITLOCKS_NUM U(1) #endif +/* + * Bitlocks array + */ +static bitlock_t gpt_bitlock[BITLOCKS_NUM]; +#define BITLOCK_BASE (uintptr_t)gpt_bitlock +#define BITLOCK_SIZE sizeof(gpt_bitlock) +#endif /* RME_GPT_BITLOCK_BLOCK */ +#endif /* ENABLE_RME */ #if !RESET_TO_BL31 /* @@ -551,7 +573,7 @@ void __init arm_bl31_plat_arch_setup(void) * stage, so there is no need to provide any PAS here. This function * sets up pointers to those tables. */ - if (gpt_runtime_init() < 0) { + if (gpt_runtime_init(BITLOCK_BASE, BITLOCK_SIZE) < 0) { ERROR("gpt_runtime_init() failed!\n"); panic(); }