aboutsummaryrefslogtreecommitdiff
path: root/plat/fvp/fvp_pm.c
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2014-10-02 16:56:51 +0100
committerSoby Mathew <soby.mathew@arm.com>2015-01-23 18:36:15 +0000
commit539dcedb7d83804a4237c4385b2cb15f0b7ee0b5 (patch)
tree83e9dc96a440e1c2f113bc822c7ecd3ebc7baf5d /plat/fvp/fvp_pm.c
parent31244d74b350d49cfba6ad46d90dad2d5f2f364c (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/fvp/fvp_pm.c')
-rw-r--r--plat/fvp/fvp_pm.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/plat/fvp/fvp_pm.c b/plat/fvp/fvp_pm.c
index fdf32097..9044e693 100644
--- a/plat/fvp/fvp_pm.c
+++ b/plat/fvp/fvp_pm.c
@@ -119,28 +119,14 @@ static int32_t fvp_do_plat_actions(unsigned int afflvl, unsigned int state)
/*******************************************************************************
* FVP handler called when an affinity instance is about to enter standby.
******************************************************************************/
-int fvp_affinst_standby(unsigned int power_state)
+void fvp_affinst_standby(unsigned int power_state)
{
- unsigned int target_afflvl;
-
- /* 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 FVP. Ignore any other affinity level.
- */
- if (target_afflvl != MPIDR_AFFLVL0)
- return PSCI_E_INVALID_PARAMS;
-
/*
* Enter standby state
* dsb is good practice before using wfi to enter low power states
*/
dsb();
wfi();
-
- return PSCI_E_SUCCESS;
}
/*******************************************************************************
@@ -190,12 +176,12 @@ int fvp_affinst_on(unsigned long mpidr,
* global variables across calls. It will be wise to do flush a write to the
* global to prevent unpredictable results.
******************************************************************************/
-int fvp_affinst_off(unsigned int afflvl,
+void fvp_affinst_off(unsigned int afflvl,
unsigned int state)
{
/* Determine if any platform actions need to be executed */
if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
- return PSCI_E_SUCCESS;
+ return;
/*
* If execution reaches this stage then this affinity level will be
@@ -207,7 +193,6 @@ int fvp_affinst_off(unsigned int afflvl,
if (afflvl != MPIDR_AFFLVL0)
fvp_cluster_pwrdwn_common();
- return PSCI_E_SUCCESS;
}
/*******************************************************************************
@@ -221,7 +206,7 @@ int fvp_affinst_off(unsigned int afflvl,
* global variables across calls. It will be wise to do flush a write to the
* global to prevent unpredictable results.
******************************************************************************/
-int fvp_affinst_suspend(unsigned long sec_entrypoint,
+void fvp_affinst_suspend(unsigned long sec_entrypoint,
unsigned int afflvl,
unsigned int state)
{
@@ -229,7 +214,7 @@ int fvp_affinst_suspend(unsigned long sec_entrypoint,
/* Determine if any platform actions need to be executed. */
if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
- return PSCI_E_SUCCESS;
+ return;
/* Get the mpidr for this cpu */
mpidr = read_mpidr_el1();
@@ -246,8 +231,6 @@ int fvp_affinst_suspend(unsigned long sec_entrypoint,
/* Perform the common cluster specific operations */
if (afflvl != MPIDR_AFFLVL0)
fvp_cluster_pwrdwn_common();
-
- return PSCI_E_SUCCESS;
}
/*******************************************************************************
@@ -257,15 +240,14 @@ int fvp_affinst_suspend(unsigned long sec_entrypoint,
* was turned off prior to wakeup and do what's necessary to setup it up
* correctly.
******************************************************************************/
-int fvp_affinst_on_finish(unsigned int afflvl,
+void fvp_affinst_on_finish(unsigned int afflvl,
unsigned int state)
{
- int rc = PSCI_E_SUCCESS;
unsigned long mpidr;
/* Determine if any platform actions need to be executed. */
if (fvp_do_plat_actions(afflvl, state) == -EAGAIN)
- return PSCI_E_SUCCESS;
+ return;
/* Get the mpidr for this cpu */
mpidr = read_mpidr_el1();
@@ -301,8 +283,6 @@ int fvp_affinst_on_finish(unsigned int afflvl,
/* TODO: This setup is needed only after a cold boot */
arm_gic_pcpu_distif_setup();
-
- return rc;
}
/*******************************************************************************
@@ -312,10 +292,10 @@ int fvp_affinst_on_finish(unsigned int afflvl,
* TODO: At the moment we reuse the on finisher and reinitialize the secure
* context. Need to implement a separate suspend finisher.
******************************************************************************/
-int fvp_affinst_suspend_finish(unsigned int afflvl,
+void fvp_affinst_suspend_finish(unsigned int afflvl,
unsigned int state)
{
- return fvp_affinst_on_finish(afflvl, state);
+ fvp_affinst_on_finish(afflvl, state);
}
/*******************************************************************************
@@ -342,6 +322,30 @@ static void __dead2 fvp_system_reset(void)
}
/*******************************************************************************
+ * FVP handler called to check the validity of the power state parameter.
+ ******************************************************************************/
+int fvp_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 fvp. 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;
+}
+
+/*******************************************************************************
* Export the platform handlers to enable psci to invoke them
******************************************************************************/
static const plat_pm_ops_t fvp_plat_pm_ops = {
@@ -352,7 +356,8 @@ static const plat_pm_ops_t fvp_plat_pm_ops = {
.affinst_on_finish = fvp_affinst_on_finish,
.affinst_suspend_finish = fvp_affinst_suspend_finish,
.system_off = fvp_system_off,
- .system_reset = fvp_system_reset
+ .system_reset = fvp_system_reset,
+ .validate_power_state = fvp_validate_power_state
};
/*******************************************************************************