summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm64/boot.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/arch/arm64/boot.c b/src/arch/arm64/boot.c
index 5217a9f3b0..91980fbf19 100644
--- a/src/arch/arm64/boot.c
+++ b/src/arch/arm64/boot.c
@@ -18,17 +18,36 @@
*/
#include <arch/cache.h>
+#include <arch/lib_helpers.h>
#include <arch/stages.h>
+#include <arch/transition.h>
#include <cbmem.h>
#include <console/console.h>
#include <program_loading.h>
+#include <string.h>
void arch_payload_run(const struct payload *payload)
{
void (*doit)(void *) = payload->entry;
void *cb_tables = cbmem_find(CBMEM_ID_CBTABLE);
+ uint8_t current_el = get_current_el();
printk(BIOS_SPEW, "entry = %p\n", payload->entry);
+
+ /* If current EL is not EL3, jump to payload at same EL. */
+ if (current_el != EL3) {
+ cache_sync_instructions();
+ /* Point of no-return */
+ doit(cb_tables);
+ }
+
+ /* If current EL is EL3, we transition to payload in EL2. */
+ struct exc_state exc_state;
+
+ memset(&exc_state, 0, sizeof(exc_state));
+
+ exc_state.elx.spsr = get_eret_el(EL2, SPSR_USE_L);
+
cache_sync_instructions();
- doit(cb_tables);
+ transition_with_entry(payload->entry, cb_tables, &exc_state);
}