Commit 31244d74 authored by Soby Mathew's avatar Soby Mathew
Browse files

Save 'power_state' early in PSCI CPU_SUSPEND call

This patch adds support to save the "power state" parameter before the
affinity level specific handlers are called in a CPU_SUSPEND call.
This avoids the need to pass the power_state as a parameter to the
handlers and Secure Payload Dispatcher (SPD) suspend spd_pm_ops.
The power_state arguments in the spd_pm_ops operations are now reserved
and must not be used. The SPD can query the relevant power_state fields
by using the psci_get_suspend_afflvl() & psci_get_suspend_stateid() APIs.

NOTE: THIS PATCH WILL BREAK THE SPD_PM_OPS INTERFACE. HENCE THE SECURE
PAYLOAD DISPATCHERS WILL NEED TO BE REWORKED TO USE THE NEW INTERFACE.

Change-Id: I1293d7dc8cf29cfa6a086a009eee41bcbf2f238e
parent 78879b9a
...@@ -216,7 +216,7 @@ tsp_args_t *tsp_cpu_off_main(uint64_t arg0, ...@@ -216,7 +216,7 @@ tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
* this cpu's architectural state is saved in response to an earlier psci * this cpu's architectural state is saved in response to an earlier psci
* cpu_suspend request. * cpu_suspend request.
******************************************************************************/ ******************************************************************************/
tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state, tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0,
uint64_t arg1, uint64_t arg1,
uint64_t arg2, uint64_t arg2,
uint64_t arg3, uint64_t arg3,
...@@ -242,8 +242,6 @@ tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state, ...@@ -242,8 +242,6 @@ tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
#if LOG_LEVEL >= LOG_LEVEL_INFO #if LOG_LEVEL >= LOG_LEVEL_INFO
spin_lock(&console_lock); spin_lock(&console_lock);
INFO("TSP: cpu 0x%x suspend request. power state: 0x%x\n",
mpidr, power_state);
INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
mpidr, mpidr,
tsp_stats[linear_id].smc_count, tsp_stats[linear_id].smc_count,
......
...@@ -186,7 +186,7 @@ typedef struct plat_pm_ops { ...@@ -186,7 +186,7 @@ typedef struct plat_pm_ops {
typedef struct spd_pm_ops { typedef struct spd_pm_ops {
void (*svc_on)(uint64_t target_cpu); void (*svc_on)(uint64_t target_cpu);
int32_t (*svc_off)(uint64_t __unused); int32_t (*svc_off)(uint64_t __unused);
void (*svc_suspend)(uint64_t power_state); void (*svc_suspend)(uint64_t __unused);
void (*svc_on_finish)(uint64_t __unused); void (*svc_on_finish)(uint64_t __unused);
void (*svc_suspend_finish)(uint64_t suspend_level); void (*svc_suspend_finish)(uint64_t suspend_level);
void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2); void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2);
......
...@@ -48,7 +48,7 @@ static void opteed_cpu_on_handler(uint64_t target_cpu) ...@@ -48,7 +48,7 @@ static void opteed_cpu_on_handler(uint64_t target_cpu)
* This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
* needed * needed
******************************************************************************/ ******************************************************************************/
static int32_t opteed_cpu_off_handler(uint64_t cookie) static int32_t opteed_cpu_off_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
...@@ -82,7 +82,7 @@ static int32_t opteed_cpu_off_handler(uint64_t cookie) ...@@ -82,7 +82,7 @@ static int32_t opteed_cpu_off_handler(uint64_t cookie)
* This cpu is being suspended. S-EL1 state must have been saved in the * This cpu is being suspended. S-EL1 state must have been saved in the
* resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
******************************************************************************/ ******************************************************************************/
static void opteed_cpu_suspend_handler(uint64_t power_state) static void opteed_cpu_suspend_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
...@@ -92,10 +92,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state) ...@@ -92,10 +92,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state)
assert(optee_vectors); assert(optee_vectors);
assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
/* Program the entry point, power_state parameter and enter OPTEE */ /* Program the entry point and enter OPTEE */
write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
CTX_GPREG_X0,
power_state);
cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry); cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry);
rc = opteed_synchronous_sp_entry(optee_ctx); rc = opteed_synchronous_sp_entry(optee_ctx);
...@@ -116,7 +113,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state) ...@@ -116,7 +113,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state)
* after initialising minimal architectural state that guarantees safe * after initialising minimal architectural state that guarantees safe
* execution. * execution.
******************************************************************************/ ******************************************************************************/
static void opteed_cpu_on_finish_handler(uint64_t cookie) static void opteed_cpu_on_finish_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
......
...@@ -49,7 +49,7 @@ static void tspd_cpu_on_handler(uint64_t target_cpu) ...@@ -49,7 +49,7 @@ static void tspd_cpu_on_handler(uint64_t target_cpu)
* This cpu is being turned off. Allow the TSPD/TSP to perform any actions * This cpu is being turned off. Allow the TSPD/TSP to perform any actions
* needed * needed
******************************************************************************/ ******************************************************************************/
static int32_t tspd_cpu_off_handler(uint64_t cookie) static int32_t tspd_cpu_off_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
...@@ -83,7 +83,7 @@ static int32_t tspd_cpu_off_handler(uint64_t cookie) ...@@ -83,7 +83,7 @@ static int32_t tspd_cpu_off_handler(uint64_t cookie)
* This cpu is being suspended. S-EL1 state must have been saved in the * This cpu is being suspended. S-EL1 state must have been saved in the
* resident cpu (mpidr format) if it is a UP/UP migratable TSP. * resident cpu (mpidr format) if it is a UP/UP migratable TSP.
******************************************************************************/ ******************************************************************************/
static void tspd_cpu_suspend_handler(uint64_t power_state) static void tspd_cpu_suspend_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
...@@ -93,10 +93,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) ...@@ -93,10 +93,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state)
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);
/* Program the entry point, power_state parameter and enter the TSP */ /* Program the entry point and enter the TSP */
write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx),
CTX_GPREG_X0,
power_state);
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);
...@@ -117,7 +114,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) ...@@ -117,7 +114,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state)
* after initialising minimal architectural state that guarantees safe * after initialising minimal architectural state that guarantees safe
* execution. * execution.
******************************************************************************/ ******************************************************************************/
static void tspd_cpu_on_finish_handler(uint64_t cookie) static void tspd_cpu_on_finish_handler(uint64_t unused)
{ {
int32_t rc = 0; int32_t rc = 0;
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
......
...@@ -40,8 +40,7 @@ ...@@ -40,8 +40,7 @@
#include <stddef.h> #include <stddef.h>
#include "psci_private.h" #include "psci_private.h"
typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node, typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node);
unsigned int power_state);
/******************************************************************************* /*******************************************************************************
* This function saves the power state parameter passed in the current PSCI * This function saves the power state parameter passed in the current PSCI
...@@ -103,17 +102,13 @@ int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr) ...@@ -103,17 +102,13 @@ int psci_get_suspend_stateid_by_mpidr(unsigned long mpidr)
* The next three functions implement a handler for each supported affinity * The next three functions implement a handler for each supported affinity
* level which is called when that affinity level is about to be suspended. * level which is called when that affinity level is about to be suspended.
******************************************************************************/ ******************************************************************************/
static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, static int psci_afflvl0_suspend(aff_map_node_t *cpu_node)
unsigned int power_state)
{ {
unsigned long psci_entrypoint; unsigned long psci_entrypoint;
/* Sanity check to safeguard against data corruption */ /* Sanity check to safeguard against data corruption */
assert(cpu_node->level == MPIDR_AFFLVL0); assert(cpu_node->level == MPIDR_AFFLVL0);
/* Save PSCI power state parameter for the core in suspend context */
psci_set_suspend_power_state(power_state);
/* /*
* Generic management: Allow the Secure world to suspend itself * Generic management: Allow the Secure world to suspend itself
*/ */
...@@ -124,8 +119,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, ...@@ -124,8 +119,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node,
* error, it's expected to assert within * error, it's expected to assert within
*/ */
if (psci_spd_pm && psci_spd_pm->svc_suspend) if (psci_spd_pm && psci_spd_pm->svc_suspend)
psci_spd_pm->svc_suspend(power_state); psci_spd_pm->svc_suspend(0);
/* Set the secure world (EL3) re-entry point after BL1 */ /* Set the secure world (EL3) re-entry point after BL1 */
psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry; psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry;
...@@ -150,8 +144,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, ...@@ -150,8 +144,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node,
psci_get_phys_state(cpu_node)); psci_get_phys_state(cpu_node));
} }
static int psci_afflvl1_suspend(aff_map_node_t *cluster_node, static int psci_afflvl1_suspend(aff_map_node_t *cluster_node)
unsigned int power_state)
{ {
unsigned int plat_state; unsigned int plat_state;
unsigned long psci_entrypoint; unsigned long psci_entrypoint;
...@@ -184,8 +177,7 @@ static int psci_afflvl1_suspend(aff_map_node_t *cluster_node, ...@@ -184,8 +177,7 @@ static int psci_afflvl1_suspend(aff_map_node_t *cluster_node,
} }
static int psci_afflvl2_suspend(aff_map_node_t *system_node, static int psci_afflvl2_suspend(aff_map_node_t *system_node)
unsigned int power_state)
{ {
unsigned int plat_state; unsigned int plat_state;
unsigned long psci_entrypoint; unsigned long psci_entrypoint;
...@@ -238,8 +230,7 @@ static const afflvl_suspend_handler_t psci_afflvl_suspend_handlers[] = { ...@@ -238,8 +230,7 @@ static const afflvl_suspend_handler_t psci_afflvl_suspend_handlers[] = {
******************************************************************************/ ******************************************************************************/
static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[], static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
int start_afflvl, int start_afflvl,
int end_afflvl, int end_afflvl)
unsigned int power_state)
{ {
int rc = PSCI_E_INVALID_PARAMS, level; int rc = PSCI_E_INVALID_PARAMS, level;
aff_map_node_t *node; aff_map_node_t *node;
...@@ -254,8 +245,7 @@ static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[], ...@@ -254,8 +245,7 @@ static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
* of restoring what we might have torn down at * of restoring what we might have torn down at
* lower affinity levels. * lower affinity levels.
*/ */
rc = psci_afflvl_suspend_handlers[level](node, rc = psci_afflvl_suspend_handlers[level](node);
power_state);
if (rc != PSCI_E_SUCCESS) if (rc != PSCI_E_SUCCESS)
break; break;
} }
...@@ -283,7 +273,6 @@ static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[], ...@@ -283,7 +273,6 @@ static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[],
* first. * first.
******************************************************************************/ ******************************************************************************/
int psci_afflvl_suspend(entry_point_info_t *ep, int psci_afflvl_suspend(entry_point_info_t *ep,
unsigned int power_state,
int start_afflvl, int start_afflvl,
int end_afflvl) int end_afflvl)
{ {
...@@ -339,8 +328,7 @@ int psci_afflvl_suspend(entry_point_info_t *ep, ...@@ -339,8 +328,7 @@ int psci_afflvl_suspend(entry_point_info_t *ep,
/* Perform generic, architecture and platform specific handling */ /* Perform generic, architecture and platform specific handling */
rc = psci_call_suspend_handlers(mpidr_nodes, rc = psci_call_suspend_handlers(mpidr_nodes,
start_afflvl, start_afflvl,
end_afflvl, end_afflvl);
power_state);
/* /*
* Invalidate the entry for the highest affinity level stashed earlier. * Invalidate the entry for the highest affinity level stashed earlier.
......
...@@ -125,18 +125,23 @@ int psci_cpu_suspend(unsigned int power_state, ...@@ -125,18 +125,23 @@ int psci_cpu_suspend(unsigned int power_state,
if (rc != PSCI_E_SUCCESS) if (rc != PSCI_E_SUCCESS)
return rc; return rc;
/* Save PSCI power state parameter for the core in suspend context */
psci_set_suspend_power_state(power_state);
/* /*
* Do what is needed to enter the power down state. Upon success, * Do what is needed to enter the power down state. Upon success,
* enter the final wfi which will power down this cpu else return * enter the final wfi which will power down this cpu else return
* an error. * an error.
*/ */
rc = psci_afflvl_suspend(&ep, rc = psci_afflvl_suspend(&ep,
power_state,
MPIDR_AFFLVL0, MPIDR_AFFLVL0,
target_afflvl); target_afflvl);
if (rc == PSCI_E_SUCCESS) if (rc == PSCI_E_SUCCESS)
psci_power_down_wfi(); psci_power_down_wfi();
assert(rc == PSCI_E_INVALID_PARAMS); assert(rc == PSCI_E_INVALID_PARAMS);
/* Reset PSCI power state parameter for the core. */
psci_set_suspend_power_state(PSCI_INVALID_DATA);
return rc; return rc;
} }
......
...@@ -139,7 +139,6 @@ int psci_afflvl_off(int, int); ...@@ -139,7 +139,6 @@ int psci_afflvl_off(int, int);
/* Private exported functions from psci_affinity_suspend.c */ /* Private exported functions from psci_affinity_suspend.c */
int psci_afflvl_suspend(entry_point_info_t *ep, int psci_afflvl_suspend(entry_point_info_t *ep,
unsigned int power_state,
int start_afflvl, int start_afflvl,
int end_afflvl); int end_afflvl);
......
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