From: Soby Mathew Date: Tue, 30 Sep 2014 10:19:51 +0000 (+0100) Subject: Save 'power_state' early in PSCI CPU_SUSPEND call X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=31244d74b350d49cfba6ad46d90dad2d5f2f364c;p=project%2Fbcm63xx%2Fatf.git 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 --- diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c index 2eaca7c9..c6000e19 100644 --- a/bl32/tsp/tsp_main.c +++ b/bl32/tsp/tsp_main.c @@ -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 * 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 arg2, uint64_t arg3, @@ -242,8 +242,6 @@ tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state, #if LOG_LEVEL >= LOG_LEVEL_INFO 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", mpidr, tsp_stats[linear_id].smc_count, diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h index 26b607c0..7513326f 100644 --- a/include/bl31/services/psci.h +++ b/include/bl31/services/psci.h @@ -186,7 +186,7 @@ typedef struct plat_pm_ops { typedef struct spd_pm_ops { void (*svc_on)(uint64_t target_cpu); 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_suspend_finish)(uint64_t suspend_level); void (*svc_migrate)(uint64_t __unused1, uint64_t __unused2); diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c index 552d7a0c..37419ec7 100644 --- a/services/spd/opteed/opteed_pm.c +++ b/services/spd/opteed/opteed_pm.c @@ -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 * 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; uint64_t mpidr = read_mpidr(); @@ -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 * 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; uint64_t mpidr = read_mpidr(); @@ -92,10 +92,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state) assert(optee_vectors); assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); - /* Program the entry point, power_state parameter and enter OPTEE */ - write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), - CTX_GPREG_X0, - power_state); + /* Program the entry point and enter OPTEE */ cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry); rc = opteed_synchronous_sp_entry(optee_ctx); @@ -116,7 +113,7 @@ static void opteed_cpu_suspend_handler(uint64_t power_state) * after initialising minimal architectural state that guarantees safe * 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; uint64_t mpidr = read_mpidr(); diff --git a/services/spd/tspd/tspd_pm.c b/services/spd/tspd/tspd_pm.c index 16552853..17abaea6 100644 --- a/services/spd/tspd/tspd_pm.c +++ b/services/spd/tspd/tspd_pm.c @@ -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 * 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; uint64_t mpidr = read_mpidr(); @@ -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 * 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; uint64_t mpidr = read_mpidr(); @@ -93,10 +93,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) assert(tsp_vectors); assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); - /* Program the entry point, power_state parameter and enter the TSP */ - write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), - CTX_GPREG_X0, - power_state); + /* 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); @@ -117,7 +114,7 @@ static void tspd_cpu_suspend_handler(uint64_t power_state) * after initialising minimal architectural state that guarantees safe * 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; uint64_t mpidr = read_mpidr(); diff --git a/services/std_svc/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c index 4988e677..942e9a12 100644 --- a/services/std_svc/psci/psci_afflvl_suspend.c +++ b/services/std_svc/psci/psci_afflvl_suspend.c @@ -40,8 +40,7 @@ #include #include "psci_private.h" -typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node, - unsigned int power_state); +typedef int (*afflvl_suspend_handler_t)(aff_map_node_t *node); /******************************************************************************* * 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) * The next three functions implement a handler for each supported affinity * level which is called when that affinity level is about to be suspended. ******************************************************************************/ -static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, - unsigned int power_state) +static int psci_afflvl0_suspend(aff_map_node_t *cpu_node) { unsigned long psci_entrypoint; /* Sanity check to safeguard against data corruption */ 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 */ @@ -124,8 +119,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, * error, it's expected to assert within */ 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 */ psci_entrypoint = (unsigned long) psci_aff_suspend_finish_entry; @@ -150,8 +144,7 @@ static int psci_afflvl0_suspend(aff_map_node_t *cpu_node, psci_get_phys_state(cpu_node)); } -static int psci_afflvl1_suspend(aff_map_node_t *cluster_node, - unsigned int power_state) +static int psci_afflvl1_suspend(aff_map_node_t *cluster_node) { unsigned int plat_state; unsigned long psci_entrypoint; @@ -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, - unsigned int power_state) +static int psci_afflvl2_suspend(aff_map_node_t *system_node) { unsigned int plat_state; unsigned long psci_entrypoint; @@ -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[], int start_afflvl, - int end_afflvl, - unsigned int power_state) + int end_afflvl) { int rc = PSCI_E_INVALID_PARAMS, level; aff_map_node_t *node; @@ -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 * lower affinity levels. */ - rc = psci_afflvl_suspend_handlers[level](node, - power_state); + rc = psci_afflvl_suspend_handlers[level](node); if (rc != PSCI_E_SUCCESS) break; } @@ -283,7 +273,6 @@ static int psci_call_suspend_handlers(aff_map_node_t *mpidr_nodes[], * first. ******************************************************************************/ int psci_afflvl_suspend(entry_point_info_t *ep, - unsigned int power_state, int start_afflvl, int end_afflvl) { @@ -339,8 +328,7 @@ int psci_afflvl_suspend(entry_point_info_t *ep, /* Perform generic, architecture and platform specific handling */ rc = psci_call_suspend_handlers(mpidr_nodes, start_afflvl, - end_afflvl, - power_state); + end_afflvl); /* * Invalidate the entry for the highest affinity level stashed earlier. diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c index 7fce5faf..506f5920 100644 --- a/services/std_svc/psci/psci_main.c +++ b/services/std_svc/psci/psci_main.c @@ -125,18 +125,23 @@ int psci_cpu_suspend(unsigned int power_state, if (rc != PSCI_E_SUCCESS) 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, * enter the final wfi which will power down this cpu else return * an error. */ rc = psci_afflvl_suspend(&ep, - power_state, MPIDR_AFFLVL0, target_afflvl); if (rc == PSCI_E_SUCCESS) psci_power_down_wfi(); assert(rc == PSCI_E_INVALID_PARAMS); + + /* Reset PSCI power state parameter for the core. */ + psci_set_suspend_power_state(PSCI_INVALID_DATA); return rc; } diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h index 3a4ee3c8..98d5d92a 100644 --- a/services/std_svc/psci/psci_private.h +++ b/services/std_svc/psci/psci_private.h @@ -139,7 +139,6 @@ int psci_afflvl_off(int, int); /* Private exported functions from psci_affinity_suspend.c */ int psci_afflvl_suspend(entry_point_info_t *ep, - unsigned int power_state, int start_afflvl, int end_afflvl);