From 14fcc6e14e2d9c1c7c91753fbcb04727a1dc667f Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Fri, 15 Jun 2018 16:21:01 +0100 Subject: [PATCH] SPM: Refactor entry and exit of the SP Only use synchronous calls to enter the Secure Partition in order to simplify the SMC handling code. Change-Id: Ia501a045585ee0836b9151141ad3bd11d0971be2 Signed-off-by: Antonio Nino Diaz --- services/std_svc/spm/spm_main.c | 96 ++++++++++++++---------------- services/std_svc/spm/spm_private.h | 2 +- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c index be76dc2dc..f63f9c4f5 100644 --- a/services/std_svc/spm/spm_main.c +++ b/services/std_svc/spm/spm_main.c @@ -81,10 +81,13 @@ int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) } /******************************************************************************* - * This function takes an SP context pointer and prepares the CPU to enter. + * This function takes an SP context pointer and performs a synchronous entry + * into it. ******************************************************************************/ -static void spm_sp_prepare_enter(sp_context_t *sp_ctx) +static uint64_t spm_sp_synchronous_entry(sp_context_t *sp_ctx) { + uint64_t rc; + assert(sp_ctx != NULL); /* Assign the context of the SP to this CPU */ @@ -97,15 +100,32 @@ static void spm_sp_prepare_enter(sp_context_t *sp_ctx) /* Invalidate TLBs at EL1. */ tlbivmalle1(); dsbish(); + + /* Enter Secure Partition */ + rc = spm_secure_partition_enter(&sp_ctx->c_rt_ctx); + + /* Save secure state */ + cm_el1_sysregs_context_save(SECURE); + + return rc; } /******************************************************************************* - * Enter SP after preparing it with spm_sp_prepare_enter(). + * This function returns to the place where spm_sp_synchronous_entry() was + * called originally. ******************************************************************************/ -static uint64_t spm_sp_enter(sp_context_t *sp_ctx) +__dead2 static void spm_sp_synchronous_exit(uint64_t rc) { - /* Enter Secure Partition */ - return spm_secure_partition_enter(&sp_ctx->c_rt_ctx); + sp_context_t *ctx = &sp_ctx; + + /* + * The SPM must have initiated the original request through a + * synchronous entry into the secure partition. Jump back to the + * original C runtime context with the value of rc in x0; + */ + spm_secure_partition_exit(ctx->c_rt_ctx, rc); + + panic(); } /******************************************************************************* @@ -113,7 +133,7 @@ static uint64_t spm_sp_enter(sp_context_t *sp_ctx) ******************************************************************************/ static int32_t spm_init(void) { - uint64_t rc = 0; + uint64_t rc; sp_context_t *ctx; INFO("Secure Partition init...\n"); @@ -122,8 +142,7 @@ static int32_t spm_init(void) ctx->state = SP_STATE_RESET; - spm_sp_prepare_enter(ctx); - rc |= spm_sp_enter(ctx); + rc = spm_sp_synchronous_entry(ctx); assert(rc == 0); ctx->state = SP_STATE_IDLE; @@ -168,6 +187,7 @@ static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, uint64_t comm_buffer_address, 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. */ @@ -188,59 +208,29 @@ 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. */ + /* 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. */ - spm_sp_prepare_enter(ctx); + rc = spm_sp_synchronous_entry(ctx); - SMC_RET4(&(ctx->cpu_ctx), smc_fid, comm_buffer_address, - comm_size_address, plat_my_core_pos()); -} - -/******************************************************************************* - * SP_EVENT_COMPLETE_AARCH64 handler - ******************************************************************************/ -static uint64_t sp_event_complete(uint64_t x1) -{ - sp_context_t *ctx = &sp_ctx; - - /* Save secure state */ - cm_el1_sysregs_context_save(SECURE); - - if (ctx->state == SP_STATE_RESET) { - /* - * SPM reports completion. The SPM must have initiated the - * original request through a synchronous entry into the secure - * partition. Jump back to the original C runtime context. - */ - spm_secure_partition_exit(ctx->c_rt_ctx, x1); - - /* spm_secure_partition_exit doesn't return */ - } - - /* - * This is the result from the Secure partition of an earlier request. - * Copy the result into the non-secure context and return to the - * non-secure state. - */ - - /* Mark Secure Partition as idle */ + /* Flag Secure Partition as idle. */ assert(ctx->state == SP_STATE_BUSY); - sp_state_set(ctx, SP_STATE_IDLE); - /* Get a reference to the non-secure context */ - cpu_context_t *ns_cpu_context = cm_get_context(NON_SECURE); - - assert(ns_cpu_context != NULL); - /* Restore non-secure state */ cm_el1_sysregs_context_restore(NON_SECURE); cm_set_next_eret_context(NON_SECURE); - /* Return to non-secure world */ - SMC_RET1(ns_cpu_context, x1); + SMC_RET1(handle, rc); } /******************************************************************************* @@ -275,7 +265,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid, SMC_RET1(handle, SPM_VERSION_COMPILED); case SP_EVENT_COMPLETE_AARCH64: - return sp_event_complete(x1); + spm_sp_synchronous_exit(x1); case SP_MEMORY_ATTRIBUTES_GET_AARCH64: INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); @@ -305,6 +295,8 @@ uint64_t spm_smc_handler(uint32_t smc_fid, /* Handle SMCs from Non-secure world. */ + assert(handle == cm_get_context(NON_SECURE)); + switch (smc_fid) { case MM_VERSION_AARCH32: diff --git a/services/std_svc/spm/spm_private.h b/services/std_svc/spm/spm_private.h index 64d8cf89e..f094739fa 100644 --- a/services/std_svc/spm/spm_private.h +++ b/services/std_svc/spm/spm_private.h @@ -35,7 +35,7 @@ #include #include -typedef enum secure_partition_state { +typedef enum sp_state { SP_STATE_RESET = 0, SP_STATE_IDLE, SP_STATE_BUSY