From 4d4ceb598c168c86d74ec535868e7bfc3d18cee4 Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Wed, 20 Jun 2018 12:05:02 +0100 Subject: [PATCH] SPM: Allow entering the SP without needing a SMC It may be needed to enter the Secure Partition through other means than an MM_COMMUNICATE SMC. This patch enables this behaviour by extracting the necessary code from mm_communicate() and allowing other parts of the code to use it. Change-Id: I59f6638d22d9c9d0baff0984f39d056298a8dc8e Signed-off-by: Antonio Nino Diaz --- include/services/spm_svc.h | 3 ++ services/std_svc/spm/spm_main.c | 49 +++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h index 8f872c39..0200992c 100644 --- a/include/services/spm_svc.h +++ b/include/services/spm_svc.h @@ -74,6 +74,9 @@ uint64_t spm_smc_handler(uint32_t smc_fid, void *handle, uint64_t flags); +/* Helper to enter a Secure Partition */ +uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3); + #endif /* __ASSEMBLY__ */ #endif /* __SPM_SVC_H__ */ diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c index f63f9c4f..585707dc 100644 --- a/services/std_svc/spm/spm_main.c +++ b/services/std_svc/spm/spm_main.c @@ -180,6 +180,35 @@ int32_t spm_setup(void) return 0; } +/******************************************************************************* + * Function to perform a call to a Secure Partition. + ******************************************************************************/ +uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint64_t rc; + sp_context_t *sp_ptr = &sp_ctx; + + /* Wait until the Secure Partition is idle and set it to busy. */ + sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY); + + /* Set values for registers on SP entry */ + cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx); + + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3); + + /* Jump to the Secure Partition. */ + rc = spm_sp_synchronous_entry(sp_ptr); + + /* Flag Secure Partition as idle. */ + assert(sp_ptr->state == SP_STATE_BUSY); + sp_state_set(sp_ptr, SP_STATE_IDLE); + + return rc; +} + /******************************************************************************* * MM_COMMUNICATE handler ******************************************************************************/ @@ -188,7 +217,6 @@ static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, uint64_t comm_size_address, void *handle) { uint64_t rc; - sp_context_t *ctx = &sp_ctx; /* Cookie. Reserved for future use. It must be zero. */ if (mm_cookie != 0U) { @@ -208,23 +236,8 @@ static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, /* Save the Normal world context */ cm_el1_sysregs_context_save(NON_SECURE); - /* Wait until the Secure Partition is idle and set it to busy. */ - sp_state_wait_switch(ctx, SP_STATE_IDLE, SP_STATE_BUSY); - - /* Set values for registers on SP entry */ - cpu_context_t *cpu_ctx = &(ctx->cpu_ctx); - - write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); - write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, comm_buffer_address); - write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, comm_size_address); - write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, plat_my_core_pos()); - - /* Jump to the Secure Partition. */ - rc = spm_sp_synchronous_entry(ctx); - - /* Flag Secure Partition as idle. */ - assert(ctx->state == SP_STATE_BUSY); - sp_state_set(ctx, SP_STATE_IDLE); + rc = spm_sp_call(smc_fid, comm_buffer_address, comm_size_address, + plat_my_core_pos()); /* Restore non-secure state */ cm_el1_sysregs_context_restore(NON_SECURE); -- 2.30.2