Commit cef7b3ce authored by davidcunado-arm's avatar davidcunado-arm Committed by GitHub
Browse files

Merge pull request #798 from douglas-raillard-arm/dr/fix_std_smc_after_suspend

Abort preempted TSP STD SMC after PSCI CPU suspend
parents 153e5eb8 3df6012a
...@@ -180,6 +180,7 @@ func tsp_vector_table ...@@ -180,6 +180,7 @@ func tsp_vector_table
b tsp_sel1_intr_entry b tsp_sel1_intr_entry
b tsp_system_off_entry b tsp_system_off_entry
b tsp_system_reset_entry b tsp_system_reset_entry
b tsp_abort_std_smc_entry
endfunc tsp_vector_table endfunc tsp_vector_table
/*--------------------------------------------- /*---------------------------------------------
...@@ -441,3 +442,30 @@ func tsp_std_smc_entry ...@@ -441,3 +442,30 @@ func tsp_std_smc_entry
/* Should never reach here */ /* Should never reach here */
no_ret plat_panic_handler no_ret plat_panic_handler
endfunc tsp_std_smc_entry 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
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -416,3 +416,20 @@ tsp_args_t *tsp_smc_handler(uint64_t func, ...@@ -416,3 +416,20 @@ tsp_args_t *tsp_smc_handler(uint64_t func,
0, 0, 0, 0); 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);
}
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define TSP_SUSPEND_DONE 0xf2000003 #define TSP_SUSPEND_DONE 0xf2000003
#define TSP_RESUME_DONE 0xf2000004 #define TSP_RESUME_DONE 0xf2000004
#define TSP_PREEMPTED 0xf2000005 #define TSP_PREEMPTED 0xf2000005
#define TSP_ABORT_DONE 0xf2000007
#define TSP_SYSTEM_OFF_DONE 0xf2000008 #define TSP_SYSTEM_OFF_DONE 0xf2000008
#define TSP_SYSTEM_RESET_DONE 0xf2000009 #define TSP_SYSTEM_RESET_DONE 0xf2000009
...@@ -80,11 +81,18 @@ ...@@ -80,11 +81,18 @@
/* SMC function ID to request a previously preempted std smc */ /* SMC function ID to request a previously preempted std smc */
#define TSP_FID_RESUME TSP_STD_FID(0x3000) #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. * Total number of function IDs implemented for services offered to NS clients.
* The function IDs are defined above * The function IDs are defined above
*/ */
#define TSP_NUM_FID 0x4 #define TSP_NUM_FID 0x5
/* TSP implementation version numbers */ /* TSP implementation version numbers */
#define TSP_VERSION_MAJOR 0x0 /* Major version */ #define TSP_VERSION_MAJOR 0x0 /* Major version */
...@@ -117,6 +125,7 @@ typedef struct tsp_vectors { ...@@ -117,6 +125,7 @@ typedef struct tsp_vectors {
tsp_vector_isn_t sel1_intr_entry; tsp_vector_isn_t sel1_intr_entry;
tsp_vector_isn_t system_off_entry; tsp_vector_isn_t system_off_entry;
tsp_vector_isn_t system_reset_entry; tsp_vector_isn_t system_reset_entry;
tsp_vector_isn_t abort_std_smc_entry;
} tsp_vectors_t; } tsp_vectors_t;
......
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
#include <assert.h> #include <assert.h>
#include <bl_common.h> #include <bl_common.h>
#include <context_mgmt.h> #include <context_mgmt.h>
#include <debug.h>
#include <string.h> #include <string.h>
#include <tsp.h>
#include "tspd_private.h" #include "tspd_private.h"
/******************************************************************************* /*******************************************************************************
...@@ -129,3 +131,31 @@ void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret) ...@@ -129,3 +131,31 @@ void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret)
/* Should never reach here */ /* Should never reach here */
assert(0); 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;
}
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -459,6 +459,11 @@ uint64_t tspd_smc_handler(uint32_t smc_fid, ...@@ -459,6 +459,11 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
*/ */
tspd_synchronous_sp_exit(tsp_ctx, x1); tspd_synchronous_sp_exit(tsp_ctx, x1);
#endif #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 * 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, ...@@ -596,6 +601,26 @@ uint64_t tspd_smc_handler(uint32_t smc_fid,
} }
break; 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 * Request from non secure world to resume the preempted
......
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
...@@ -58,6 +58,12 @@ static int32_t tspd_cpu_off_handler(uint64_t unused) ...@@ -58,6 +58,12 @@ static int32_t tspd_cpu_off_handler(uint64_t unused)
assert(tsp_vectors); assert(tsp_vectors);
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); 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 */ /* Program the entry point and enter the TSP */
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry); cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry);
rc = tspd_synchronous_sp_entry(tsp_ctx); rc = tspd_synchronous_sp_entry(tsp_ctx);
...@@ -91,6 +97,12 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl) ...@@ -91,6 +97,12 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl)
assert(tsp_vectors); assert(tsp_vectors);
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); 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 */ /* Program the entry point and enter the TSP */
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry); cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry);
rc = tspd_synchronous_sp_entry(tsp_ctx); rc = tspd_synchronous_sp_entry(tsp_ctx);
...@@ -99,7 +111,7 @@ static void tspd_cpu_suspend_handler(uint64_t max_off_pwrlvl) ...@@ -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 * Read the response from the TSP. A non-zero return means that
* something went wrong while communicating with the TSP. * something went wrong while communicating with the TSP.
*/ */
if (rc != 0) if (rc)
panic(); panic();
/* Update its context to reflect the state the TSP is in */ /* 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) ...@@ -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 * 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 * after initialising minimal architectural state that guarantees safe
* execution. * execution.
******************************************************************************/ ******************************************************************************/
...@@ -205,6 +217,12 @@ static void tspd_system_off(void) ...@@ -205,6 +217,12 @@ static void tspd_system_off(void)
assert(tsp_vectors); assert(tsp_vectors);
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); 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 */ /* Program the entry point */
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry); cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry);
...@@ -225,11 +243,19 @@ static void tspd_system_reset(void) ...@@ -225,11 +243,19 @@ static void tspd_system_reset(void)
assert(tsp_vectors); assert(tsp_vectors);
assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); 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 */ /* Program the entry point */
cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry); 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); tspd_synchronous_sp_entry(tsp_ctx);
} }
......
/* /*
* 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * 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, ...@@ -242,6 +242,7 @@ void tspd_init_tsp_ep_state(struct entry_point_info *tsp_ep,
uint32_t rw, uint32_t rw,
uint64_t pc, uint64_t pc,
tsp_context_t *tsp_ctx); 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 tsp_context_t tspd_sp_context[TSPD_CORE_COUNT];
extern struct tsp_vectors *tsp_vectors; extern struct tsp_vectors *tsp_vectors;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment