mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-28 08:08:45 +00:00
feat(spmc/lsp): add logical partition framework
Introduce a framework to support running logical partitions alongside the SPMC in EL3 as per the v1.1 FF-A spec. The DECLARE_LOGICAL_PARTITION macro has been added to simplify the process to define a Logical Partition. The partitions themselves are statically allocated with the descriptors placed in RO memory. It is assumed that the MAX_EL3_LP_DESCS_COUNT will be defined by the platform. Change-Id: I1c2523e0ad2d9c5d36aeeef6b8bcb1e80db7c443 Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
This commit is contained in:
parent
6dc0f1f329
commit
7affa25cad
8 changed files with 276 additions and 8 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
|
* Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -81,6 +81,10 @@
|
||||||
#define __RODATA_END__ Load$$__RODATA_EPILOGUE__$$Base
|
#define __RODATA_END__ Load$$__RODATA_EPILOGUE__$$Base
|
||||||
#define __RT_SVC_DESCS_START__ Load$$__RT_SVC_DESCS__$$Base
|
#define __RT_SVC_DESCS_START__ Load$$__RT_SVC_DESCS__$$Base
|
||||||
#define __RT_SVC_DESCS_END__ Load$$__RT_SVC_DESCS__$$Limit
|
#define __RT_SVC_DESCS_END__ Load$$__RT_SVC_DESCS__$$Limit
|
||||||
|
#if SPMC_AT_EL3
|
||||||
|
#define __EL3_LP_DESCS_START__ Load$$__EL3_LP_DESCS__$$Base
|
||||||
|
#define __EL3_LP_DESCS_END__ Load$$__EL3_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
|
||||||
|
|
|
@ -39,6 +39,16 @@
|
||||||
KEEP(*(rt_svc_descs)) \
|
KEEP(*(rt_svc_descs)) \
|
||||||
__RT_SVC_DESCS_END__ = .;
|
__RT_SVC_DESCS_END__ = .;
|
||||||
|
|
||||||
|
#if SPMC_AT_EL3
|
||||||
|
#define EL3_LP_DESCS \
|
||||||
|
. = ALIGN(STRUCT_ALIGN); \
|
||||||
|
__EL3_LP_DESCS_START__ = .; \
|
||||||
|
KEEP(*(el3_lp_descs)) \
|
||||||
|
__EL3_LP_DESCS_END__ = .;
|
||||||
|
#else
|
||||||
|
#define EL3_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__ = .; \
|
||||||
|
@ -89,7 +99,8 @@
|
||||||
PARSER_LIB_DESCS \
|
PARSER_LIB_DESCS \
|
||||||
CPU_OPS \
|
CPU_OPS \
|
||||||
GOT \
|
GOT \
|
||||||
BASE_XLAT_TABLE_RO
|
BASE_XLAT_TABLE_RO \
|
||||||
|
EL3_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
|
||||||
|
|
60
include/services/el3_spmc_logical_sp.h
Normal file
60
include/services/el3_spmc_logical_sp.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef EL3_SP_H
|
||||||
|
#define EL3_SP_H
|
||||||
|
|
||||||
|
#include <common/bl_common.h>
|
||||||
|
#include <lib/cassert.h>
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Structure definition, typedefs & constants for the Logical SPs.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
typedef uint64_t (*direct_msg_handler)(uint32_t smc_fid, bool secure_origin,
|
||||||
|
uint64_t x1, uint64_t x2, uint64_t x3,
|
||||||
|
uint64_t x4, void *cookie, void *handle,
|
||||||
|
uint64_t flags);
|
||||||
|
|
||||||
|
/* Prototype for logical partition initializing function. */
|
||||||
|
typedef int32_t (*ffa_partition_init_t)(void);
|
||||||
|
|
||||||
|
/* Logical Partition Descriptor. */
|
||||||
|
struct el3_lp_desc {
|
||||||
|
ffa_partition_init_t init;
|
||||||
|
uint16_t sp_id;
|
||||||
|
uint32_t properties;
|
||||||
|
uint32_t uuid[4]; /* Little Endian. */
|
||||||
|
direct_msg_handler direct_req;
|
||||||
|
const char *debug_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Convenience macro to declare a logical partition descriptor. */
|
||||||
|
#define DECLARE_LOGICAL_PARTITION(_name, _init, _sp_id, _uuid, _properties, \
|
||||||
|
_direct_req) \
|
||||||
|
static const struct el3_lp_desc __partition_desc_ ## _name \
|
||||||
|
__section("el3_lp_descs") __used = { \
|
||||||
|
.debug_name = #_name, \
|
||||||
|
.init = (_init), \
|
||||||
|
.sp_id = (_sp_id), \
|
||||||
|
.uuid = _uuid, \
|
||||||
|
.properties = (_properties), \
|
||||||
|
.direct_req = (_direct_req), \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Function & variable prototypes.
|
||||||
|
******************************************************************************/
|
||||||
|
int el3_sp_desc_validate(void);
|
||||||
|
uintptr_t handle_el3_sp(uint32_t smc_fid, void *cookie, void *handle,
|
||||||
|
unsigned int flags);
|
||||||
|
IMPORT_SYM(uintptr_t, __EL3_LP_DESCS_START__, EL3_LP_DESCS_START);
|
||||||
|
IMPORT_SYM(uintptr_t, __EL3_LP_DESCS_END__, EL3_LP_DESCS_END);
|
||||||
|
|
||||||
|
#define EL3_LP_DESCS_COUNT ((EL3_LP_DESCS_END - EL3_LP_DESCS_START) \
|
||||||
|
/ sizeof(struct el3_lp_desc))
|
||||||
|
|
||||||
|
#endif /* EL3_SP_H */
|
|
@ -163,6 +163,13 @@
|
||||||
#define FFA_NOTIFICATION_INFO_GET_SMC64 \
|
#define FFA_NOTIFICATION_INFO_GET_SMC64 \
|
||||||
FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
|
FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FF-A partition properties values.
|
||||||
|
*/
|
||||||
|
#define FFA_PARTITION_DIRECT_REQ_RECV U(1 << 0)
|
||||||
|
#define FFA_PARTITION_DIRECT_REQ_SEND U(1 << 1)
|
||||||
|
#define FFA_PARTITION_INDIRECT_MSG U(1 << 2)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reserve a special value for traffic targeted to the Hypervisor or SPM.
|
* Reserve a special value for traffic targeted to the Hypervisor or SPM.
|
||||||
*/
|
*/
|
||||||
|
|
107
services/std_svc/spm/el3_spmc/logical_sp.c
Normal file
107
services/std_svc/spm/el3_spmc/logical_sp.c
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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_spmc_logical_sp.h>
|
||||||
|
#include <services/ffa_svc.h>
|
||||||
|
#include "spmc.h"
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Validate any logical partition descriptors before we initialise.
|
||||||
|
* Initialization of said partitions will be taken care of during SPMC boot.
|
||||||
|
******************************************************************************/
|
||||||
|
int el3_sp_desc_validate(void)
|
||||||
|
{
|
||||||
|
struct el3_lp_desc *lp_array;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assert the number of descriptors is less than maximum allowed.
|
||||||
|
* This constant should be define on a per platform basis.
|
||||||
|
*/
|
||||||
|
assert(EL3_LP_DESCS_COUNT <= MAX_EL3_LP_DESCS_COUNT);
|
||||||
|
|
||||||
|
/* Check the array bounds are valid. */
|
||||||
|
assert(EL3_LP_DESCS_END >= EL3_LP_DESCS_START);
|
||||||
|
|
||||||
|
/* If no logical partitions are implemented then simply bail out. */
|
||||||
|
if (EL3_LP_DESCS_COUNT == 0U) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lp_array = get_el3_lp_array();
|
||||||
|
|
||||||
|
for (unsigned int index = 0; index < EL3_LP_DESCS_COUNT; index++) {
|
||||||
|
struct el3_lp_desc *lp_desc = &lp_array[index];
|
||||||
|
|
||||||
|
/* Validate our logical partition descriptors. */
|
||||||
|
if (lp_desc == NULL) {
|
||||||
|
ERROR("Invalid Logical SP Descriptor\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure the ID follows the convention to indidate it resides
|
||||||
|
* in the secure world.
|
||||||
|
*/
|
||||||
|
if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
|
||||||
|
ERROR("Invalid Logical SP ID (0x%x)\n",
|
||||||
|
lp_desc->sp_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure we don't conflict with the SPMC partition ID. */
|
||||||
|
if (lp_desc->sp_id == FFA_SPMC_ID) {
|
||||||
|
ERROR("Logical SP ID clashes with SPMC 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 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 LP only supports receiving direct requests. */
|
||||||
|
if (lp_desc->properties &
|
||||||
|
~(FFA_PARTITION_DIRECT_REQ_RECV)) {
|
||||||
|
ERROR("Invalid partition properties (0x%x)\n",
|
||||||
|
lp_desc->properties);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure direct request function callback is registered. */
|
||||||
|
if (lp_desc->direct_req == NULL) {
|
||||||
|
ERROR("No Direct Req handler for Logical SP (0x%x)\n",
|
||||||
|
lp_desc->sp_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure that all partition IDs are unique. */
|
||||||
|
for (unsigned int inner_idx = index + 1;
|
||||||
|
inner_idx < EL3_LP_DESCS_COUNT; inner_idx++) {
|
||||||
|
if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
|
||||||
|
ERROR("Duplicate SP ID Detected (0x%x)\n",
|
||||||
|
lp_desc->sp_id);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <lib/psci/psci.h>
|
#include <lib/psci/psci.h>
|
||||||
#include <lib/spinlock.h>
|
#include <lib/spinlock.h>
|
||||||
|
#include <services/el3_spmc_logical_sp.h>
|
||||||
#include "spm_common.h"
|
#include "spm_common.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -184,4 +185,10 @@ uint64_t spmc_ffa_error_return(void *handle, int error_code);
|
||||||
*/
|
*/
|
||||||
bool is_ffa_secure_id_valid(uint16_t partition_id);
|
bool is_ffa_secure_id_valid(uint16_t partition_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to obtain the array storing the EL3
|
||||||
|
* Logical Partition descriptors.
|
||||||
|
*/
|
||||||
|
struct el3_lp_desc *get_el3_lp_array(void);
|
||||||
|
|
||||||
#endif /* SPMC_H */
|
#endif /* SPMC_H */
|
||||||
|
|
|
@ -10,8 +10,8 @@ endif
|
||||||
|
|
||||||
SPMC_SOURCES := $(addprefix services/std_svc/spm/el3_spmc/, \
|
SPMC_SOURCES := $(addprefix services/std_svc/spm/el3_spmc/, \
|
||||||
spmc_main.c \
|
spmc_main.c \
|
||||||
spmc_setup.c)
|
spmc_setup.c \
|
||||||
|
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
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
#include <plat/common/platform.h>
|
#include <plat/common/platform.h>
|
||||||
|
#include <services/el3_spmc_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>
|
||||||
|
@ -40,6 +41,15 @@ static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT];
|
||||||
*/
|
*/
|
||||||
static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT];
|
static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function to obtain the array storing the EL3
|
||||||
|
* Logical Partition descriptors.
|
||||||
|
*/
|
||||||
|
struct el3_lp_desc *get_el3_lp_array(void)
|
||||||
|
{
|
||||||
|
return (struct el3_lp_desc *) EL3_LP_DESCS_START;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function to obtain the descriptor of the last SP to whom control was
|
* Helper function to obtain the descriptor of the last SP to whom control was
|
||||||
* handed to on this physical cpu. Currently, we assume there is only one SP.
|
* handed to on this physical cpu. Currently, we assume there is only one SP.
|
||||||
|
@ -105,6 +115,8 @@ uint64_t spmc_ffa_error_return(void *handle, int error_code)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
bool is_ffa_secure_id_valid(uint16_t partition_id)
|
bool is_ffa_secure_id_valid(uint16_t partition_id)
|
||||||
{
|
{
|
||||||
|
struct el3_lp_desc *el3_lp_descs = get_el3_lp_array();
|
||||||
|
|
||||||
/* Ensure the ID is not the invalid partition ID. */
|
/* Ensure the ID is not the invalid partition ID. */
|
||||||
if (partition_id == INV_SP_ID) {
|
if (partition_id == INV_SP_ID) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -133,12 +145,22 @@ bool is_ffa_secure_id_valid(uint16_t partition_id)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure we don't clash with any Logical SP's. */
|
||||||
|
for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
|
||||||
|
if (el3_lp_descs[i].sp_id == partition_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* This function either forwards the request to the other world or returns
|
* This function either forwards the request to the other world or returns
|
||||||
* with an ERET depending on the source of the call.
|
* with an ERET depending on the source of the call.
|
||||||
|
* We can assume that the destination is for an entity at a lower exception
|
||||||
|
* level as any messages destined for a logical SP resident in EL3 will have
|
||||||
|
* already been taken care of by the SPMC before entering this function.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
static uint64_t spmc_smc_return(uint32_t smc_fid,
|
static uint64_t spmc_smc_return(uint32_t smc_fid,
|
||||||
bool secure_origin,
|
bool secure_origin,
|
||||||
|
@ -210,6 +232,7 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
||||||
uint64_t flags)
|
uint64_t flags)
|
||||||
{
|
{
|
||||||
uint16_t dst_id = ffa_endpoint_destination(x1);
|
uint16_t dst_id = ffa_endpoint_destination(x1);
|
||||||
|
struct el3_lp_desc *el3_lp_descs;
|
||||||
struct secure_partition_desc *sp;
|
struct secure_partition_desc *sp;
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
|
|
||||||
|
@ -219,11 +242,22 @@ static uint64_t direct_req_smc_handler(uint32_t smc_fid,
|
||||||
FFA_ERROR_INVALID_PARAMETER);
|
FFA_ERROR_INVALID_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
el3_lp_descs = get_el3_lp_array();
|
||||||
|
|
||||||
|
/* Check if the request is destined for a Logical Partition. */
|
||||||
|
for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
|
||||||
|
if (el3_lp_descs[i].sp_id == dst_id) {
|
||||||
|
return el3_lp_descs[i].direct_req(
|
||||||
|
smc_fid, secure_origin, x1, x2, x3, x4,
|
||||||
|
cookie, handle, flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If called by the secure world it is an invalid call since a
|
* If the request was not targeted to a LSP and from the secure world
|
||||||
* SP cannot call into the Normal world and there is no other SP to call
|
* then it is invalid since a SP cannot call into the Normal world and
|
||||||
* into. If there are other SPs in future then the partition runtime
|
* there is no other SP to call into. If there are other SPs in future
|
||||||
* model would need to be validated as well.
|
* then the partition runtime model would need to be validated as well.
|
||||||
*/
|
*/
|
||||||
if (secure_origin) {
|
if (secure_origin) {
|
||||||
VERBOSE("Direct request not supported to the Normal World.\n");
|
VERBOSE("Direct request not supported to the Normal World.\n");
|
||||||
|
@ -621,6 +655,37 @@ static int find_and_prepare_sp_context(void)
|
||||||
* This function takes an SP context pointer and performs a synchronous entry
|
* This function takes an SP context pointer and performs a synchronous entry
|
||||||
* into it.
|
* into it.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
static int32_t logical_sp_init(void)
|
||||||
|
{
|
||||||
|
int32_t rc = 0;
|
||||||
|
struct el3_lp_desc *el3_lp_descs;
|
||||||
|
|
||||||
|
/* Perform initial validation of the Logical Partitions. */
|
||||||
|
rc = el3_sp_desc_validate();
|
||||||
|
if (rc != 0) {
|
||||||
|
ERROR("Logical Partition validation failed!\n");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
el3_lp_descs = get_el3_lp_array();
|
||||||
|
|
||||||
|
INFO("Logical Secure Partition init start.\n");
|
||||||
|
for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
|
||||||
|
rc = el3_lp_descs[i].init();
|
||||||
|
if (rc != 0) {
|
||||||
|
ERROR("Logical SP (0x%x) Failed to Initialize\n",
|
||||||
|
el3_lp_descs[i].sp_id);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
VERBOSE("Logical SP (0x%x) Initialized\n",
|
||||||
|
el3_lp_descs[i].sp_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO("Logical Secure Partition init completed.\n");
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec)
|
uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec)
|
||||||
{
|
{
|
||||||
uint64_t rc;
|
uint64_t rc;
|
||||||
|
@ -725,6 +790,13 @@ int32_t spmc_setup(void)
|
||||||
initalize_sp_descs();
|
initalize_sp_descs();
|
||||||
initalize_ns_ep_descs();
|
initalize_ns_ep_descs();
|
||||||
|
|
||||||
|
/* Setup logical SPs. */
|
||||||
|
ret = logical_sp_init();
|
||||||
|
if (ret != 0) {
|
||||||
|
ERROR("Failed to initialize Logical Partitions.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform physical SP setup. */
|
/* Perform physical SP setup. */
|
||||||
|
|
||||||
/* Disable MMU at EL1 (initialized by BL2) */
|
/* Disable MMU at EL1 (initialized by BL2) */
|
||||||
|
|
Loading…
Add table
Reference in a new issue