mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-08 13:53:54 +00:00
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>
This commit is contained in:
parent
ac07f3ab6e
commit
b0f1c84035
7 changed files with 138 additions and 118 deletions
|
@ -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
|
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
|
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
|
building the level 0 tables.
|
||||||
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.
|
|
||||||
|
|
||||||
The ``gpt_init_pas_l1_tables`` API takes an address and size for
|
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
|
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
|
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.
|
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
|
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
|
structure. Setting this option to 0 chooses a single spinlock for all GPT L1
|
||||||
table entries.
|
table entries.
|
||||||
|
|
||||||
|
@ -185,6 +182,10 @@ process.
|
||||||
#. In systems that make use of the granule transition service, runtime
|
#. In systems that make use of the granule transition service, runtime
|
||||||
firmware must call ``gpt_runtime_init`` to set up the data structures needed
|
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.
|
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
|
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
|
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
|
size of each L0 region (L0GPTSZ) multiplied by the size of each L0 descriptor
|
||||||
(8 bytes). ((PPS / L0GPTSZ) * 8)
|
(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 L0 memory must fall within a PAS of type GPT_GPI_ROOT.
|
||||||
|
|
||||||
The L1 memory also has some constraints.
|
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)
|
the granules controlled in each byte (2). ((L0GPTSZ / PGS) / 2)
|
||||||
* There must be enough L1 memory supplied to build all requested L1 tables.
|
* 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 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
|
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
|
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
|
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)
|
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
|
And solve to get 32 bytes. In this case, 4096 is greater than 32, so the L0
|
||||||
tables must be aligned to 4096 bytes.
|
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
|
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
|
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``
|
512MB (0x20000000). This is then divided by the number of bits in ``bitlock_t``
|
||||||
structure (8) to get the size of bit array in bytes.
|
structure (8) to get the size of array in bytes.
|
||||||
|
|
||||||
In other words, we can find the total size of ``bitlock`` array
|
In other words, we can find the total size of ``bitlock_t`` array
|
||||||
in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8).
|
in bytes with PPS / (RME_GPT_BITLOCK_BLOCK * 0x20000000 * 8).
|
||||||
|
|
||||||
Substitute values to get this: 0x1000000000000 / (1 * 0x20000000 * 8)
|
Substitute values to get this: 0x1000000000000 / (1 * 0x20000000 * 8)
|
||||||
|
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -8,13 +8,20 @@
|
||||||
#define GPT_RME_H
|
#define GPT_RME_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <lib/spinlock.h>
|
||||||
#include <arch.h>
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* GPT helper macros and definitions */
|
/* 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
|
* 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
|
* 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
|
* initialization from a previous stage. Granule protection checks must be
|
||||||
* enabled already or this function will return an error.
|
* 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
|
* Return
|
||||||
* Negative Linux error code in the event of a failure, 0 for success.
|
* 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
|
* Public API to enable granule protection checks once the tables have all been
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -12,14 +12,13 @@
|
||||||
|
|
||||||
#include <arch.h>
|
#include <arch.h>
|
||||||
#include <arch_features.h>
|
#include <arch_features.h>
|
||||||
#include <arch_helpers.h>
|
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
#include "gpt_rme_private.h"
|
|
||||||
#include <lib/gpt_rme/gpt_rme.h>
|
#include <lib/gpt_rme/gpt_rme.h>
|
||||||
#include <lib/smccc.h>
|
#include <lib/smccc.h>
|
||||||
#include <lib/spinlock.h>
|
|
||||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||||
|
|
||||||
|
#include "gpt_rme_private.h"
|
||||||
|
|
||||||
#if !ENABLE_RME
|
#if !ENABLE_RME
|
||||||
#error "ENABLE_RME must be enabled to use the GPT library"
|
#error "ENABLE_RME must be enabled to use the GPT library"
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,25 +122,19 @@ static uint64_t gpt_l1_index_mask;
|
||||||
#define GPT_L1_INDEX(_pa) \
|
#define GPT_L1_INDEX(_pa) \
|
||||||
(((_pa) >> (unsigned int)GPT_L1_IDX_SHIFT(gpt_config.p)) & gpt_l1_index_mask)
|
(((_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;
|
static uintptr_t gpt_l1_tbl;
|
||||||
|
|
||||||
/* These variable is used during runtime */
|
/* These variables are used during runtime */
|
||||||
#if (RME_GPT_BITLOCK_BLOCK == 0)
|
#if (RME_GPT_BITLOCK_BLOCK == 0)
|
||||||
/*
|
/*
|
||||||
* The GPTs are protected by a global spinlock to ensure
|
* The GPTs are protected by a global spinlock to ensure
|
||||||
* that multiple CPUs do not attempt to change the descriptors at once.
|
* that multiple CPUs do not attempt to change the descriptors at once.
|
||||||
*/
|
*/
|
||||||
static spinlock_t gpt_lock;
|
static spinlock_t gpt_lock;
|
||||||
#else
|
|
||||||
|
|
||||||
/* Bitlocks base address */
|
/* Lock/unlock macros for GPT entries
|
||||||
static bitlock_t *gpt_bitlock_base;
|
*
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Lock/unlock macros for GPT entries */
|
|
||||||
#if (RME_GPT_BITLOCK_BLOCK == 0)
|
|
||||||
/*
|
|
||||||
* Access to GPT is controlled by a global lock to ensure
|
* Access to GPT is controlled by a global lock to ensure
|
||||||
* that no more than one CPU is allowed to make changes at any
|
* that no more than one CPU is allowed to make changes at any
|
||||||
* given time.
|
* given time.
|
||||||
|
@ -149,13 +142,17 @@ static bitlock_t *gpt_bitlock_base;
|
||||||
#define GPT_LOCK spin_lock(&gpt_lock)
|
#define GPT_LOCK spin_lock(&gpt_lock)
|
||||||
#define GPT_UNLOCK spin_unlock(&gpt_lock)
|
#define GPT_UNLOCK spin_unlock(&gpt_lock)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
/* Base address of bitlocks array */
|
||||||
|
static bitlock_t *gpt_bitlock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Access to a block of memory is controlled by a bitlock.
|
* Access to a block of memory is controlled by a bitlock.
|
||||||
* Size of block = RME_GPT_BITLOCK_BLOCK * 512MB.
|
* Size of block = RME_GPT_BITLOCK_BLOCK * 512MB.
|
||||||
*/
|
*/
|
||||||
#define GPT_LOCK bit_lock(gpi_info.lock, gpi_info.mask)
|
#define GPT_LOCK bit_lock(gpi_info.lock, gpi_info.mask)
|
||||||
#define GPT_UNLOCK bit_unlock(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)
|
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.
|
* This function validates L0 initialization parameters.
|
||||||
*
|
*
|
||||||
* Parameters
|
* Parameters
|
||||||
* l0_mem_base Base address of memory used for L0 tables.
|
* l0_mem_base Base address of memory used for L0 table.
|
||||||
* l0_mem_size Size of memory available for L0 tables.
|
* l0_mem_size Size of memory available for L0 table.
|
||||||
*
|
*
|
||||||
* Return
|
* Return
|
||||||
* Negative Linux error code in the event of a failure, 0 for success.
|
* 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,
|
static int validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base,
|
||||||
size_t l0_mem_size)
|
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
|
* 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.pps = pps;
|
||||||
gpt_config.t = gpt_t_lookup[pps];
|
gpt_config.t = gpt_t_lookup[pps];
|
||||||
|
|
||||||
/* Alignment must be the greater of 4KB or l0 table size */
|
/* Alignment must be the greater of 4KB or L0 table size */
|
||||||
l0_alignment = PAGE_SIZE_4KB;
|
l0_alignment = SZ_4K;
|
||||||
if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) {
|
if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) {
|
||||||
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;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (RME_GPT_BITLOCK_BLOCK != 0)
|
/* Check memory size for L0 table */
|
||||||
/*
|
if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) {
|
||||||
* 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)) {
|
|
||||||
ERROR("GPT: Inadequate L0 memory\n");
|
ERROR("GPT: Inadequate L0 memory\n");
|
||||||
ERROR(" Expected 0x%lx bytes, got 0x%lx bytes\n",
|
ERROR(" Expected 0x%lx bytes, got 0x%lx\n",
|
||||||
GPT_L0_TABLE_SIZE(gpt_config.t) + locks_size,
|
GPT_L0_TABLE_SIZE(gpt_config.t), l0_mem_size);
|
||||||
l0_mem_size);
|
|
||||||
return -ENOMEM;
|
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) {
|
if (l1_mem_size < l1_gpt_mem_sz) {
|
||||||
ERROR("%sL1 GPTs%s", (const char *)"GPT: Inadequate ",
|
ERROR("%sL1 GPTs%s", (const char *)"GPT: Inadequate ",
|
||||||
(const char *)" memory\n");
|
(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);
|
l1_gpt_mem_sz, l1_mem_size);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -623,7 +603,7 @@ static void generate_l0_blk_desc(pas_region_t *pas)
|
||||||
unsigned long idx, end_idx;
|
unsigned long idx, end_idx;
|
||||||
uint64_t *l0_gpt_arr;
|
uint64_t *l0_gpt_arr;
|
||||||
|
|
||||||
assert(gpt_config.plat_gpt_l0_base != 0U);
|
assert(gpt_config.plat_gpt_l0_base != 0UL);
|
||||||
assert(pas != NULL);
|
assert(pas != NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -928,7 +908,7 @@ static void generate_l0_tbl_desc(pas_region_t *pas)
|
||||||
uint64_t *l1_gpt_arr;
|
uint64_t *l1_gpt_arr;
|
||||||
unsigned int l0_idx, gpi;
|
unsigned int l0_idx, gpi;
|
||||||
|
|
||||||
assert(gpt_config.plat_gpt_l0_base != 0U);
|
assert(gpt_config.plat_gpt_l0_base != 0UL);
|
||||||
assert(pas != NULL);
|
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)
|
size_t l0_mem_size)
|
||||||
{
|
{
|
||||||
uint64_t gpt_desc;
|
uint64_t gpt_desc;
|
||||||
size_t locks_size = 0;
|
|
||||||
__unused bitlock_t *bit_locks;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Ensure that MMU and Data caches are enabled */
|
/* 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 */
|
/* Validate other parameters */
|
||||||
ret = validate_l0_params(pps, l0_mem_base, l0_mem_size);
|
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;
|
((uint64_t *)l0_mem_base)[i] = gpt_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (RME_GPT_BITLOCK_BLOCK != 0)
|
/* Flush updated L0 table to memory */
|
||||||
/* Initialise bitlocks at the end of L0 table */
|
flush_dcache_range((uintptr_t)l0_mem_base, GPT_L0_TABLE_SIZE(gpt_config.t));
|
||||||
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);
|
|
||||||
|
|
||||||
/* Stash the L0 base address once initial setup is complete */
|
/* Stash the L0 base address once initial setup is complete */
|
||||||
gpt_config.plat_gpt_l0_base = l0_mem_base;
|
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;
|
int l1_gpt_cnt, ret;
|
||||||
|
|
||||||
/* Ensure that MMU and Data caches are enabled */
|
/* 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 */
|
/* PGS is needed for validate_pas_mappings so check it now */
|
||||||
if (pgs > GPT_PGS_MAX) {
|
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];
|
gpt_config.p = gpt_p_lookup[pgs];
|
||||||
|
|
||||||
/* Make sure L0 tables have been initialized */
|
/* 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");
|
ERROR("GPT: L0 tables must be initialized first!\n");
|
||||||
return -EPERM;
|
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
|
* initialization from a previous stage. Granule protection checks must be
|
||||||
* enabled already or this function will return an error.
|
* 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
|
* Return
|
||||||
* Negative Linux error code in the event of a failure, 0 for success.
|
* 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;
|
u_register_t reg;
|
||||||
|
__unused size_t locks_size;
|
||||||
|
|
||||||
/* Ensure that MMU and Data caches are enabled */
|
/* 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 */
|
/* 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");
|
ERROR("GPT: Granule protection checks are not enabled!\n");
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
@ -1334,17 +1294,43 @@ int gpt_runtime_init(void)
|
||||||
gpt_l1_index_mask = GPT_L1_IDX_MASK(gpt_config.p);
|
gpt_l1_index_mask = GPT_L1_IDX_MASK(gpt_config.p);
|
||||||
|
|
||||||
#if (RME_GPT_BITLOCK_BLOCK != 0)
|
#if (RME_GPT_BITLOCK_BLOCK != 0)
|
||||||
/* Bitlocks at the end of L0 table */
|
/*
|
||||||
gpt_bitlock_base = (bitlock_t *)(gpt_config.plat_gpt_l0_base +
|
* Size of GPT bitlocks in bytes for the protected address space
|
||||||
GPT_L0_TABLE_SIZE(gpt_config.t));
|
* with RME_GPT_BITLOCK_BLOCK * 512MB per bitlock.
|
||||||
#endif
|
*/
|
||||||
|
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("GPT: Runtime Configuration\n");
|
||||||
VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t);
|
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(" 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(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL);
|
||||||
VERBOSE(" L0 base: 0x%"PRIxPTR"\n", gpt_config.plat_gpt_l0_base);
|
VERBOSE(" L0 base: 0x%"PRIxPTR"\n", gpt_config.plat_gpt_l0_base);
|
||||||
#if (RME_GPT_BITLOCK_BLOCK != 0)
|
#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
|
#endif
|
||||||
return 0;
|
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));
|
block_idx = (unsigned int)(base / (RME_GPT_BITLOCK_BLOCK * SZ_512M));
|
||||||
|
|
||||||
/* Bitlock address and mask */
|
/* 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));
|
gpi_info->mask = 1U << (block_idx & (LOCK_BITS - 1U));
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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
|
# 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
|
# Process RME_GPT_BITLOCK_BLOCK value
|
||||||
ifeq ($(filter 0 1 2 4 8 16 32 64 128 256 512, ${RME_GPT_BITLOCK_BLOCK}),)
|
ifneq (${BITLOCK_BLOCK_POWER_2}, 0)
|
||||||
$(error "Invalid value for RME_GPT_BITLOCK_BLOCK: ${RME_GPT_BITLOCK_BLOCK}")
|
$(error "RME_GPT_BITLOCK_BLOCK must be power of 2. Invalid value ${RME_GPT_BITLOCK_BLOCK}.")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (${RME_GPT_BITLOCK_BLOCK},0)
|
ifeq (${RME_GPT_BITLOCK_BLOCK},0)
|
||||||
$(warning "GPT library uses global spinlock")
|
$(info "GPT library uses global spinlock")
|
||||||
endif
|
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}),)
|
ifeq ($(filter 0 2 32 512, ${RME_GPT_MAX_BLOCK}),)
|
||||||
$(error "Invalid value for RME_GPT_MAX_BLOCK: ${RME_GPT_MAX_BLOCK}")
|
$(error "Invalid value for RME_GPT_MAX_BLOCK: ${RME_GPT_MAX_BLOCK}")
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -7,9 +7,7 @@
|
||||||
#ifndef GPT_RME_PRIVATE_H
|
#ifndef GPT_RME_PRIVATE_H
|
||||||
#define GPT_RME_PRIVATE_H
|
#define GPT_RME_PRIVATE_H
|
||||||
|
|
||||||
#include <arch.h>
|
|
||||||
#include <lib/gpt_rme/gpt_rme.h>
|
#include <lib/gpt_rme/gpt_rme.h>
|
||||||
#include <lib/spinlock.h>
|
|
||||||
#include <lib/utils_def.h>
|
#include <lib/utils_def.h>
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -141,10 +139,6 @@ typedef enum {
|
||||||
PGS_64KB_P = 16U
|
PGS_64KB_P = 16U
|
||||||
} gpt_p_val_e;
|
} 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();
|
* Internal structure to retrieve the values from get_gpi_params();
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
/* Protected physical address size */
|
/* Protected physical address size */
|
||||||
#define PLAT_ARM_PPS (64 * SZ_1G)
|
#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
|
* Max size of SPMC is 2MB for fvp. With SPMD enabled this value corresponds to
|
||||||
|
|
|
@ -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 bl32_image_ep_info;
|
||||||
static entry_point_info_t bl33_image_ep_info;
|
static entry_point_info_t bl33_image_ep_info;
|
||||||
|
|
||||||
#if ENABLE_RME
|
#if ENABLE_RME
|
||||||
static entry_point_info_t rmm_image_ep_info;
|
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
|
#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
|
#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
|
* stage, so there is no need to provide any PAS here. This function
|
||||||
* sets up pointers to those tables.
|
* 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");
|
ERROR("gpt_runtime_init() failed!\n");
|
||||||
panic();
|
panic();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue