Merge pull request #798 from douglas-raillard-arm/dr/fix_std_smc_after_suspend
Abort preempted TSP STD SMC after PSCI CPU suspend
This commit is contained in:
commit
cef7b3ce8b
|
@ -180,6 +180,7 @@ func tsp_vector_table
|
|||
b tsp_sel1_intr_entry
|
||||
b tsp_system_off_entry
|
||||
b tsp_system_reset_entry
|
||||
b tsp_abort_std_smc_entry
|
||||
endfunc tsp_vector_table
|
||||
|
||||
/*---------------------------------------------
|
||||
|
@ -441,3 +442,30 @@ func tsp_std_smc_entry
|
|||
/* Should never reach here */
|
||||
no_ret plat_panic_handler
|
||||
endfunc tsp_std_smc_entry
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
* This entrypoint is used by the TSPD to abort a pre-empted Standard
|
||||
* SMC. It could be on behalf of non-secure world or because a CPU
|
||||
* suspend/CPU off request needs to abort the preempted SMC.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
func tsp_abort_std_smc_entry
|
||||
|
||||
/*
|
||||
* Exceptions masking is already done by the TSPD when entering this
|
||||
* hook so there is no need to do it here.
|
||||
*/
|
||||
|
||||
/* Reset the stack used by the pre-empted SMC */
|
||||
bl plat_set_my_stack
|
||||
|
||||
/*
|
||||
* Allow some cleanup such as releasing locks.
|
||||
*/
|
||||
bl tsp_abort_smc_handler
|
||||
|
||||
restore_args_call_smc
|
||||
|
||||
/* Should never reach here */
|
||||
bl plat_panic_handler
|
||||
endfunc tsp_abort_std_smc_entry
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -416,3 +416,20 @@ tsp_args_t *tsp_smc_handler(uint64_t func,
|
|||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TSP smc abort handler. This function is called when aborting a preemtped
|
||||
* standard SMC request. It should cleanup all resources owned by the SMC
|
||||
* handler such as locks or dynamically allocated memory so following SMC
|
||||
* request are executed in a clean environment.
|
||||
******************************************************************************/
|
||||
tsp_args_t *tsp_abort_smc_handler(uint64_t func,
|
||||
uint64_t arg1,
|
||||
uint64_t arg2,
|
||||
uint64_t arg3,
|
||||
uint64_t arg4,
|
||||
uint64_t arg5,
|
||||
uint64_t arg6,
|
||||
uint64_t arg7)
|
||||
{
|
||||
return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -41,6 +41,7 @@
|
|||
#define TSP_SUSPEND_DONE 0xf2000003
|
||||
#define TSP_RESUME_DONE 0xf2000004
|
||||
#define TSP_PREEMPTED 0xf2000005
|
||||
#define TSP_ABORT_DONE 0xf2000007
|
||||
#define TSP_SYSTEM_OFF_DONE 0xf2000008
|
||||
#define TSP_SYSTEM_RESET_DONE 0xf2000009
|
||||
|
||||
|
@ -80,11 +81,18 @@
|
|||
|
||||
/* SMC function ID to request a previously preempted std smc */
|
||||
#define TSP_FID_RESUME TSP_STD_FID(0x3000)
|
||||
/*
|
||||
* SMC function ID to request abortion of a previously preempted std smc. A
|
||||
* fast SMC is used so that the TSP abort handler does not have to be
|
||||
* reentrant.
|
||||
*/
|
||||
#define TSP_FID_ABORT TSP_FAST_FID(0x3001)
|
||||
|
||||
/*
|
||||
* Total number of function IDs implemented for services offered to NS clients.
|
||||
* The function IDs are defined above
|
||||
*/
|
||||
#define TSP_NUM_FID 0x4
|
||||
#define TSP_NUM_FID 0x5
|
||||
|
||||
/* TSP implementation version numbers */
|
||||
#define TSP_VERSION_MAJOR 0x0 /* Major version */
|
||||
|
@ -117,6 +125,7 @@ typedef struct tsp_vectors {
|
|||
tsp_vector_isn_t sel1_intr_entry;
|
||||
tsp_vector_isn_t system_off_entry;
|
||||
tsp_vector_isn_t system_reset_entry;
|
||||
tsp_vector_isn_t abort_std_smc_entry;
|
||||
} tsp_vectors_t;
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -32,7 +32,9 @@
|
|||
#include <assert.h>
|
||||
#include <bl_common.h>
|
||||
#include <context_mgmt.h>
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
#include <tsp.h>
|
||||
#include "tspd_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -129,3 +131,31 @@ void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret)
|
|||
/* Should never reach here */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function takes an SP context pointer and abort any preempted SMC
|
||||
* request.
|
||||
* Return 1 if there was a preempted SMC request, 0 otherwise.
|
||||
******************************************************************************/
|
||||
int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx)
|
||||
{
|
||||
if (!get_std_smc_active_flag(tsp_ctx->state))
|
||||
return 0;
|
||||
|
||||
/* Abort any preempted SMC request */
|
||||
clr_std_smc_active_flag(tsp_ctx->state);
|
||||
|
||||
/*
|
||||
* Arrange for an entry into the test secure payload. It will
|
||||
* be returned via TSP_ABORT_DONE case in tspd_smc_handler.
|
||||
*/
|
||||
cm_set_elr_el3(SECURE,
|
||||
(uint64_t) &tsp_vectors->abort_std_smc_entry);
|
||||
uint64_t rc = tspd_synchronous_sp_entry(tsp_ctx);
|
||||
|
||||
if (rc != 0)
|
||||
panic();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -459,6 +459,11 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
|||
*/
|
||||
tspd_synchronous_sp_exit(tsp_ctx, x1);
|
||||
#endif
|
||||
/*
|
||||
* This function ID is used only by the SP to indicate it has finished
|
||||
* aborting a preempted Standard SMC request.
|
||||
*/
|
||||
case TSP_ABORT_DONE:
|
||||
|
||||
/*
|
||||
* These function IDs are used only by the SP to indicate it has
|
||||
|
@ -596,6 +601,26 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
|
|||
}
|
||||
|
||||
break;
|
||||
/*
|
||||
* Request from the non-secure world to abort a preempted Standard SMC
|
||||
* call.
|
||||
*/
|
||||
case TSP_FID_ABORT:
|
||||
/* ABORT should only be invoked by normal world */
|
||||
if (!ns) {
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Abort the preempted SMC request */
|
||||
if (!tspd_abort_preempted_smc(tsp_ctx))
|
||||
/*
|
||||
* If there was no preempted SMC to abort, return
|
||||
* SMC_UNK.
|
||||
*/
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
|
||||
break;
|
||||
|
||||
/*
|
||||
* Request from non secure world to resume the preempted
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -58,6 +58,12 @@ static int32_t tspd_cpu_off_handler(uint64_t unused)
|
|||
assert(tsp_vectors);
|
||||
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
|
||||
|
||||
/*
|
||||
* Abort any preempted SMC request before overwriting the SECURE
|
||||
* context.
|
||||
*/
|
||||
tspd_abort_preempted_smc(tsp_ctx);
|
||||
|
||||
/* Program the entry point and enter the TSP */
|
||||
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
|
||||
rc = tspd_synchronous_sp_entry(tsp_ctx);
|
||||
|
@ -75,7 +81,7 @@ static int32_t tspd_cpu_off_handler(uint64_t unused)
|
|||
*/
|
||||
set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -91,6 +97,12 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
|
|||
assert(tsp_vectors);
|
||||
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
|
||||
|
||||
/*
|
||||
* Abort any preempted SMC request before overwriting the SECURE
|
||||
* context.
|
||||
*/
|
||||
tspd_abort_preempted_smc(tsp_ctx);
|
||||
|
||||
/* Program the entry point and enter the TSP */
|
||||
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
|
||||
rc = tspd_synchronous_sp_entry(tsp_ctx);
|
||||
|
@ -99,7 +111,7 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
|
|||
* Read the response from the TSP. A non-zero return means that
|
||||
* something went wrong while communicating with the TSP.
|
||||
*/
|
||||
if (rc != 0)
|
||||
if (rc)
|
||||
panic();
|
||||
|
||||
/* Update its context to reflect the state the TSP is in */
|
||||
|
@ -108,7 +120,7 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
|
|||
|
||||
/*******************************************************************************
|
||||
* This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits
|
||||
* before passing control back to the Secure Monitor. Entry in S-El1 is done
|
||||
* before passing control back to the Secure Monitor. Entry in S-EL1 is done
|
||||
* after initialising minimal architectural state that guarantees safe
|
||||
* execution.
|
||||
******************************************************************************/
|
||||
|
@ -205,6 +217,12 @@ static void tspd_system_off(void)
|
|||
assert(tsp_vectors);
|
||||
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
|
||||
|
||||
/*
|
||||
* Abort any preempted SMC request before overwriting the SECURE
|
||||
* context.
|
||||
*/
|
||||
tspd_abort_preempted_smc(tsp_ctx);
|
||||
|
||||
/* Program the entry point */
|
||||
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
|
||||
|
||||
|
@ -225,11 +243,19 @@ static void tspd_system_reset(void)
|
|||
assert(tsp_vectors);
|
||||
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON);
|
||||
|
||||
/*
|
||||
* Abort any preempted SMC request before overwriting the SECURE
|
||||
* context.
|
||||
*/
|
||||
tspd_abort_preempted_smc(tsp_ctx);
|
||||
|
||||
/* Program the entry point */
|
||||
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry);
|
||||
|
||||
/* Enter the TSP. We do not care about the return value because we
|
||||
* must continue the reset anyway */
|
||||
/*
|
||||
* Enter the TSP. We do not care about the return value because we
|
||||
* must continue the reset anyway
|
||||
*/
|
||||
tspd_synchronous_sp_entry(tsp_ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
|
@ -242,6 +242,7 @@ void tspd_init_tsp_ep_state(struct entry_point_info *tsp_ep,
|
|||
uint32_t rw,
|
||||
uint64_t pc,
|
||||
tsp_context_t *tsp_ctx);
|
||||
int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx);
|
||||
|
||||
extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
|
||||
extern struct tsp_vectors *tsp_vectors;
|
||||
|
|
Loading…
Reference in New Issue