Add support for handling runtime service requests

This patch uses the reworked exception handling support to handle
runtime service requests through SMCs following the SMC calling
convention. This is a giant commit since all the changes are
inter-related. It does the following:

1. Replace the old exception handling mechanism with the new one
2. Enforce that SP_EL0 is used C runtime stacks.
3. Ensures that the cold and warm boot paths use the 'cpu_context'
   structure to program an ERET into the next lower EL.
4. Ensures that SP_EL3 always points to the next 'cpu_context'
   structure prior to an ERET into the next lower EL
5. Introduces a PSCI SMC handler which completes the use of PSCI as a
   runtime service

Change-Id: I661797f834c0803d2c674d20f504df1b04c2b852
Co-authored-by: Achin Gupta <achin.gupta@arm.com>
diff --git a/common/psci/psci_common.c b/common/psci/psci_common.c
index 193655d..214db78 100644
--- a/common/psci/psci_common.c
+++ b/common/psci/psci_common.c
@@ -36,6 +36,7 @@
 #include <platform.h>
 #include <psci.h>
 #include <psci_private.h>
+#include <context_mgmt.h>
 #include <runtime_svc.h>
 #include "debug.h"
 
@@ -86,7 +87,8 @@
 	unsigned int state;
 
 	/* Retrieve our node from the topology tree */
-	node = psci_get_aff_map_node(mpidr & MPIDR_AFFINITY_MASK, MPIDR_AFFLVL0);
+	node = psci_get_aff_map_node(mpidr & MPIDR_AFFINITY_MASK,
+			MPIDR_AFFLVL0);
 	assert(node);
 
 	/*
@@ -222,13 +224,12 @@
 void psci_get_ns_entry_info(unsigned int index)
 {
 	unsigned long sctlr = 0, scr, el_status, id_aa64pfr0;
-	gp_regs *ns_gp_regs;
+	uint64_t mpidr = read_mpidr();
+	cpu_context *ns_entry_context;
+	gp_regs *ns_entry_gpregs;
 
 	scr = read_scr();
 
-	/* Switch to the non-secure view of the registers */
-	write_scr(scr | SCR_NS_BIT);
-
 	/* Find out which EL we are going to */
 	id_aa64pfr0 = read_id_aa64pfr0_el1();
 	el_status = (id_aa64pfr0 >> ID_AA64PFR0_EL2_SHIFT) &
@@ -257,23 +258,29 @@
 		write_sctlr_el1(sctlr);
 
 	/* Fulfill the cpu_on entry reqs. as per the psci spec */
-	write_scr(scr);
-	write_elr(psci_ns_entry_info[index].eret_info.entrypoint);
+	ns_entry_context = (cpu_context *) cm_get_context(mpidr, NON_SECURE);
+	assert(ns_entry_context);
 
 	/*
-	 * Set the general purpose registers to ~0 upon entry into the
-	 * non-secure world except for x0 which should contain the
-	 * context id & spsr. This is done directly on the "would be"
-	 * stack pointer. Prior to entry into the non-secure world, an
-	 * offset equivalent to the size of the 'gp_regs' structure is
-	 * added to the sp. This general purpose register context is
-	 * retrieved then.
+	 * Setup general purpose registers to return the context id and
+	 * prevent leakage of secure information into the normal world.
 	 */
-	ns_gp_regs = (gp_regs *) platform_get_stack(read_mpidr());
-	ns_gp_regs--;
-	memset(ns_gp_regs, ~0, sizeof(*ns_gp_regs));
-	ns_gp_regs->x0 = psci_ns_entry_info[index].context_id;
-	ns_gp_regs->spsr = psci_ns_entry_info[index].eret_info.spsr;
+	ns_entry_gpregs = get_gpregs_ctx(ns_entry_context);
+	write_ctx_reg(ns_entry_gpregs,
+		      CTX_GPREG_X0,
+		      psci_ns_entry_info[index].context_id);
+
+	/*
+	 * Tell the context management library to setup EL3 system registers to
+	 * be able to ERET into the ns state, and SP_EL3 points to the right
+	 * context to exit from EL3 correctly.
+	 */
+	cm_set_el3_eret_context(NON_SECURE,
+			psci_ns_entry_info[index].eret_info.entrypoint,
+			psci_ns_entry_info[index].eret_info.spsr,
+			scr);
+
+	cm_set_next_eret_context(NON_SECURE);
 }
 
 /*******************************************************************************
@@ -344,7 +351,7 @@
 		 */
 		spsr |= DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;
 		spsr <<= PSR_DAIF_SHIFT;
-		if(ee)
+		if (ee)
 			spsr |= SPSR32_EE_BIT;
 		spsr |= mode;
 
@@ -500,7 +507,7 @@
 	mpidr_aff_map_nodes mpidr_nodes;
 	int rc;
 
-	mpidr &= MPIDR_AFFINITY_MASK;;
+	mpidr &= MPIDR_AFFINITY_MASK;
 
 	/*
 	 * Collect the pointers to the nodes in the topology tree for