Browse Source

feat(rme): add RMM dispatcher (RMMD)

This patch introduces the RMM dispatcher into BL31. This
will be the mechanism that will enable communication to
take place between the Realm and non-secure world. Currently
gives the capability for granules to be
transitioned from non-secure type to realm and vice versa.

Signed-off-by: Zelalem Aweke <zelalem.aweke@arm.com>
Signed-off-by: Subhasish Ghosh <subhasish.ghosh@arm.com>
Change-Id: I1fdc99a4bdd42bc14911aa0c6954b131de309511
pull/1981/head
Zelalem Aweke 3 years ago
parent
commit
77c2775323
  1. 4
      bl31/bl31.mk
  2. 2
      include/arch/aarch64/arch.h
  3. 40
      include/services/gtsi_svc.h
  4. 64
      include/services/rmi_svc.h
  5. 34
      include/services/rmmd_svc.h
  6. 26
      services/arm_arch_svc/arm_arch_svc_setup.c
  7. 73
      services/std_svc/rmmd/aarch64/rmmd_helpers.S
  8. 13
      services/std_svc/rmmd/rmmd.mk
  9. 33
      services/std_svc/rmmd/rmmd_initial_context.h
  10. 341
      services/std_svc/rmmd/rmmd_main.c
  11. 64
      services/std_svc/rmmd/rmmd_private.h
  12. 12
      services/std_svc/std_svc_setup.c

4
bl31/bl31.mk

@ -111,6 +111,10 @@ ifeq ($(SMC_PCI_SUPPORT),1)
BL31_SOURCES += services/std_svc/pci_svc.c
endif
ifeq (${ENABLE_RME},1)
BL31_SOURCES += ${RMMD_SOURCES}
endif
BL31_LINKERFILE := bl31/bl31.ld.S
# Flag used to indicate if Crash reporting via console should be included

2
include/arch/aarch64/arch.h

@ -448,6 +448,7 @@
#define SCR_ECVEN_BIT (UL(1) << 28)
#define SCR_FGTEN_BIT (UL(1) << 27)
#define SCR_ATA_BIT (UL(1) << 26)
#define SCR_EnSCXT_BIT (UL(1) << 25)
#define SCR_FIEN_BIT (UL(1) << 21)
#define SCR_EEL2_BIT (UL(1) << 18)
#define SCR_API_BIT (UL(1) << 17)
@ -609,6 +610,7 @@
#define SPSR_M_MASK U(0x1)
#define SPSR_M_AARCH64 U(0x0)
#define SPSR_M_AARCH32 U(0x1)
#define SPSR_M_EL2H U(0x9)
#define SPSR_EL_SHIFT U(2)
#define SPSR_EL_WIDTH U(2)

40
include/services/gtsi_svc.h

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef GTSI_SVC_H
#define GTSI_SVC_H
/* GTSI error codes. */
#define GTSI_SUCCESS 0
#define GTSI_ERROR_NOT_SUPPORTED -1
#define GTSI_ERROR_INVALID_ADDRESS -2
#define GTSI_ERROR_INVALID_PAS -3
/* The macros below are used to identify GTSI calls from the SMC function ID */
#define GTSI_FNUM_MIN_VALUE U(0x100)
#define GTSI_FNUM_MAX_VALUE U(0x101)
#define is_gtsi_fid(fid) __extension__ ({ \
__typeof__(fid) _fid = (fid); \
((GET_SMC_NUM(_fid) >= GTSI_FNUM_MIN_VALUE) && \
(GET_SMC_NUM(_fid) <= GTSI_FNUM_MAX_VALUE)); })
/* Get GTSI fastcall std FID from function number */
#define GTSI_FID(smc_cc, func_num) \
((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
((smc_cc) << FUNCID_CC_SHIFT) | \
(OEN_STD_START << FUNCID_OEN_SHIFT) | \
((func_num) << FUNCID_NUM_SHIFT))
#define GRAN_TRANS_TO_REALM_FNUM U(0x100)
#define GRAN_TRANS_TO_NS_FNUM U(0x101)
#define SMC_ASC_MARK_REALM GTSI_FID(SMC_64, GRAN_TRANS_TO_REALM_FNUM)
#define SMC_ASC_MARK_NONSECURE GTSI_FID(SMC_64, GRAN_TRANS_TO_NS_FNUM)
#define GRAN_TRANS_RET_BAD_ADDR -2
#define GRAN_TRANS_RET_BAD_PAS -3
#endif /* GTSI_SVC_H */

64
include/services/rmi_svc.h

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RMI_SVC_H
#define RMI_SVC_H
#include <lib/smccc.h>
#include <lib/utils_def.h>
/* RMI error codes. */
#define RMI_SUCCESS 0
#define RMI_ERROR_NOT_SUPPORTED -1
#define RMI_ERROR_INVALID_ADDRESS -2
#define RMI_ERROR_INVALID_PAS -3
/* The macros below are used to identify RMI calls from the SMC function ID */
#define RMI_FNUM_MIN_VALUE U(0x00)
#define RMI_FNUM_MAX_VALUE U(0x20)
#define is_rmi_fid(fid) __extension__ ({ \
__typeof__(fid) _fid = (fid); \
((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) && \
(GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) && \
(GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \
(GET_SMC_CC(_fid) == SMC_64) && \
(GET_SMC_OEN(_fid) == OEN_ARM_START) && \
((_fid & 0x00FE0000) == 0U)); })
/* Get RMI fastcall std FID from function number */
#define RMI_FID(smc_cc, func_num) \
((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \
((smc_cc) << FUNCID_CC_SHIFT) | \
(OEN_ARM_START << FUNCID_OEN_SHIFT) | \
((func_num) << FUNCID_NUM_SHIFT))
/*
* SMC_RMM_INIT_COMPLETE is the only function in the RMI that originates from
* the Realm world and is handled by the RMMD. The remaining functions are
* always invoked by the Normal world, forwarded by RMMD and handled by the
* RMM
*/
#define RMI_FNUM_REQ_COMPLETE U(0x10)
#define RMI_FNUM_VERSION_REQ U(0x00)
#define RMI_FNUM_GRAN_NS_REALM U(0x01)
#define RMI_FNUM_GRAN_REALM_NS U(0x10)
/* RMI SMC64 FIDs handled by the RMMD */
#define RMI_RMM_REQ_COMPLETE RMI_FID(SMC_64, RMI_FNUM_REQ_COMPLETE)
#define RMI_RMM_REQ_VERSION RMI_FID(SMC_64, RMI_FNUM_VERSION_REQ)
#define RMI_RMM_GRANULE_DELEGATE RMI_FID(SMC_64, RMI_FNUM_GRAN_NS_REALM)
#define RMI_RMM_GRANULE_UNDELEGATE RMI_FID(SMC_64, RMI_FNUM_GRAN_REALM_NS)
#define RMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
#define RMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
/* Reserve a special value for MBZ parameters. */
#define RMI_PARAM_MBZ U(0x0)
#endif /* RMI_SVC_H */

34
include/services/rmmd_svc.h

@ -0,0 +1,34 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RMMD_SVC_H
#define RMMD_SVC_H
#ifndef __ASSEMBLER__
#include <stdint.h>
int rmmd_setup(void);
uint64_t rmmd_rmi_handler(uint32_t smc_fid,
uint64_t x1,
uint64_t x2,
uint64_t x3,
uint64_t x4,
void *cookie,
void *handle,
uint64_t flags);
uint64_t rmmd_gtsi_handler(uint32_t smc_fid,
uint64_t x1,
uint64_t x2,
uint64_t x3,
uint64_t x4,
void *cookie,
void *handle,
uint64_t flags);
#endif /* __ASSEMBLER__ */
#endif /* RMMD_SVC_H */

26
services/arm_arch_svc/arm_arch_svc_setup.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -11,9 +11,19 @@
#include <lib/cpus/wa_cve_2018_3639.h>
#include <lib/smccc.h>
#include <services/arm_arch_svc.h>
#include <services/rmi_svc.h>
#include <services/rmmd_svc.h>
#include <smccc_helpers.h>
#include <plat/common/platform.h>
#if ENABLE_RME
/* Setup Arm architecture Services */
static int32_t arm_arch_svc_setup(void)
{
return rmmd_setup();
}
#endif
static int32_t smccc_version(void)
{
return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION);
@ -133,6 +143,16 @@ static uintptr_t arm_arch_svc_smc_handler(uint32_t smc_fid,
SMC_RET0(handle);
#endif
default:
#if ENABLE_RME
/*
* RMI functions are allocated from the Arch service range. Call
* the RMM dispatcher to handle RMI calls.
*/
if (is_rmi_fid(smc_fid)) {
return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie,
handle, flags);
}
#endif
WARN("Unimplemented Arm Architecture Service Call: 0x%x \n",
smc_fid);
SMC_RET1(handle, SMC_UNK);
@ -145,6 +165,10 @@ DECLARE_RT_SVC(
OEN_ARM_START,
OEN_ARM_END,
SMC_TYPE_FAST,
#if ENABLE_RME
arm_arch_svc_setup,
#else
NULL,
#endif
arm_arch_svc_smc_handler
);

73
services/std_svc/rmmd/aarch64/rmmd_helpers.S

@ -0,0 +1,73 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "../rmmd_private.h"
#include <asm_macros.S>
.global rmmd_rmm_enter
.global rmmd_rmm_exit
/* ---------------------------------------------------------------------
* This function is called with SP_EL0 as stack. Here we stash our EL3
* callee-saved registers on to the stack as a part of saving the C
* runtime and enter the secure payload.
* 'x0' contains a pointer to the memory where the address of the C
* runtime context is to be saved.
* ---------------------------------------------------------------------
*/
func rmmd_rmm_enter
/* Make space for the registers that we're going to save */
mov x3, sp
str x3, [x0, #0]
sub sp, sp, #RMMD_C_RT_CTX_SIZE
/* Save callee-saved registers on to the stack */
stp x19, x20, [sp, #RMMD_C_RT_CTX_X19]
stp x21, x22, [sp, #RMMD_C_RT_CTX_X21]
stp x23, x24, [sp, #RMMD_C_RT_CTX_X23]
stp x25, x26, [sp, #RMMD_C_RT_CTX_X25]
stp x27, x28, [sp, #RMMD_C_RT_CTX_X27]
stp x29, x30, [sp, #RMMD_C_RT_CTX_X29]
/* ---------------------------------------------------------------------
* Everything is setup now. el3_exit() will use the secure context to
* restore to the general purpose and EL3 system registers to ERET
* into the secure payload.
* ---------------------------------------------------------------------
*/
b el3_exit
endfunc rmmd_rmm_enter
/* ---------------------------------------------------------------------
* This function is called with 'x0' pointing to a C runtime context.
* It restores the saved registers and jumps to that runtime with 'x0'
* as the new SP register. This destroys the C runtime context that had
* been built on the stack below the saved context by the caller. Later
* the second parameter 'x1' is passed as a return value to the caller.
* ---------------------------------------------------------------------
*/
func rmmd_rmm_exit
/* Restore the previous stack */
mov sp, x0
/* Restore callee-saved registers on to the stack */
ldp x19, x20, [x0, #(RMMD_C_RT_CTX_X19 - RMMD_C_RT_CTX_SIZE)]
ldp x21, x22, [x0, #(RMMD_C_RT_CTX_X21 - RMMD_C_RT_CTX_SIZE)]
ldp x23, x24, [x0, #(RMMD_C_RT_CTX_X23 - RMMD_C_RT_CTX_SIZE)]
ldp x25, x26, [x0, #(RMMD_C_RT_CTX_X25 - RMMD_C_RT_CTX_SIZE)]
ldp x27, x28, [x0, #(RMMD_C_RT_CTX_X27 - RMMD_C_RT_CTX_SIZE)]
ldp x29, x30, [x0, #(RMMD_C_RT_CTX_X29 - RMMD_C_RT_CTX_SIZE)]
/* ---------------------------------------------------------------------
* This should take us back to the instruction after the call to the
* last rmmd_rmm_enter().* Place the second parameter to x0
* so that the caller will see it as a return value from the original
* entry call.
* ---------------------------------------------------------------------
*/
mov x0, x1
ret
endfunc rmmd_rmm_exit

13
services/std_svc/rmmd/rmmd.mk

@ -0,0 +1,13 @@
#
# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifneq (${ARCH},aarch64)
$(error "Error: RMMD is only supported on aarch64.")
endif
RMMD_SOURCES += $(addprefix services/std_svc/rmmd/, \
${ARCH}/rmmd_helpers.S \
rmmd_main.c)

33
services/std_svc/rmmd/rmmd_initial_context.h

@ -0,0 +1,33 @@
/*
* Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RMMD_INITIAL_CONTEXT_H
#define RMMD_INITIAL_CONTEXT_H
#include <arch.h>
/*
* SPSR_EL2
* M=0x9 (0b1001 EL2h)
* M[4]=0
* DAIF=0xF Exceptions masked on entry.
* BTYPE=0 BTI not yet supported.
* SSBS=0 Not yet supported.
* IL=0 Not an illegal exception return.
* SS=0 Not single stepping.
* PAN=1 RMM shouldn't access realm memory.
* UAO=0
* DIT=0
* TCO=0
* NZCV=0
*/
#define REALM_SPSR_EL2 ( \
SPSR_M_EL2H | \
(0xF << SPSR_DAIF_SHIFT) | \
SPSR_PAN_BIT \
)
#endif /* RMMD_INITIAL_CONTEXT_H */

341
services/std_svc/rmmd/rmmd_main.c

@ -0,0 +1,341 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <arch_helpers.h>
#include <arch_features.h>
#include <bl31/bl31.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <context.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/el3_runtime/pubsub.h>
#include <lib/gpt/gpt_defs.h>
#include <lib/spinlock.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/common_def.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <services/gtsi_svc.h>
#include <services/rmi_svc.h>
#include <services/rmmd_svc.h>
#include <smccc_helpers.h>
#include "rmmd_initial_context.h"
#include "rmmd_private.h"
/*******************************************************************************
* RMM context information.
******************************************************************************/
rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT];
/*******************************************************************************
* RMM entry point information. Discovered on the primary core and reused
* on secondary cores.
******************************************************************************/
static entry_point_info_t *rmm_ep_info;
/*******************************************************************************
* Static function declaration.
******************************************************************************/
static int32_t rmm_init(void);
static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
uint32_t dst_sec_state, uint64_t x1,
uint64_t x2, uint64_t x3, uint64_t x4,
void *handle);
/*******************************************************************************
* This function takes an RMM context pointer and performs a synchronous entry
* into it.
******************************************************************************/
uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx)
{
uint64_t rc;
assert(rmm_ctx != NULL);
cm_set_context(&(rmm_ctx->cpu_ctx), REALM);
/* Save the current el1/el2 context before loading realm context. */
cm_el1_sysregs_context_save(NON_SECURE);
cm_el2_sysregs_context_save(NON_SECURE);
/* Restore the realm context assigned above */
cm_el1_sysregs_context_restore(REALM);
cm_el2_sysregs_context_restore(REALM);
cm_set_next_eret_context(REALM);
/* Enter RMM */
rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx);
/* Save realm context */
cm_el1_sysregs_context_save(REALM);
cm_el2_sysregs_context_save(REALM);
/* Restore the el1/el2 context again. */
cm_el1_sysregs_context_restore(NON_SECURE);
cm_el2_sysregs_context_restore(NON_SECURE);
return rc;
}
/*******************************************************************************
* This function returns to the place where rmmd_rmm_sync_entry() was
* called originally.
******************************************************************************/
__dead2 void rmmd_rmm_sync_exit(uint64_t rc)
{
rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
/* Get context of the RMM in use by this CPU. */
assert(cm_get_context(REALM) == &(ctx->cpu_ctx));
/*
* The RMMD must have initiated the original request through a
* synchronous entry into RMM. Jump back to the original C runtime
* context with the value of rc in x0;
*/
rmmd_rmm_exit(ctx->c_rt_ctx, rc);
panic();
}
static void rmm_el2_context_init(el2_sysregs_t *regs)
{
regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2;
regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1;
}
/*******************************************************************************
* Jump to the RMM for the first time.
******************************************************************************/
static int32_t rmm_init(void)
{
uint64_t rc;
rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
INFO("RMM init start.\n");
ctx->state = RMM_STATE_RESET;
/* Initialize RMM EL2 context. */
rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
rc = rmmd_rmm_sync_entry(ctx);
if (rc != 0ULL) {
ERROR("RMM initialisation failed 0x%llx\n", rc);
panic();
}
ctx->state = RMM_STATE_IDLE;
INFO("RMM init end.\n");
return 1;
}
/*******************************************************************************
* Load and read RMM manifest, setup RMM.
******************************************************************************/
int rmmd_setup(void)
{
uint32_t ep_attr;
unsigned int linear_id = plat_my_core_pos();
rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id];
/* Make sure RME is supported. */
assert(get_armv9_2_feat_rme_support() != 0U);
rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM);
if (rmm_ep_info == NULL) {
WARN("No RMM image provided by BL2 boot loader, Booting "
"device without RMM initialization. SMCs destined for "
"RMM will return SMC_UNK\n");
return -ENOENT;
}
/* Under no circumstances will this parameter be 0 */
assert(rmm_ep_info->pc == RMM_BASE);
/* Initialise an entrypoint to set up the CPU context */
ep_attr = EP_REALM;
if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) {
ep_attr |= EP_EE_BIG;
}
SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr);
rmm_ep_info->spsr = SPSR_64(MODE_EL2,
MODE_SP_ELX,
DISABLE_ALL_EXCEPTIONS);
/* Initialise RMM context with this entry point information */
cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info);
INFO("RMM setup done.\n");
/* Register init function for deferred init. */
bl31_register_rmm_init(&rmm_init);
return 0;
}
/*******************************************************************************
* Forward SMC to the other security state
******************************************************************************/
static uint64_t rmmd_smc_forward(uint32_t smc_fid, uint32_t src_sec_state,
uint32_t dst_sec_state, uint64_t x1,
uint64_t x2, uint64_t x3, uint64_t x4,
void *handle)
{
/* Save incoming security state */
cm_el1_sysregs_context_save(src_sec_state);
cm_el2_sysregs_context_save(src_sec_state);
/* Restore outgoing security state */
cm_el1_sysregs_context_restore(dst_sec_state);
cm_el2_sysregs_context_restore(dst_sec_state);
cm_set_next_eret_context(dst_sec_state);
SMC_RET8(cm_get_context(dst_sec_state), smc_fid, x1, x2, x3, x4,
SMC_GET_GP(handle, CTX_GPREG_X5),
SMC_GET_GP(handle, CTX_GPREG_X6),
SMC_GET_GP(handle, CTX_GPREG_X7));
}
/*******************************************************************************
* This function handles all SMCs in the range reserved for RMI. Each call is
* either forwarded to the other security state or handled by the RMM dispatcher
******************************************************************************/
uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
uint64_t x3, uint64_t x4, void *cookie,
void *handle, uint64_t flags)
{
rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()];
uint32_t src_sec_state;
/* Determine which security state this SMC originated from */
src_sec_state = caller_sec_state(flags);
/* RMI must not be invoked by the Secure world */
if (src_sec_state == SMC_FROM_SECURE) {
WARN("RMM: RMI invoked by secure world.\n");
SMC_RET1(handle, SMC_UNK);
}
/*
* Forward an RMI call from the Normal world to the Realm world as it
* is.
*/
if (src_sec_state == SMC_FROM_NON_SECURE) {
VERBOSE("RMM: RMI call from non-secure world.\n");
return rmmd_smc_forward(smc_fid, NON_SECURE, REALM,
x1, x2, x3, x4, handle);
}
assert(src_sec_state == SMC_FROM_REALM);
switch (smc_fid) {
case RMI_RMM_REQ_COMPLETE:
if (ctx->state == RMM_STATE_RESET) {
VERBOSE("RMM: running rmmd_rmm_sync_exit\n");
rmmd_rmm_sync_exit(x1);
}
return rmmd_smc_forward(x1, REALM, NON_SECURE,
x2, x3, x4, 0, handle);
default:
WARN("RMM: Unsupported RMM call 0x%08x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}
/*******************************************************************************
* This cpu has been turned on. Enter RMM to initialise R-EL2. Entry into RMM
* is done after initialising minimal architectural state that guarantees safe
* execution.
******************************************************************************/
static void *rmmd_cpu_on_finish_handler(const void *arg)
{
int32_t rc;
uint32_t linear_id = plat_my_core_pos();
rmmd_rmm_context_t *ctx = &rmm_context[linear_id];
ctx->state = RMM_STATE_RESET;
/* Initialise RMM context with this entry point information */
cm_setup_context(&ctx->cpu_ctx, rmm_ep_info);
/* Initialize RMM EL2 context. */
rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx);
rc = rmmd_rmm_sync_entry(ctx);
if (rc != 0) {
ERROR("RMM initialisation failed (%d) on CPU%d\n", rc,
linear_id);
panic();
}
ctx->state = RMM_STATE_IDLE;
return NULL;
}
/* Subscribe to PSCI CPU on to initialize RMM on secondary */
SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler);
static int gtsi_transition_granule(uint64_t pa,
unsigned int src_sec_state,
unsigned int target_pas)
{
int ret;
ret = gpt_transition_pas(pa, src_sec_state, target_pas);
/* Convert TF-A error codes into GTSI error codes */
if (ret == -EINVAL) {
ret = GRAN_TRANS_RET_BAD_ADDR;
} else if (ret == -EPERM) {
ret = GRAN_TRANS_RET_BAD_PAS;
}
return ret;
}
/*******************************************************************************
* This function handles all SMCs in the range reserved for GTF.
******************************************************************************/
uint64_t rmmd_gtsi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2,
uint64_t x3, uint64_t x4, void *cookie,
void *handle, uint64_t flags)
{
uint32_t src_sec_state;
/* Determine which security state this SMC originated from */
src_sec_state = caller_sec_state(flags);
if (src_sec_state != SMC_FROM_REALM) {
WARN("RMM: GTF call originated from secure or normal world\n");
SMC_RET1(handle, SMC_UNK);
}
switch (smc_fid) {
case SMC_ASC_MARK_REALM:
SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
GPI_REALM));
break;
case SMC_ASC_MARK_NONSECURE:
SMC_RET1(handle, gtsi_transition_granule(x1, SMC_FROM_REALM,
GPI_NS));
break;
default:
WARN("RMM: Unsupported GTF call 0x%08x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
}

64
services/std_svc/rmmd/rmmd_private.h

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RMMD_PRIVATE_H
#define RMMD_PRIVATE_H
#include <context.h>
/*******************************************************************************
* Constants that allow assembler code to preserve callee-saved registers of the
* C runtime context while performing a security state switch.
******************************************************************************/
#define RMMD_C_RT_CTX_X19 0x0
#define RMMD_C_RT_CTX_X20 0x8
#define RMMD_C_RT_CTX_X21 0x10
#define RMMD_C_RT_CTX_X22 0x18
#define RMMD_C_RT_CTX_X23 0x20
#define RMMD_C_RT_CTX_X24 0x28
#define RMMD_C_RT_CTX_X25 0x30
#define RMMD_C_RT_CTX_X26 0x38
#define RMMD_C_RT_CTX_X27 0x40
#define RMMD_C_RT_CTX_X28 0x48
#define RMMD_C_RT_CTX_X29 0x50
#define RMMD_C_RT_CTX_X30 0x58
#define RMMD_C_RT_CTX_SIZE 0x60
#define RMMD_C_RT_CTX_ENTRIES (RMMD_C_RT_CTX_SIZE >> DWORD_SHIFT)
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <services/rmi_svc.h>
typedef enum rmm_state {
RMM_STATE_RESET = 0,
RMM_STATE_IDLE
} rmm_state_t;
/*
* Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of
* the RMM at R-EL2.
*/
typedef struct rmmd_rmm_context {
uint64_t c_rt_ctx;
cpu_context_t cpu_ctx;
rmm_state_t state;
} rmmd_rmm_context_t;
/* Functions used to enter/exit the RMM synchronously */
uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *ctx);
__dead2 void rmmd_rmm_sync_exit(uint64_t rc);
/* Assembly helpers */
uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx);
void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret);
/* Reference to PM ops for the RMMD */
extern const spd_pm_ops_t rmmd_pm;
#endif /* __ASSEMBLER__ */
#endif /* RMMD_PRIVATE_H */

12
services/std_svc/std_svc_setup.c

@ -13,7 +13,9 @@
#include <lib/pmf/pmf.h>
#include <lib/psci/psci.h>
#include <lib/runtime_instr.h>
#include <services/gtsi_svc.h>
#include <services/pci_svc.h>
#include <services/rmmd_svc.h>
#include <services/sdei.h>
#include <services/spm_mm_svc.h>
#include <services/spmd_svc.h>
@ -158,6 +160,16 @@ static uintptr_t std_svc_smc_handler(uint32_t smc_fid,
flags);
}
#endif
#if ENABLE_RME
/*
* Granule transition service interface functions (GTSI) are allocated
* from the Std service range. Call the RMM dispatcher to handle calls.
*/
if (is_gtsi_fid(smc_fid)) {
return rmmd_gtsi_handler(smc_fid, x1, x2, x3, x4, cookie,
handle, flags);
}
#endif
#if SMC_PCI_SUPPORT
if (is_pci_fid(smc_fid)) {

Loading…
Cancel
Save