Fix CPU_SUSPEND when invoked with affinity level higher than get_max_afflvl()
authorSoby Mathew <soby.mathew@arm.com>
Thu, 2 Oct 2014 16:24:19 +0000 (17:24 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Fri, 12 Dec 2014 13:53:07 +0000 (13:53 +0000)
This patch fixes the assertion failure when CPU_SUSPEND is invoked with
an affinity level higher than supported by the platform by adding suitable
checks for affinity level within `psci_cpu_suspend`. Also added suitable
bound checks within `psci_aff_map_get_idx` to prevent indexing beyond array
limits.

Fixes ARM-software/tf-issues#260

Change-Id: I04b75c49729e6c6d1983add590f60146c8fc3630

services/std_svc/psci/psci_common.c
services/std_svc/psci/psci_main.c
services/std_svc/psci/psci_setup.c

index 2267ad089e423f32d940ac19c30f8bcbc3d54e5d..155f842e26fb6f41360061bd4e0230e608f1208d 100644 (file)
@@ -201,7 +201,7 @@ unsigned long mpidr_set_aff_inst(unsigned long mpidr,
 int psci_check_afflvl_range(int start_afflvl, int end_afflvl)
 {
        /* Sanity check the parameters passed */
-       if (end_afflvl > MPIDR_MAX_AFFLVL)
+       if (end_afflvl > get_max_afflvl())
                return PSCI_E_INVALID_PARAMS;
 
        if (start_afflvl < MPIDR_AFFLVL0)
index 0ffa5d739ea8c46b0ecdbf5f90d51968ceecd669..2e700e8ae11d6a52b083ff75bafd4057a103fae3 100644 (file)
@@ -86,7 +86,7 @@ int psci_cpu_suspend(unsigned int power_state,
 
        /* Sanity check the requested state */
        target_afflvl = psci_get_pstate_afflvl(power_state);
-       if (target_afflvl > MPIDR_MAX_AFFLVL)
+       if (target_afflvl > get_max_afflvl())
                return PSCI_E_INVALID_PARAMS;
 
        /* Determine the 'state type' in the 'power_state' parameter */
index a5ae4ef5dd53b8324315bf154fd3da041588a4be..8e9d15dc0564a4ab6e0532d25c7448fbe32b32dd 100644 (file)
@@ -76,6 +76,11 @@ static int psci_aff_map_get_idx(unsigned long key,
        if (max_idx < min_idx)
                return PSCI_E_INVALID_PARAMS;
 
+       /*
+        * Make sure we are within array limits.
+        */
+       assert(min_idx >= 0 && max_idx < PSCI_NUM_AFFS);
+
        /*
         * Bisect the array around 'mid' and then recurse into the array chunk
         * where the key is likely to be found. The mpidrs in each node in the
@@ -83,6 +88,7 @@ static int psci_aff_map_get_idx(unsigned long key,
         * order which makes the binary search possible.
         */
        mid = min_idx + ((max_idx - min_idx) >> 1);     /* Divide by 2 */
+
        if (psci_aff_map[mid].mpidr > key)
                return psci_aff_map_get_idx(key, min_idx, mid - 1);
        else if (psci_aff_map[mid].mpidr < key)
@@ -95,6 +101,9 @@ aff_map_node_t *psci_get_aff_map_node(unsigned long mpidr, int aff_lvl)
 {
        int rc;
 
+       if (aff_lvl > get_max_afflvl())
+               return NULL;
+
        /* Right shift the mpidr to the required affinity level */
        mpidr = mpidr_mask_lower_afflvls(mpidr, aff_lvl);