feat(qemu): setup Granule Protection Table

When RME is enabled, call the GPT library to setup the granule
protection tables and partition the physical address space.

Change-Id: Ib466c4579ff55fcff9307550e6d26d432674779a
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
This commit is contained in:
Jean-Philippe Brucker 2023-09-07 18:47:48 +01:00
parent cd75693f5e
commit 6cd113fe06
2 changed files with 68 additions and 0 deletions

View file

@ -24,6 +24,9 @@
#endif #endif
#include <lib/utils.h> #include <lib/utils.h>
#include <plat/common/platform.h> #include <plat/common/platform.h>
#if ENABLE_RME
#include <qemu_pas_def.h>
#endif
#include "qemu_private.h" #include "qemu_private.h"
@ -151,6 +154,53 @@ void qemu_bl2_sync_transfer_list(void)
#endif #endif
} }
#if ENABLE_RME
static void bl2_plat_gpt_setup(void)
{
/*
* The GPT library might modify the gpt regions structure to optimize
* the layout, so the array cannot be constant.
*/
pas_region_t pas_regions[] = {
QEMU_PAS_ROOT,
QEMU_PAS_SECURE,
QEMU_PAS_GPTS,
QEMU_PAS_NS0,
QEMU_PAS_REALM,
QEMU_PAS_NS1,
};
/*
* Initialize entire protected space to GPT_GPI_ANY. With each L0 entry
* covering 1GB (currently the only supported option), then covering
* 256TB of RAM (48-bit PA) would require a 2MB L0 region. At the
* moment we use a 8KB table, which covers 1TB of RAM (40-bit PA).
*/
if (gpt_init_l0_tables(GPCCR_PPS_1TB, PLAT_QEMU_L0_GPT_BASE,
PLAT_QEMU_L0_GPT_SIZE) < 0) {
ERROR("gpt_init_l0_tables() failed!\n");
panic();
}
/* Carve out defined PAS ranges. */
if (gpt_init_pas_l1_tables(GPCCR_PGS_4K,
PLAT_QEMU_L1_GPT_BASE,
PLAT_QEMU_L1_GPT_SIZE,
pas_regions,
(unsigned int)(sizeof(pas_regions) /
sizeof(pas_region_t))) < 0) {
ERROR("gpt_init_pas_l1_tables() failed!\n");
panic();
}
INFO("Enabling Granule Protection Checks\n");
if (gpt_enable() < 0) {
ERROR("gpt_enable() failed!\n");
panic();
}
}
#endif
void bl2_plat_arch_setup(void) void bl2_plat_arch_setup(void)
{ {
const mmap_region_t bl_regions[] = { const mmap_region_t bl_regions[] = {
@ -173,6 +223,9 @@ void bl2_plat_arch_setup(void)
/* BL2 runs in EL3 when RME enabled. */ /* BL2 runs in EL3 when RME enabled. */
assert(get_armv9_2_feat_rme_support() != 0U); assert(get_armv9_2_feat_rme_support() != 0U);
enable_mmu_el3(0); enable_mmu_el3(0);
/* Initialise and enable granule protection after MMU. */
bl2_plat_gpt_setup();
#else /* ENABLE_RME */ #else /* ENABLE_RME */
#ifdef __aarch64__ #ifdef __aarch64__

View file

@ -8,6 +8,7 @@
#include <common/bl_common.h> #include <common/bl_common.h>
#include <drivers/arm/pl061_gpio.h> #include <drivers/arm/pl061_gpio.h>
#include <lib/gpt_rme/gpt_rme.h>
#include <plat/common/platform.h> #include <plat/common/platform.h>
#include "qemu_private.h" #include "qemu_private.h"
@ -108,6 +109,20 @@ void bl31_plat_arch_setup(void)
setup_page_tables(bl_regions, plat_qemu_get_mmap()); setup_page_tables(bl_regions, plat_qemu_get_mmap());
enable_mmu_el3(0); enable_mmu_el3(0);
#if ENABLE_RME
/*
* Initialise Granule Protection library and enable GPC for the primary
* processor. The tables have already been initialized by a previous BL
* stage, so there is no need to provide any PAS here. This function
* sets up pointers to those tables.
*/
if (gpt_runtime_init() < 0) {
ERROR("gpt_runtime_init() failed!\n");
panic();
}
#endif /* ENABLE_RME */
} }
static void qemu_gpio_init(void) static void qemu_gpio_init(void)