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 <Alexei.Fedorov@arm.com>
diff --git a/docs/components/granule-protection-tables-design.rst b/docs/components/granule-protection-tables-design.rst
index 78d2f12..91673c6 100644
--- a/docs/components/granule-protection-tables-design.rst
+++ b/docs/components/granule-protection-tables-design.rst
@@ -124,10 +124,7 @@
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 @@
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 @@
#. 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 @@
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 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 @@
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 @@
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 94a88b0..135a948 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 <stdint.h>
-
-#include <arch.h>
+#include <lib/spinlock.h>
/******************************************************************************/
/* 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 @@
* 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 79c4ea5..115f50d 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 <arch.h>
#include <arch_features.h>
-#include <arch_helpers.h>
#include <common/debug.h>
-#include "gpt_rme_private.h"
#include <lib/gpt_rme/gpt_rme.h>
#include <lib/smccc.h>
-#include <lib/spinlock.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
+#include "gpt_rme_private.h"
+
#if !ENABLE_RME
#error "ENABLE_RME must be enabled to use the GPT library"
#endif
@@ -123,25 +122,19 @@
#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 @@
#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 @@
* 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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
@@ -1141,32 +1119,9 @@
for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) {
((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 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 @@
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 @@
* 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 @@
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 @@
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 7d6b61f..6878489 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 31dad20..78d1cec 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 <arch.h>
#include <lib/gpt_rme/gpt_rme.h>
-#include <lib/spinlock.h>
#include <lib/utils_def.h>
/******************************************************************************/
@@ -141,10 +139,6 @@
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 25848e4..f597f4b 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 ce1545f..0503acf 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -34,9 +34,31 @@
*/
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 @@
* 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();
}