Commit cb790c5e authored by Varun Wadekar's avatar Varun Wadekar
Browse files

Send power management events to the Trusted OS (TLK)



This patch adds PM handlers to TLKD for the system suspend/resume and
system poweroff/reset cases. TLK expects all SMCs through a single
handler, which then fork out into multiple handlers depending on the
SMC. We tap into the same single entrypoint by restoring the S-EL1
context before passing the PM event via register 'x0'. On completion
of the PM event, TLK sends a completion SMC and TLKD then moves on
with the PM process.
Signed-off-by: default avatarVarun Wadekar <vwadekar@nvidia.com>
parent a6ef882c
...@@ -43,6 +43,9 @@ ...@@ -43,6 +43,9 @@
#define TLK_REGISTER_LOGBUF TLK_TOS_STD_FID(0x1) #define TLK_REGISTER_LOGBUF TLK_TOS_STD_FID(0x1)
#define TLK_REGISTER_REQBUF TLK_TOS_STD_FID(0x2) #define TLK_REGISTER_REQBUF TLK_TOS_STD_FID(0x2)
#define TLK_RESUME_FID TLK_TOS_STD_FID(0x100) #define TLK_RESUME_FID TLK_TOS_STD_FID(0x100)
#define TLK_SYSTEM_SUSPEND TLK_TOS_STD_FID(0xE001)
#define TLK_SYSTEM_RESUME TLK_TOS_STD_FID(0xE002)
#define TLK_SYSTEM_OFF TLK_TOS_STD_FID(0xE003)
/* /*
* SMC function IDs that TLK uses to signal various forms of completions * SMC function IDs that TLK uses to signal various forms of completions
...@@ -52,6 +55,9 @@ ...@@ -52,6 +55,9 @@
#define TLK_PREEMPTED (0x32000002 | (1 << 31)) #define TLK_PREEMPTED (0x32000002 | (1 << 31))
#define TLK_ENTRY_DONE (0x32000003 | (1 << 31)) #define TLK_ENTRY_DONE (0x32000003 | (1 << 31))
#define TLK_VA_TRANSLATE (0x32000004 | (1 << 31)) #define TLK_VA_TRANSLATE (0x32000004 | (1 << 31))
#define TLK_SUSPEND_DONE (0x32000005 | (1 << 31))
#define TLK_RESUME_DONE (0x32000006 | (1 << 31))
#define TLK_SYSTEM_OFF_DONE (0x32000007 | (1 << 31))
/* /*
* Trusted Application specific function IDs * Trusted Application specific function IDs
......
...@@ -54,9 +54,9 @@ ...@@ -54,9 +54,9 @@
extern const spd_pm_ops_t tlkd_pm_ops; extern const spd_pm_ops_t tlkd_pm_ops;
/******************************************************************************* /*******************************************************************************
* Array to keep track of per-cpu Secure Payload state * Per-cpu Secure Payload state
******************************************************************************/ ******************************************************************************/
static tlk_context_t tlk_ctx; tlk_context_t tlk_ctx;
/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ /* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */
DEFINE_SVC_UUID(tlk_uuid, DEFINE_SVC_UUID(tlk_uuid,
...@@ -386,6 +386,31 @@ uint64_t tlkd_smc_handler(uint32_t smc_fid, ...@@ -386,6 +386,31 @@ uint64_t tlkd_smc_handler(uint32_t smc_fid,
*/ */
tlkd_synchronous_sp_exit(&tlk_ctx, x1); tlkd_synchronous_sp_exit(&tlk_ctx, x1);
/*
* These function IDs are used only by TLK to indicate it has
* finished:
* 1. suspending itself after an earlier psci cpu_suspend
* request.
* 2. resuming itself after an earlier psci cpu_suspend
* request.
* 3. powering down after an earlier psci system_off/system_reset
* request.
*/
case TLK_SUSPEND_DONE:
case TLK_RESUME_DONE:
case TLK_SYSTEM_OFF_DONE:
if (ns)
SMC_RET1(handle, SMC_UNK);
/*
* TLK reports completion. TLKD must have initiated the
* original request through a synchronous entry into the SP.
* Jump back to the original C runtime context, and pass x1 as
* return value to the caller
*/
tlkd_synchronous_sp_exit(&tlk_ctx, x1);
/* /*
* Return the number of service function IDs implemented to * Return the number of service function IDs implemented to
* provide service to non-secure * provide service to non-secure
......
...@@ -28,7 +28,17 @@ ...@@ -28,7 +28,17 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <arch_helpers.h>
#include <assert.h>
#include <bl_common.h>
#include <context_mgmt.h>
#include <debug.h>
#include <psci.h> #include <psci.h>
#include <tlk.h>
#include "tlkd_private.h"
extern tlk_context_t tlk_ctx;
#define MPIDR_CPU0 0x80000000 #define MPIDR_CPU0 0x80000000
...@@ -45,10 +55,102 @@ static int32_t cpu_migrate_info(uint64_t *resident_cpu) ...@@ -45,10 +55,102 @@ static int32_t cpu_migrate_info(uint64_t *resident_cpu)
return PSCI_TOS_NOT_UP_MIG_CAP; return PSCI_TOS_NOT_UP_MIG_CAP;
} }
/*******************************************************************************
* This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so
* that it can pass this information to its Trusted Apps.
******************************************************************************/
static void cpu_suspend_handler(uint64_t suspend_level)
{
gp_regs_t *gp_regs;
int cpu = read_mpidr() & MPIDR_CPU_MASK;
int32_t rc = 0;
/*
* TLK runs only on CPU0 and suspends its Trusted Apps during
* SYSTEM_SUSPEND. It has no role to play during CPU_SUSPEND.
*/
if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL))
return;
/* pass system suspend event to TLK */
gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx);
write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_SUSPEND);
/* Program the entry point and enter TLK */
rc = tlkd_synchronous_sp_entry(&tlk_ctx);
/*
* Read the response from TLK. A non-zero return means that
* something went wrong while communicating with it.
*/
if (rc != 0)
panic();
}
/*******************************************************************************
* This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so
* that it can pass this information to its Trusted Apps.
******************************************************************************/
static void cpu_resume_handler(uint64_t suspend_level)
{
gp_regs_t *gp_regs;
int cpu = read_mpidr() & MPIDR_CPU_MASK;
int32_t rc = 0;
/*
* TLK runs only on CPU0 and resumes its Trusted Apps during
* SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND
* exit.
*/
if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL))
return;
/* pass system resume event to TLK */
gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx);
write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME);
/* Program the entry point and enter TLK */
rc = tlkd_synchronous_sp_entry(&tlk_ctx);
/*
* Read the response from TLK. A non-zero return means that
* something went wrong while communicating with it.
*/
if (rc != 0)
panic();
}
/*******************************************************************************
* System is about to be reset. Inform the SP to allow any book-keeping
******************************************************************************/
static void system_off_handler(void)
{
int cpu = read_mpidr() & MPIDR_CPU_MASK;
gp_regs_t *gp_regs;
/* TLK runs only on CPU0 */
if (cpu != 0)
return;
/* pass system off/reset events to TLK */
gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx);
write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_OFF);
/*
* Enter the SP. We do not care about the return value because we
* must continue with the shutdown anyway.
*/
(void)tlkd_synchronous_sp_entry(&tlk_ctx);
}
/******************************************************************************* /*******************************************************************************
* Structure populated by the Dispatcher to be given a chance to perform any * Structure populated by the Dispatcher to be given a chance to perform any
* bookkeeping before PSCI executes a power mgmt. operation. * bookkeeping before PSCI executes a power mgmt. operation.
******************************************************************************/ ******************************************************************************/
const spd_pm_ops_t tlkd_pm_ops = { const spd_pm_ops_t tlkd_pm_ops = {
.svc_migrate_info = cpu_migrate_info, .svc_migrate_info = cpu_migrate_info,
.svc_suspend = cpu_suspend_handler,
.svc_suspend_finish = cpu_resume_handler,
.svc_system_off = system_off_handler,
.svc_system_reset = system_off_handler
}; };
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