Merge "feat(SPMD): route secure interrupts to SPMC" into integration
This commit is contained in:
commit
a127b99d5a
|
@ -139,6 +139,7 @@
|
||||||
#define FFA_NOTIFICATION_INFO_GET \
|
#define FFA_NOTIFICATION_INFO_GET \
|
||||||
FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_INFO_GET)
|
FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_INFO_GET)
|
||||||
#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
|
#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET)
|
||||||
|
#define FFA_NORMAL_WORLD_RESUME FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME)
|
||||||
|
|
||||||
/* FFA SMC64 FIDs */
|
/* FFA SMC64 FIDs */
|
||||||
#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR)
|
#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <arch_helpers.h>
|
#include <arch_helpers.h>
|
||||||
#include <arch/aarch64/arch_features.h>
|
#include <arch/aarch64/arch_features.h>
|
||||||
#include <bl31/bl31.h>
|
#include <bl31/bl31.h>
|
||||||
|
#include <bl31/interrupt_mgmt.h>
|
||||||
#include <common/debug.h>
|
#include <common/debug.h>
|
||||||
#include <common/runtime_svc.h>
|
#include <common/runtime_svc.h>
|
||||||
#include <lib/el3_runtime/context_mgmt.h>
|
#include <lib/el3_runtime/context_mgmt.h>
|
||||||
|
@ -169,6 +170,62 @@ static int32_t spmd_init(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* spmd_secure_interrupt_handler
|
||||||
|
* Enter the SPMC for further handling of the secure interrupt by the SPMC
|
||||||
|
* itself or a Secure Partition.
|
||||||
|
******************************************************************************/
|
||||||
|
static uint64_t spmd_secure_interrupt_handler(uint32_t id,
|
||||||
|
uint32_t flags,
|
||||||
|
void *handle,
|
||||||
|
void *cookie)
|
||||||
|
{
|
||||||
|
spmd_spm_core_context_t *ctx = spmd_get_context();
|
||||||
|
gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
|
||||||
|
unsigned int linear_id = plat_my_core_pos();
|
||||||
|
int64_t rc;
|
||||||
|
|
||||||
|
/* Sanity check the security state when the exception was generated */
|
||||||
|
assert(get_interrupt_src_ss(flags) == NON_SECURE);
|
||||||
|
|
||||||
|
/* Sanity check the pointer to this cpu's context */
|
||||||
|
assert(handle == cm_get_context(NON_SECURE));
|
||||||
|
|
||||||
|
/* Save the non-secure context before entering SPMC */
|
||||||
|
cm_el1_sysregs_context_save(NON_SECURE);
|
||||||
|
#if SPMD_SPM_AT_SEL2
|
||||||
|
cm_el2_sysregs_context_save(NON_SECURE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Convey the event to the SPMC through the FFA_INTERRUPT interface. */
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_INTERRUPT);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X1, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X2, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X3, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X4, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X5, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X6, 0);
|
||||||
|
write_ctx_reg(gpregs, CTX_GPREG_X7, 0);
|
||||||
|
|
||||||
|
/* Mark current core as handling a secure interrupt. */
|
||||||
|
ctx->secure_interrupt_ongoing = true;
|
||||||
|
|
||||||
|
rc = spmd_spm_core_sync_entry(ctx);
|
||||||
|
if (rc != 0ULL) {
|
||||||
|
ERROR("%s failed (%llu) on CPU%u\n", __func__, rc, linear_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->secure_interrupt_ongoing = false;
|
||||||
|
|
||||||
|
cm_el1_sysregs_context_restore(NON_SECURE);
|
||||||
|
#if SPMD_SPM_AT_SEL2
|
||||||
|
cm_el2_sysregs_context_restore(NON_SECURE);
|
||||||
|
#endif
|
||||||
|
cm_set_next_eret_context(NON_SECURE);
|
||||||
|
|
||||||
|
SMC_RET0(&ctx->cpu_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Loads SPMC manifest and inits SPMC.
|
* Loads SPMC manifest and inits SPMC.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -176,7 +233,7 @@ static int spmd_spmc_init(void *pm_addr)
|
||||||
{
|
{
|
||||||
cpu_context_t *cpu_ctx;
|
cpu_context_t *cpu_ctx;
|
||||||
unsigned int core_id;
|
unsigned int core_id;
|
||||||
uint32_t ep_attr;
|
uint32_t ep_attr, flags;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Load the SPM Core manifest */
|
/* Load the SPM Core manifest */
|
||||||
|
@ -292,6 +349,19 @@ static int spmd_spmc_init(void *pm_addr)
|
||||||
|
|
||||||
INFO("SPM Core setup done.\n");
|
INFO("SPM Core setup done.\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register an interrupt handler routing secure interrupts to SPMD
|
||||||
|
* while the NWd is running.
|
||||||
|
*/
|
||||||
|
flags = 0;
|
||||||
|
set_interrupt_rm_flag(flags, NON_SECURE);
|
||||||
|
rc = register_interrupt_type_handler(INTR_TYPE_S_EL1,
|
||||||
|
spmd_secure_interrupt_handler,
|
||||||
|
flags);
|
||||||
|
if (rc != 0) {
|
||||||
|
panic();
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +666,7 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
|
||||||
|
|
||||||
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
|
case FFA_MSG_SEND_DIRECT_RESP_SMC32:
|
||||||
if (secure_origin && spmd_is_spmc_message(x1)) {
|
if (secure_origin && spmd_is_spmc_message(x1)) {
|
||||||
spmd_spm_core_sync_exit(0);
|
spmd_spm_core_sync_exit(0ULL);
|
||||||
} else {
|
} else {
|
||||||
/* Forward direct message to the other world */
|
/* Forward direct message to the other world */
|
||||||
return spmd_smc_forward(smc_fid, secure_origin,
|
return spmd_smc_forward(smc_fid, secure_origin,
|
||||||
|
@ -668,7 +738,7 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
|
||||||
* SPM Core initialised successfully.
|
* SPM Core initialised successfully.
|
||||||
*/
|
*/
|
||||||
if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
|
if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
|
||||||
spmd_spm_core_sync_exit(0);
|
spmd_spm_core_sync_exit(0ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fall through to forward the call to the other world */
|
/* Fall through to forward the call to the other world */
|
||||||
|
@ -684,6 +754,14 @@ uint64_t spmd_smc_handler(uint32_t smc_fid,
|
||||||
x1, x2, x3, x4, handle);
|
x1, x2, x3, x4, handle);
|
||||||
break; /* not reached */
|
break; /* not reached */
|
||||||
|
|
||||||
|
case FFA_NORMAL_WORLD_RESUME:
|
||||||
|
if (secure_origin && ctx->secure_interrupt_ongoing) {
|
||||||
|
spmd_spm_core_sync_exit(0ULL);
|
||||||
|
} else {
|
||||||
|
return spmd_ffa_error_return(handle, FFA_ERROR_DENIED);
|
||||||
|
}
|
||||||
|
break; /* Not reached */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
|
WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
|
||||||
return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
|
return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
|
||||||
|
|
|
@ -50,6 +50,7 @@ typedef struct spmd_spm_core_context {
|
||||||
uint64_t c_rt_ctx;
|
uint64_t c_rt_ctx;
|
||||||
cpu_context_t cpu_ctx;
|
cpu_context_t cpu_ctx;
|
||||||
spmc_state_t state;
|
spmc_state_t state;
|
||||||
|
bool secure_interrupt_ongoing;
|
||||||
} spmd_spm_core_context_t;
|
} spmd_spm_core_context_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue