Browse Source

feat(spmd): add spmd logical partitions

Add header file to help with creation of SPMD logical partitions. Also
update linker files to create sections to record SPMD logical partitions
declared. This follows the same pattern as the EL3 SPMC's logical
partitions. This patch also adds initialization of SPMD logical
partitions when the SPMD comes up.
ENABLE_SPMD_LP is a build flag that is used to enable support for
SPMD logical partitions.
Note that the approach chosen is to keep SPMD and SPMC logical
partition support separate, as opposed to extend the existing SPMC
logical partition support since the code would need to have a number of
ifdefs and the interactions with various build options such as
SPMC_AT_EL3 needs to be accounted for, which would make code more
complicated.

Signed-off-by: Raghu Krishnamurthy <raghu.ncstate@gmail.com>
Change-Id: I9642ddbf6ea26dd3f4a283baec598d61c07e3661
pull/2000/head
Raghu Krishnamurthy 2 years ago
parent
commit
890b508820
  1. 11
      Makefile
  2. 4
      include/common/bl_common.h
  3. 12
      include/common/bl_common.ld.h
  4. 63
      include/services/el3_spmd_logical_sp.h
  5. 3
      make_helpers/defaults.mk
  6. 3
      services/std_svc/spmd/spmd.mk
  7. 165
      services/std_svc/spmd/spmd_logical_sp.c
  8. 7
      services/std_svc/spmd/spmd_main.c

11
Makefile

@ -623,6 +623,15 @@ ifneq (${SPD},none)
# over the sources. # over the sources.
endif #(SPD=none) endif #(SPD=none)
ifeq (${ENABLE_SPMD_LP}, 1)
ifneq (${SPD},spmd)
$(error Error: ENABLE_SPMD_LP requires SPD=spmd.)
endif
ifeq ($(SPMC_AT_EL3),1)
$(error SPMC at EL3 not supported when enabling SPMD Logical partitions.)
endif
endif
ifeq (${CTX_INCLUDE_EL2_REGS}, 1) ifeq (${CTX_INCLUDE_EL2_REGS}, 1)
ifeq (${SPD},none) ifeq (${SPD},none)
ifeq (${ENABLE_RME},0) ifeq (${ENABLE_RME},0)
@ -1181,6 +1190,7 @@ $(eval $(call assert_booleans,\
SPM_MM \ SPM_MM \
SPMC_AT_EL3 \ SPMC_AT_EL3 \
SPMD_SPM_AT_SEL2 \ SPMD_SPM_AT_SEL2 \
ENABLE_SPMD_LP \
TRUSTED_BOARD_BOOT \ TRUSTED_BOARD_BOOT \
USE_COHERENT_MEM \ USE_COHERENT_MEM \
USE_DEBUGFS \ USE_DEBUGFS \
@ -1397,6 +1407,7 @@ $(eval $(call add_defines,\
CONDITIONAL_CMO \ CONDITIONAL_CMO \
IMPDEF_SYSREG_TRAP \ IMPDEF_SYSREG_TRAP \
SVE_VECTOR_LEN \ SVE_VECTOR_LEN \
ENABLE_SPMD_LP \
))) )))
ifeq (${SANITIZE_UB},trap) ifeq (${SANITIZE_UB},trap)

4
include/common/bl_common.h

@ -85,6 +85,10 @@
#define __EL3_LP_DESCS_START__ Load$$__EL3_LP_DESCS__$$Base #define __EL3_LP_DESCS_START__ Load$$__EL3_LP_DESCS__$$Base
#define __EL3_LP_DESCS_END__ Load$$__EL3_LP_DESCS__$$Limit #define __EL3_LP_DESCS_END__ Load$$__EL3_LP_DESCS__$$Limit
#endif #endif
#if ENABLE_SPMD_LP
#define __SPMD_LP_DESCS_START__ Load$$__SPMD_LP_DESCS__$$Base
#define __SPMD_LP_DESCS_END__ Load$$__SPMD_LP_DESCS__$$Limit
#endif
#define __RW_START__ Load$$LR$$LR_RW_DATA$$Base #define __RW_START__ Load$$LR$$LR_RW_DATA$$Base
#define __RW_END__ Load$$LR$$LR_END$$Base #define __RW_END__ Load$$LR$$LR_END$$Base
#define __SPM_SHIM_EXCEPTIONS_START__ Load$$__SPM_SHIM_EXCEPTIONS__$$Base #define __SPM_SHIM_EXCEPTIONS_START__ Load$$__SPM_SHIM_EXCEPTIONS__$$Base

12
include/common/bl_common.ld.h

@ -49,6 +49,15 @@
#define EL3_LP_DESCS #define EL3_LP_DESCS
#endif #endif
#if ENABLE_SPMD_LP
#define SPMD_LP_DESCS \
. = ALIGN(STRUCT_ALIGN); \
__SPMD_LP_DESCS_START__ = .; \
KEEP(*(.spmd_lp_descs)) \
__SPMD_LP_DESCS_END__ = .;
#else
#define SPMD_LP_DESCS
#endif
#define PMF_SVC_DESCS \ #define PMF_SVC_DESCS \
. = ALIGN(STRUCT_ALIGN); \ . = ALIGN(STRUCT_ALIGN); \
__PMF_SVC_DESCS_START__ = .; \ __PMF_SVC_DESCS_START__ = .; \
@ -100,7 +109,8 @@
CPU_OPS \ CPU_OPS \
GOT \ GOT \
BASE_XLAT_TABLE_RO \ BASE_XLAT_TABLE_RO \
EL3_LP_DESCS EL3_LP_DESCS \
SPMD_LP_DESCS
/* /*
* .data must be placed at a lower address than the stacks if the stack * .data must be placed at a lower address than the stacks if the stack

63
include/services/el3_spmd_logical_sp.h

@ -0,0 +1,63 @@
/*
* Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef EL3_SPMD_LOGICAL_SP_H
#define EL3_SPMD_LOGICAL_SP_H
#include <common/bl_common.h>
#include <lib/cassert.h>
#include <services/ffa_svc.h>
/*******************************************************************************
* Structure definition, typedefs & constants for the SPMD Logical Partitions.
******************************************************************************/
/* Prototype for SPMD logical partition initializing function. */
typedef int32_t (*ffa_spmd_lp_init_t)(void);
/* SPMD Logical Partition Descriptor. */
struct spmd_lp_desc {
ffa_spmd_lp_init_t init;
uint16_t sp_id;
uint32_t properties;
uint32_t uuid[4]; /* Little Endian. */
const char *debug_name;
};
/* Convenience macro to declare a SPMD logical partition descriptor. */
#define DECLARE_SPMD_LOGICAL_PARTITION(_name, _init, _sp_id, _uuid, _properties) \
static const struct spmd_lp_desc __partition_desc_ ## _name \
__section(".spmd_lp_descs") __used = { \
.debug_name = #_name, \
.init = (_init), \
.sp_id = (_sp_id), \
.uuid = _uuid, \
.properties = (_properties), \
}
IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_START__, SPMD_LP_DESCS_START);
IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_END__, SPMD_LP_DESCS_END);
#define SPMD_LP_DESCS_COUNT ((SPMD_LP_DESCS_END - SPMD_LP_DESCS_START) \
/ sizeof(struct spmd_lp_desc))
CASSERT(sizeof(struct spmd_lp_desc) == 40, assert_spmd_lp_desc_size_mismatch);
/*
* Reserve 63 IDs for SPMD Logical Partitions. Currently, 0xFFC0 to 0xFFFE
* is reserved.
*/
#define SPMD_LP_ID_END (SPMD_DIRECT_MSG_ENDPOINT_ID - 1)
#define SPMD_LP_ID_START (SPMD_LP_ID_END - 62)
static inline bool is_spmd_lp_id(unsigned int id)
{
return (id >= SPMD_LP_ID_START && id <= SPMD_LP_ID_END);
}
void spmd_logical_sp_set_spmc_initialized(void);
void spmc_logical_sp_set_spmc_failure(void);
int32_t spmd_logical_sp_init(void);
#endif /* EL3_SPMD_LOGICAL_SP_H */

3
make_helpers/defaults.mk

@ -508,3 +508,6 @@ DRTM_SUPPORT := 0
# Check platform if cache management operations should be performed. # Check platform if cache management operations should be performed.
# Disabled by default. # Disabled by default.
CONDITIONAL_CMO := 0 CONDITIONAL_CMO := 0
# By default, disable SPMD Logical partitions
ENABLE_SPMD_LP := 0

3
services/std_svc/spmd/spmd.mk

@ -15,7 +15,8 @@ endif
SPMD_SOURCES += $(addprefix services/std_svc/spmd/, \ SPMD_SOURCES += $(addprefix services/std_svc/spmd/, \
${ARCH}/spmd_helpers.S \ ${ARCH}/spmd_helpers.S \
spmd_pm.c \ spmd_pm.c \
spmd_main.c) spmd_main.c \
spmd_logical_sp.c)
# Let the top-level Makefile know that we intend to include a BL32 image # Let the top-level Makefile know that we intend to include a BL32 image
NEED_BL32 := yes NEED_BL32 := yes

165
services/std_svc/spmd/spmd_logical_sp.c

@ -0,0 +1,165 @@
/*
* Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <common/debug.h>
#include <services/el3_spmd_logical_sp.h>
#include <services/ffa_svc.h>
#if ENABLE_SPMD_LP
static bool is_spmd_lp_inited;
static bool is_spmc_inited;
/*
* Helper function to obtain the array storing the EL3
* SPMD Logical Partition descriptors.
*/
static struct spmd_lp_desc *get_spmd_el3_lp_array(void)
{
return (struct spmd_lp_desc *) SPMD_LP_DESCS_START;
}
/*******************************************************************************
* Validate any logical partition descriptors before we initialize.
* Initialization of said partitions will be taken care of during SPMD boot.
******************************************************************************/
static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array)
{
/* Check the array bounds are valid. */
assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START);
/* If no SPMD logical partitions are implemented then simply bail out. */
if (SPMD_LP_DESCS_COUNT == 0U) {
return -1;
}
for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) {
struct spmd_lp_desc *lp_desc = &lp_array[index];
/* Validate our logical partition descriptors. */
if (lp_desc == NULL) {
ERROR("Invalid SPMD Logical SP Descriptor\n");
return -EINVAL;
}
/*
* Ensure the ID follows the convention to indicate it resides
* in the secure world.
*/
if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
ERROR("Invalid SPMD Logical SP ID (0x%x)\n",
lp_desc->sp_id);
return -EINVAL;
}
/* Ensure SPMD logical partition is in valid range. */
if (!is_spmd_lp_id(lp_desc->sp_id)) {
ERROR("Invalid SPMD Logical Partition ID (0x%x)\n",
lp_desc->sp_id);
return -EINVAL;
}
/* Ensure the UUID is not the NULL UUID. */
if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 &&
lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) {
ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n",
lp_desc->sp_id);
return -EINVAL;
}
/* Ensure init function callback is registered. */
if (lp_desc->init == NULL) {
ERROR("Missing init function for Logical SP(0x%x)\n",
lp_desc->sp_id);
return -EINVAL;
}
/* Ensure that SPMD LP only supports sending direct requests. */
if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) {
ERROR("Invalid SPMD logical partition properties (0x%x)\n",
lp_desc->properties);
return -EINVAL;
}
/* Ensure that all partition IDs are unique. */
for (uint32_t inner_idx = index + 1;
inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) {
if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n",
lp_desc->sp_id);
return -EINVAL;
}
}
}
return 0;
}
#endif
/*
* Initialize SPMD logical partitions. This function assumes that it is called
* only after the SPMC has successfully initialized.
*/
int32_t spmd_logical_sp_init(void)
{
#if ENABLE_SPMD_LP
int32_t rc = 0;
struct spmd_lp_desc *spmd_lp_descs;
if (is_spmd_lp_inited == true) {
return 0;
}
if (is_spmc_inited == false) {
return -1;
}
spmd_lp_descs = get_spmd_el3_lp_array();
/* Perform initial validation of the SPMD Logical Partitions. */
rc = el3_spmd_sp_desc_validate(spmd_lp_descs);
if (rc != 0) {
ERROR("Logical SPMD Partition validation failed!\n");
return rc;
}
VERBOSE("SPMD Logical Secure Partition init start.\n");
for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) {
rc = spmd_lp_descs[i].init();
if (rc != 0) {
ERROR("SPMD Logical SP (0x%x) failed to initialize\n",
spmd_lp_descs[i].sp_id);
return rc;
}
VERBOSE("SPMD Logical SP (0x%x) Initialized\n",
spmd_lp_descs[i].sp_id);
}
INFO("SPMD Logical Secure Partition init completed.\n");
if (rc == 0) {
is_spmd_lp_inited = true;
}
return rc;
#else
return 0;
#endif
}
void spmd_logical_sp_set_spmc_initialized(void)
{
#if ENABLE_SPMD_LP
is_spmc_inited = true;
#endif
}
void spmd_logical_sp_set_spmc_failure(void)
{
#if ENABLE_SPMD_LP
is_spmc_inited = false;
#endif
}

7
services/std_svc/spmd/spmd_main.c

@ -27,6 +27,7 @@
#include <plat/common/common_def.h> #include <plat/common/common_def.h>
#include <plat/common/platform.h> #include <plat/common/platform.h>
#include <platform_def.h> #include <platform_def.h>
#include <services/el3_spmd_logical_sp.h>
#include <services/ffa_svc.h> #include <services/ffa_svc.h>
#include <services/spmc_svc.h> #include <services/spmc_svc.h>
#include <services/spmd_svc.h> #include <services/spmd_svc.h>
@ -190,6 +191,12 @@ static int32_t spmd_init(void)
VERBOSE("SPM Core init end.\n"); VERBOSE("SPM Core init end.\n");
spmd_logical_sp_set_spmc_initialized();
rc = spmd_logical_sp_init();
if (rc != 0) {
WARN("SPMD Logical partitions failed init.\n");
}
return 1; return 1;
} }

Loading…
Cancel
Save