diff options
author | Soby Mathew <soby.mathew@arm.com> | 2014-10-02 16:56:51 +0100 |
---|---|---|
committer | Soby Mathew <soby.mathew@arm.com> | 2015-01-23 18:36:15 +0000 |
commit | 539dcedb7d83804a4237c4385b2cb15f0b7ee0b5 (patch) | |
tree | 83e9dc96a440e1c2f113bc822c7ecd3ebc7baf5d /plat/juno/plat_pm.c | |
parent | 31244d74b350d49cfba6ad46d90dad2d5f2f364c (diff) |
Validate power_state and entrypoint when executing PSCI calls
This patch allows the platform to validate the power_state and
entrypoint information from the normal world early on in PSCI
calls so that we can return the error safely. New optional
pm_ops hooks `validate_power_state` and `validate_ns_entrypoint`
are introduced to do this.
As a result of these changes, all the other pm_ops handlers except
the PSCI_ON handler are expected to be successful. Also, the PSCI
implementation will now assert if a PSCI API is invoked without the
corresponding pm_ops handler being registered by the platform.
NOTE : PLATFORM PORTS WILL BREAK ON MERGE OF THIS COMMIT. The
pm hooks have 2 additional optional callbacks and the return type
of the other hooks have changed.
Fixes ARM-Software/tf-issues#229
Change-Id: I036bc0cff2349187c7b8b687b9ee0620aa7e24dc
Diffstat (limited to 'plat/juno/plat_pm.c')
-rw-r--r-- | plat/juno/plat_pm.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/plat/juno/plat_pm.c b/plat/juno/plat_pm.c index a3907061..47338cfc 100644 --- a/plat/juno/plat_pm.c +++ b/plat/juno/plat_pm.c @@ -85,6 +85,31 @@ static int32_t juno_do_plat_actions(uint32_t afflvl, uint32_t state) } /******************************************************************************* + * Juno handler called to check the validity of the power state parameter. + ******************************************************************************/ +int32_t juno_validate_power_state(unsigned int power_state) +{ + /* Sanity check the requested state */ + if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on affinity level 0 i.e. + * a cpu on the Juno. Ignore any other affinity level. + */ + if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + } + + /* + * We expect the 'state id' to be zero. + */ + if (psci_get_pstate_id(power_state)) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + + +/******************************************************************************* * Juno handler called when an affinity instance is about to be turned on. The * level and mpidr determine the affinity instance. ******************************************************************************/ @@ -118,13 +143,13 @@ int32_t juno_affinst_on(uint64_t mpidr, * was turned off prior to wakeup and do what's necessary to setup it up * correctly. ******************************************************************************/ -int32_t juno_affinst_on_finish(uint32_t afflvl, uint32_t state) +void juno_affinst_on_finish(uint32_t afflvl, uint32_t state) { unsigned long mpidr; /* Determine if any platform actions need to be executed. */ if (juno_do_plat_actions(afflvl, state) == -EAGAIN) - return PSCI_E_SUCCESS; + return; /* Get the mpidr for this cpu */ mpidr = read_mpidr_el1(); @@ -145,8 +170,6 @@ int32_t juno_affinst_on_finish(uint32_t afflvl, uint32_t state) /* Clear the mailbox for this cpu. */ juno_program_mailbox(mpidr, 0); - - return PSCI_E_SUCCESS; } /******************************************************************************* @@ -155,7 +178,7 @@ int32_t juno_affinst_on_finish(uint32_t afflvl, uint32_t state) * the highest affinity level which will be powered down. It performs the * actions common to the OFF and SUSPEND calls. ******************************************************************************/ -static int32_t juno_power_down_common(uint32_t afflvl) +static void juno_power_down_common(uint32_t afflvl) { uint32_t cluster_state = scpi_power_on; @@ -176,8 +199,6 @@ static int32_t juno_power_down_common(uint32_t afflvl) scpi_power_off, cluster_state, scpi_power_on); - - return PSCI_E_SUCCESS; } /******************************************************************************* @@ -191,13 +212,13 @@ static int32_t juno_power_down_common(uint32_t afflvl) * global variables across calls. It will be wise to do flush a write to the * global to prevent unpredictable results. ******************************************************************************/ -static int32_t juno_affinst_off(uint32_t afflvl, uint32_t state) +static void juno_affinst_off(uint32_t afflvl, uint32_t state) { /* Determine if any platform actions need to be executed */ if (juno_do_plat_actions(afflvl, state) == -EAGAIN) - return PSCI_E_SUCCESS; + return; - return juno_power_down_common(afflvl); + juno_power_down_common(afflvl); } /******************************************************************************* @@ -212,20 +233,20 @@ static int32_t juno_affinst_off(uint32_t afflvl, uint32_t state) * global variables across calls. It will be wise to do flush a write to the * global to prevent unpredictable results. ******************************************************************************/ -static int32_t juno_affinst_suspend(uint64_t sec_entrypoint, +static void juno_affinst_suspend(uint64_t sec_entrypoint, uint32_t afflvl, uint32_t state) { /* Determine if any platform actions need to be executed */ if (juno_do_plat_actions(afflvl, state) == -EAGAIN) - return PSCI_E_SUCCESS; + return; /* * Setup mailbox with address for CPU entrypoint when it next powers up. */ juno_program_mailbox(read_mpidr_el1(), sec_entrypoint); - return juno_power_down_common(afflvl); + juno_power_down_common(afflvl); } /******************************************************************************* @@ -235,10 +256,10 @@ static int32_t juno_affinst_suspend(uint64_t sec_entrypoint, * TODO: At the moment we reuse the on finisher and reinitialize the secure * context. Need to implement a separate suspend finisher. ******************************************************************************/ -static int32_t juno_affinst_suspend_finish(uint32_t afflvl, +static void juno_affinst_suspend_finish(uint32_t afflvl, uint32_t state) { - return juno_affinst_on_finish(afflvl, state); + juno_affinst_on_finish(afflvl, state); } /******************************************************************************* @@ -279,21 +300,10 @@ static void __dead2 juno_system_reset(void) /******************************************************************************* * Handler called when an affinity instance is about to enter standby. ******************************************************************************/ -int32_t juno_affinst_standby(unsigned int power_state) +void juno_affinst_standby(unsigned int power_state) { - unsigned int target_afflvl; unsigned int scr; - /* Sanity check the requested state */ - target_afflvl = psci_get_pstate_afflvl(power_state); - - /* - * It's possible to enter standby only on affinity level 0 i.e. a cpu - * on the Juno. Ignore any other affinity level. - */ - if (target_afflvl != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - scr = read_scr_el3(); /* Enable PhysicalIRQ bit for NS world to wake the CPU */ write_scr_el3(scr | SCR_IRQ_BIT); @@ -306,8 +316,6 @@ int32_t juno_affinst_standby(unsigned int power_state) * done by eret while el3_exit to save some execution cycles. */ write_scr_el3(scr); - - return PSCI_E_SUCCESS; } /******************************************************************************* @@ -321,7 +329,8 @@ static const plat_pm_ops_t juno_ops = { .affinst_suspend = juno_affinst_suspend, .affinst_suspend_finish = juno_affinst_suspend_finish, .system_off = juno_system_off, - .system_reset = juno_system_reset + .system_reset = juno_system_reset, + .validate_power_state = juno_validate_power_state }; /******************************************************************************* |