Initialise CPU contexts from entry_point_info
Consolidate all BL3-1 CPU context initialization for cold boot, PSCI
and SPDs into two functions:
* The first uses entry_point_info to initialize the relevant
cpu_context for first entry into a lower exception level on a CPU
* The second populates the EL1 and EL2 system registers as needed
from the cpu_context to ensure correct entry into the lower EL
This patch alters the way that BL3-1 determines which exception level
is used when first entering EL1 or EL2 during cold boot - this is now
fully determined by the SPSR value in the entry_point_info for BL3-3,
as set up by the platform code in BL2 (or otherwise provided to BL3-1).
In the situation that EL1 (or svc mode) is selected for a processor
that supports EL2, the context management code will now configure all
essential EL2 register state to ensure correct execution of EL1. This
allows the platform code to run non-secure EL1 payloads directly
without requiring a small EL2 stub or OS loader.
Change-Id: If9fbb2417e82d2226e47568203d5a369f39d3b0f
diff --git a/services/std_svc/psci/psci_afflvl_suspend.c b/services/std_svc/psci/psci_afflvl_suspend.c
index 9934310..f43dced 100644
--- a/services/std_svc/psci/psci_afflvl_suspend.c
+++ b/services/std_svc/psci/psci_afflvl_suspend.c
@@ -132,10 +132,12 @@
unsigned long context_id,
unsigned int power_state)
{
- unsigned int index, plat_state;
+ unsigned int plat_state;
unsigned long psci_entrypoint, sctlr;
el3_state_t *saved_el3_state;
- int rc = PSCI_E_SUCCESS;
+ uint32_t ns_scr_el3 = read_scr_el3();
+ uint32_t ns_sctlr_el1 = read_sctlr_el1();
+ int rc;
/* Sanity check to safeguard against data corruption */
assert(cpu_node->level == MPIDR_AFFLVL0);
@@ -163,8 +165,8 @@
* Generic management: Store the re-entry information for the
* non-secure world
*/
- index = cpu_node->data;
- rc = psci_set_ns_entry_info(index, ns_entrypoint, context_id);
+ rc = psci_save_ns_entry(read_mpidr_el1(), ns_entrypoint, context_id,
+ ns_scr_el3, ns_sctlr_el1);
if (rc != PSCI_E_SUCCESS)
return rc;
@@ -174,7 +176,6 @@
* L1 caches and exit intra-cluster coherency et al
*/
cm_el3_sysregs_context_save(NON_SECURE);
- rc = PSCI_E_SUCCESS;
/*
* The EL3 state to PoC since it will be accessed after a
@@ -214,6 +215,8 @@
* platform defined mailbox with the psci entrypoint,
* program the power controller etc.
*/
+ rc = PSCI_E_SUCCESS;
+
if (psci_plat_pm_ops->affinst_suspend) {
plat_state = psci_get_phys_state(cpu_node);
rc = psci_plat_pm_ops->affinst_suspend(mpidr,
@@ -454,7 +457,7 @@
static unsigned int psci_afflvl0_suspend_finish(unsigned long mpidr,
aff_map_node_t *cpu_node)
{
- unsigned int index, plat_state, state, rc = PSCI_E_SUCCESS;
+ unsigned int plat_state, state, rc;
int32_t suspend_level;
assert(cpu_node->level == MPIDR_AFFLVL0);
@@ -481,14 +484,11 @@
}
/* Get the index for restoring the re-entry information */
- index = cpu_node->data;
-
/*
* Arch. management: Restore the stashed EL3 architectural
* context from the 'cpu_context' structure for this cpu.
*/
cm_el3_sysregs_context_restore(NON_SECURE);
- rc = PSCI_E_SUCCESS;
/*
* Call the cpu suspend finish handler registered by the Secure Payload
@@ -509,7 +509,7 @@
* information that we had stashed away during the suspend
* call to set this cpu on its way.
*/
- psci_get_ns_entry_info(index);
+ cm_prepare_el3_exit(NON_SECURE);
/* State management: mark this cpu as on */
psci_set_state(cpu_node, PSCI_STATE_ON);
@@ -517,6 +517,7 @@
/* Clean caches before re-entering normal world */
dcsw_op_louis(DCCSW);
+ rc = PSCI_E_SUCCESS;
return rc;
}