PSCI: Introduce new platform and CM helper APIs

This patch introduces new platform APIs and context management helper APIs
to support the new topology framework based on linear core position. This
framework will be introduced in the follwoing patch and it removes the
assumption that the MPIDR based affinity levels map directly to levels
in a power domain tree. The new platforms APIs and context management
helpers based on core position are as described below:

* plat_my_core_pos() and plat_core_pos_by_mpidr()

These 2 new mandatory platform APIs are meant to replace the existing
'platform_get_core_pos()' API. The 'plat_my_core_pos()' API returns the
linear index of the calling core and 'plat_core_pos_by_mpidr()' returns
the linear index of a core specified by its MPIDR. The latter API will also
validate the MPIDR passed as an argument and will return an error code (-1)
if an invalid MPIDR is passed as the argument. This enables the caller to
safely convert an MPIDR of another core to its linear index without querying
the PSCI topology tree e.g. during a call to PSCI CPU_ON.

Since the 'plat_core_pos_by_mpidr()' API verifies an MPIDR, which is always
platform specific, it is no longer possible to maintain a default implementation
of this API. Also it might not be possible for a platform port to verify an
MPIDR before the C runtime has been setup or the topology has been initialized.
This would prevent 'plat_core_pos_by_mpidr()' from being callable prior to
topology setup. As a result, the generic Trusted Firmware code does not call
this API before the topology setup has been done.

The 'plat_my_core_pos' API should be able to run without a C runtime.
Since this API needs to return a core position which is equal to the one
returned by 'plat_core_pos_by_mpidr()' API for the corresponding MPIDR,
this too cannot have default implementation and is a mandatory API for
platform ports. These APIs will be implemented by the ARM reference platform
ports later in the patch stack.

* plat_get_my_stack() and plat_set_my_stack()

These APIs are the stack management APIs which set/return stack addresses
appropriate for the calling core. These replace the 'platform_get_stack()' and
'platform_set_stack()' APIs. A default weak MP version and a global UP version
of these APIs are provided for the platforms.

* Context management helpers based on linear core position

A set of new context management(CM) helpers viz cm_get_context_by_index(),
cm_set_context_by_index(), cm_init_my_context() and cm_init_context_by_index()
are defined which are meant to replace the old helpers which took MPIDR
as argument. The old CM helpers are implemented based on the new helpers to
allow for code consolidation and will be deprecated once the switch to the new
framework is done.

Change-Id: I89758632b370c2812973a4b2efdd9b81a41f9b69
diff --git a/services/std_svc/psci1.0/psci_common.c b/services/std_svc/psci1.0/psci_common.c
index 5557837..d9e9cce 100644
--- a/services/std_svc/psci1.0/psci_common.c
+++ b/services/std_svc/psci1.0/psci_common.c
@@ -264,18 +264,14 @@
 }
 
 /*******************************************************************************
- * Simple routine to determine whether an power domain instance at a given
- * level in an mpidr exists or not.
+ * Simple routine to determine whether a mpidr is valid or not.
  ******************************************************************************/
-int psci_validate_mpidr(unsigned long mpidr, int level)
+int psci_validate_mpidr(unsigned long mpidr)
 {
-	pwr_map_node_t *node;
-
-	node = psci_get_pwr_map_node(mpidr, level);
-	if (node && (node->state & PSCI_PWR_DOMAIN_PRESENT))
-		return PSCI_E_SUCCESS;
-	else
+	if (plat_core_pos_by_mpidr(mpidr) < 0)
 		return PSCI_E_INVALID_PARAMS;
+
+	return PSCI_E_SUCCESS;
 }
 
 /*******************************************************************************
diff --git a/services/std_svc/psci1.0/psci_helpers.S b/services/std_svc/psci1.0/psci_helpers.S
index 07fb889..7ef4cdd 100644
--- a/services/std_svc/psci1.0/psci_helpers.S
+++ b/services/std_svc/psci1.0/psci_helpers.S
@@ -82,8 +82,7 @@
 	 * ---------------------------------------------
 	 */
 do_stack_maintenance:
-	mrs	x0, mpidr_el1
-	bl	platform_get_stack
+	bl	plat_get_my_stack
 
 	/* ---------------------------------------------
 	 * Calculate and store the size of the used
@@ -136,8 +135,7 @@
 	 * stack base address in x0.
 	 * ---------------------------------------------
 	 */
-	mrs	x0, mpidr_el1
-	bl	platform_get_stack
+	bl	plat_get_my_stack
 	mov	x1, sp
 	sub	x1, x0, x1
 	mov	x0, sp
diff --git a/services/std_svc/psci1.0/psci_main.c b/services/std_svc/psci1.0/psci_main.c
index 0421b15..f87fd52 100644
--- a/services/std_svc/psci1.0/psci_main.c
+++ b/services/std_svc/psci1.0/psci_main.c
@@ -50,10 +50,9 @@
 	entry_point_info_t ep;
 
 	/* Determine if the cpu exists of not */
-	rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
-	if (rc != PSCI_E_SUCCESS) {
+	rc = psci_validate_mpidr(target_cpu);
+	if (rc != PSCI_E_SUCCESS)
 		return PSCI_E_INVALID_PARAMS;
-	}
 
 	/* Validate the entrypoint using platform pm_ops */
 	if (psci_plat_pm_ops->validate_ns_entrypoint) {
@@ -287,7 +286,7 @@
 		return PSCI_E_NOT_PRESENT;
 
 	/* Check the validity of the specified target cpu */
-	rc = psci_validate_mpidr(target_cpu, MPIDR_AFFLVL0);
+	rc = psci_validate_mpidr(target_cpu);
 	if (rc != PSCI_E_SUCCESS)
 		return PSCI_E_INVALID_PARAMS;
 
diff --git a/services/std_svc/psci1.0/psci_on.c b/services/std_svc/psci1.0/psci_on.c
index 43f58f9..c78e119 100644
--- a/services/std_svc/psci1.0/psci_on.c
+++ b/services/std_svc/psci1.0/psci_on.c
@@ -147,13 +147,14 @@
 
 	if (rc == PSCI_E_SUCCESS)
 		/* Store the re-entry information for the non-secure world. */
-		cm_init_context(target_cpu, ep);
+		cm_init_context_by_index(target_idx, ep);
 	else
 		/* Restore the state on error. */
 		psci_do_state_coordination(MPIDR_AFFLVL0,
 					  end_pwrlvl,
 					  target_cpu_nodes,
 					  PSCI_STATE_OFF);
+
 exit:
 	/*
 	 * This loop releases the lock corresponding to each power level
diff --git a/services/std_svc/psci1.0/psci_private.h b/services/std_svc/psci1.0/psci_private.h
index e56d848..79909a8 100644
--- a/services/std_svc/psci1.0/psci_private.h
+++ b/services/std_svc/psci1.0/psci_private.h
@@ -123,7 +123,7 @@
 unsigned short psci_get_phys_state(pwr_map_node_t *node);
 void psci_set_state(pwr_map_node_t *node, unsigned short state);
 unsigned long mpidr_set_pwr_domain_inst(unsigned long, unsigned char, int);
-int psci_validate_mpidr(unsigned long, int);
+int psci_validate_mpidr(unsigned long mpidr);
 int get_power_on_target_pwrlvl(void);
 void psci_power_up_finish(int end_pwrlvl,
 				 pwrlvl_power_on_finisher_t pon_handler);
diff --git a/services/std_svc/psci1.0/psci_setup.c b/services/std_svc/psci1.0/psci_setup.c
index 002e220..b1eef69 100644
--- a/services/std_svc/psci1.0/psci_setup.c
+++ b/services/std_svc/psci1.0/psci_setup.c
@@ -193,36 +193,39 @@
 	state = plat_get_pwr_domain_state(level, mpidr);
 	psci_pwr_domain_map[idx].state = state;
 
-	if (level == MPIDR_AFFLVL0) {
+	/*
+	 * Check if this is a CPU node and is present in which case certain
+	 * other initialisations are required.
+	 */
+	if (level != MPIDR_AFFLVL0)
+		return;
 
-		/*
-		 * Mark the cpu as OFF. Higher power level reference counts
-		 * have already been memset to 0
-		 */
-		if (state & PSCI_PWR_DOMAIN_PRESENT)
-			psci_set_state(&psci_pwr_domain_map[idx],
-						PSCI_STATE_OFF);
+	if (!(state & PSCI_PWR_DOMAIN_PRESENT))
+		return;
 
-		/*
-		 * Associate a non-secure context with this power
-		 * instance through the context management library.
-		 */
-		linear_id = platform_get_core_pos(mpidr);
-		assert(linear_id < PLATFORM_CORE_COUNT);
+	/*
+	 * Mark the cpu as OFF. Higher power level reference counts
+	 * have already been memset to 0
+	 */
+	psci_set_state(&psci_pwr_domain_map[idx], PSCI_STATE_OFF);
 
-		/* Invalidate the suspend context for the node */
-		set_cpu_data_by_index(linear_id,
-				      psci_svc_cpu_data.power_state,
-				      PSCI_INVALID_DATA);
+	/*
+	 * Associate a non-secure context with this power
+	 * instance through the context management library.
+	 */
+	linear_id = plat_core_pos_by_mpidr(mpidr);
+	assert(linear_id < PLATFORM_CORE_COUNT);
 
-		flush_cpu_data_by_index(linear_id, psci_svc_cpu_data);
+	/* Invalidate the suspend context for the node */
+	set_cpu_data_by_index(linear_id,
+			      psci_svc_cpu_data.power_state,
+			      PSCI_INVALID_DATA);
 
-		cm_set_context_by_mpidr(mpidr,
-					(void *) &psci_ns_context[linear_id],
-					NON_SECURE);
-	}
+	flush_cpu_data_by_index(linear_id, psci_svc_cpu_data);
 
-	return;
+	cm_set_context_by_index(linear_id,
+				(void *) &psci_ns_context[linear_id],
+				NON_SECURE);
 }
 
 /*******************************************************************************
diff --git a/services/std_svc/psci1.0/psci_suspend.c b/services/std_svc/psci1.0/psci_suspend.c
index 7832b82..3d1bf09 100644
--- a/services/std_svc/psci1.0/psci_suspend.c
+++ b/services/std_svc/psci1.0/psci_suspend.c
@@ -90,7 +90,7 @@
 {
 	unsigned int power_state;
 
-	power_state = get_cpu_data_by_mpidr(mpidr,
+	power_state = get_cpu_data_by_index(plat_core_pos_by_mpidr(mpidr),
 					    psci_svc_cpu_data.power_state);
 
 	return ((power_state == PSCI_INVALID_DATA) ?
@@ -185,7 +185,7 @@
 	/*
 	 * Store the re-entry information for the non-secure world.
 	 */
-	cm_init_context(read_mpidr_el1(), ep);
+	cm_init_my_context(ep);
 
 	/* Set the secure world (EL3) re-entry point after BL1 */
 	psci_entrypoint = (unsigned long) psci_cpu_suspend_finish_entry;