summaryrefslogtreecommitdiff
path: root/bl31
diff options
context:
space:
mode:
Diffstat (limited to 'bl31')
-rw-r--r--bl31/aarch64/bl31_arch_setup.c14
-rw-r--r--bl31/aarch64/bl31_entrypoint.S61
-rw-r--r--bl31/aarch64/context.S44
-rw-r--r--bl31/aarch64/crash_reporting.S561
-rw-r--r--bl31/aarch64/runtime_exceptions.S31
-rw-r--r--bl31/bl31.mk1
-rw-r--r--bl31/cpu_data_array.c8
7 files changed, 368 insertions, 352 deletions
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c
index e0382b33..f67881e6 100644
--- a/bl31/aarch64/bl31_arch_setup.c
+++ b/bl31/aarch64/bl31_arch_setup.c
@@ -42,21 +42,12 @@
******************************************************************************/
void bl31_arch_setup(void)
{
- unsigned long tmp_reg = 0;
- uint64_t counter_freq;
-
- /* Enable alignment checks */
- tmp_reg = read_sctlr_el3();
- tmp_reg |= (SCTLR_A_BIT | SCTLR_SA_BIT);
- write_sctlr_el3(tmp_reg);
-
/*
* Route external abort and SError interrupts to EL3
* other SCR bits will be configured before exiting to a lower exception
* level
*/
- tmp_reg = SCR_RES1_BITS | SCR_EA_BIT;
- write_scr(tmp_reg);
+ write_scr_el3(SCR_RES1_BITS | SCR_EA_BIT);
/*
* Enable SError and Debug exceptions
@@ -65,6 +56,5 @@ void bl31_arch_setup(void)
enable_debug_exceptions();
/* Program the counter frequency */
- counter_freq = plat_get_syscnt_freq();
- write_cntfrq_el0(counter_freq);
+ write_cntfrq_el0(plat_get_syscnt_freq());
}
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 6e48e313..fb8fd2c4 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -52,6 +52,15 @@ func bl31_entrypoint
mov x20, x0
mov x21, x1
#else
+ /* ---------------------------------------------
+ * Set the CPU endianness before doing anything
+ * that might involve memory reads or writes.
+ * ---------------------------------------------
+ */
+ mrs x0, sctlr_el3
+ bic x0, x0, #SCTLR_EE_BIT
+ msr sctlr_el3, x0
+ isb
/* -----------------------------------------------------
* Perform any processor specific actions upon reset
@@ -61,24 +70,34 @@ func bl31_entrypoint
*/
bl cpu_reset_handler
#endif
-
/* ---------------------------------------------
- * Enable the instruction cache.
+ * Enable the instruction cache, stack pointer
+ * and data access alignment checks
* ---------------------------------------------
*/
- mrs x1, sctlr_el3
- orr x1, x1, #SCTLR_I_BIT
- msr sctlr_el3, x1
+ mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
+ mrs x0, sctlr_el3
+ orr x0, x0, x1
+ msr sctlr_el3, x0
isb
/* ---------------------------------------------
- * Set the exception vector and zero tpidr_el3
- * until the crash reporting is set up
+ * Initialise cpu_data early to enable crash
+ * reporting to have access to crash stack.
+ * Since crash reporting depends on cpu_data to
+ * report the unhandled exception, not
+ * doing so can lead to recursive exceptions due
+ * to a NULL TPIDR_EL3
+ * ---------------------------------------------
+ */
+ bl init_cpu_data_ptr
+
+ /* ---------------------------------------------
+ * Set the exception vector.
* ---------------------------------------------
*/
adr x1, runtime_exceptions
msr vbar_el3, x1
- msr tpidr_el3, xzr
/* ---------------------------------------------------------------------
* The initial state of the Architectural feature trap register
@@ -137,27 +156,21 @@ func bl31_entrypoint
bl zeromem16
/* ---------------------------------------------
- * Initialise cpu_data and crash reporting
- * ---------------------------------------------
- */
-#if CRASH_REPORTING
- bl init_crash_reporting
-#endif
- bl init_cpu_data_ptr
-
- /* ---------------------------------------------
* Use SP_EL0 for the C runtime stack.
* ---------------------------------------------
*/
msr spsel, #0
/* --------------------------------------------
- * Give ourselves a small coherent stack to
- * ease the pain of initializing the MMU
+ * Allocate a stack whose memory will be marked
+ * as Normal-IS-WBWA when the MMU is enabled.
+ * There is no risk of reading stale stack
+ * memory after enabling the MMU as only the
+ * primary cpu is running at the moment.
* --------------------------------------------
*/
mrs x0, mpidr_el1
- bl platform_set_coherent_stack
+ bl platform_set_stack
/* ---------------------------------------------
* Perform platform specific early arch. setup
@@ -175,14 +188,6 @@ func bl31_entrypoint
bl bl31_plat_arch_setup
/* ---------------------------------------------
- * Give ourselves a stack allocated in Normal
- * -IS-WBWA memory
- * ---------------------------------------------
- */
- mrs x0, mpidr_el1
- bl platform_set_stack
-
- /* ---------------------------------------------
* Jump to main function.
* ---------------------------------------------
*/
diff --git a/bl31/aarch64/context.S b/bl31/aarch64/context.S
index 26982157..79b5d19c 100644
--- a/bl31/aarch64/context.S
+++ b/bl31/aarch64/context.S
@@ -43,23 +43,9 @@
.global el3_sysregs_context_save
func el3_sysregs_context_save
- mrs x10, sctlr_el3
- str x10, [x0, #CTX_SCTLR_EL3]
-
- mrs x11, cptr_el3
- stp x11, xzr, [x0, #CTX_CPTR_EL3]
-
- mrs x13, cntfrq_el0
- mrs x14, mair_el3
- stp x13, x14, [x0, #CTX_CNTFRQ_EL0]
-
- mrs x15, tcr_el3
- mrs x16, ttbr0_el3
- stp x15, x16, [x0, #CTX_TCR_EL3]
-
- mrs x17, daif
- and x17, x17, #(DAIF_ABT_BIT | DAIF_DBG_BIT)
- stp x17, xzr, [x0, #CTX_DAIF_EL3]
+ mrs x10, cptr_el3
+ mrs x11, cntfrq_el0
+ stp x10, x11, [x0, #CTX_CPTR_EL3]
ret
@@ -78,27 +64,9 @@ func el3_sysregs_context_save
.global el3_sysregs_context_restore
func el3_sysregs_context_restore
- ldp x11, xzr, [x0, #CTX_CPTR_EL3]
- msr cptr_el3, x11
-
- ldp x13, x14, [x0, #CTX_CNTFRQ_EL0]
- msr cntfrq_el0, x13
- msr mair_el3, x14
-
- ldp x15, x16, [x0, #CTX_TCR_EL3]
- msr tcr_el3, x15
- msr ttbr0_el3, x16
-
- ldp x17, xzr, [x0, #CTX_DAIF_EL3]
- mrs x11, daif
- orr x17, x17, x11
- msr daif, x17
-
- /* Make sure all the above changes are observed */
- isb
-
- ldr x10, [x0, #CTX_SCTLR_EL3]
- msr sctlr_el3, x10
+ ldp x13, x14, [x0, #CTX_CPTR_EL3]
+ msr cptr_el3, x13
+ msr cntfrq_el0, x14
isb
ret
diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S
index 1118e968..e69878b2 100644
--- a/bl31/aarch64/crash_reporting.S
+++ b/bl31/aarch64/crash_reporting.S
@@ -34,11 +34,13 @@
#include <plat_macros.S>
#include <platform_def.h>
- .globl dump_state_and_die
- .globl dump_intr_state_and_die
- .globl init_crash_reporting
+ .globl report_unhandled_exception
+ .globl report_unhandled_interrupt
+ .globl el3_panic
#if CRASH_REPORTING
+#define REG_SIZE 0x8
+
/* ------------------------------------------------------
* The below section deals with dumping the system state
* when an unhandled exception is taken in EL3.
@@ -46,267 +48,326 @@
* be dumped during a unhandled exception is given below.
* ------------------------------------------------------
*/
-.section .rodata.dump_reg_name, "aS"
-caller_saved_regs: .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
- "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16",\
- "x17", "x18", ""
-
-callee_saved_regs: .asciz "x19", "x20", "x21", "x22", "x23", "x24",\
- "x25", "x26", "x27", "x28", "x29", "x30", ""
-
-el3_sys_regs: .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
- "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3", "esr_el3",\
- "sp_el3", "far_el3", ""
-
-non_el3_sys_0_regs: .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
- "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
- "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
- "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", ""
-
-non_el3_sys_1_regs: .asciz "tpidr_el0", "tpidrro_el0", "dacr32_el2",\
- "ifsr32_el2", "par_el1", "far_el1", "afsr0_el1", "afsr1_el1",\
- "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\
- "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2",\
- "sp_el0", ""
-
- /* -----------------------------------------------------
- * Currently we are stack limited. Hence make sure that
- * we dont try to dump more than 20 registers using the
- * stack.
- * -----------------------------------------------------
+.section .rodata.crash_prints, "aS"
+print_spacer:
+ .asciz " =\t\t0x"
+
+cpu_ectlr_reg:
+ .asciz "cpuectlr_el1 =\t\t0x"
+
+gp_regs:
+ .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\
+ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22",\
+ "x23", "x24", "x25", "x26", "x27", "x28", "x29", ""
+el3_sys_regs:
+ .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\
+ "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\
+ "esr_el3", "far_el3", ""
+
+non_el3_sys_regs:
+ .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\
+ "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\
+ "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\
+ "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\
+ "tpidrro_el0", "dacr32_el2", "ifsr32_el2", "par_el1",\
+ "mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\
+ "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\
+ "cntv_cval_el0", "cntkctl_el1", "fpexc32_el2", "sp_el0", ""
+
+panic_msg:
+ .asciz "PANIC in EL3 at x30 = 0x"
+excpt_msg:
+ .asciz "Unhandled Exception in EL3.\nx30 =\t\t0x"
+intr_excpt_msg:
+ .asciz "Unhandled Interrupt Exception in EL3.\nx30 =\t\t0x"
+
+ /*
+ * Helper function to print newline to console.
*/
+func print_newline
+ mov x0, '\n'
+ b plat_crash_console_putc
+
+ /*
+ * Helper function to print from crash buf.
+ * The print loop is controlled by the buf size and
+ * ascii reg name list which is passed in x6. The
+ * function returns the crash buf address in x0.
+ * Clobbers : x0 - x7, sp
+ */
+func size_controlled_print
+ /* Save the lr */
+ mov sp, x30
+ /* load the crash buf address */
+ mrs x7, tpidr_el3
+test_size_list:
+ /* Calculate x5 always as it will be clobbered by asm_print_hex */
+ mrs x5, tpidr_el3
+ add x5, x5, #CPU_DATA_CRASH_BUF_SIZE
+ /* Test whether we have reached end of crash buf */
+ cmp x7, x5
+ b.eq exit_size_print
+ ldrb w4, [x6]
+ /* Test whether we are at end of list */
+ cbz w4, exit_size_print
+ mov x4, x6
+ /* asm_print_str updates x4 to point to next entry in list */
+ bl asm_print_str
+ /* update x6 with the updated list pointer */
+ mov x6, x4
+ adr x4, print_spacer
+ bl asm_print_str
+ ldr x4, [x7], #REG_SIZE
+ bl asm_print_hex
+ bl print_newline
+ b test_size_list
+exit_size_print:
+ mov x30, sp
+ ret
+
+ /*
+ * Helper function to store x8 - x15 registers to
+ * the crash buf. The system registers values are
+ * copied to x8 to x15 by the caller which are then
+ * copied to the crash buf by this function.
+ * x0 points to the crash buf. It then calls
+ * size_controlled_print to print to console.
+ * Clobbers : x0 - x7, sp
+ */
+func str_in_crash_buf_print
+ /* restore the crash buf address in x0 */
+ mrs x0, tpidr_el3
+ stp x8, x9, [x0]
+ stp x10, x11, [x0, #REG_SIZE * 2]
+ stp x12, x13, [x0, #REG_SIZE * 4]
+ stp x14, x15, [x0, #REG_SIZE * 6]
+ b size_controlled_print
-#define REG_SIZE 0x8
-
-/* The caller saved registers are X0 to X18 */
-#define CALLER_SAVED_REG_SIZE (20 * REG_SIZE)
-/* The caller saved registers are X19 to X30 */
-#define CALLEE_SAVED_REG_SIZE (12 * REG_SIZE)
-/* The EL3 sys regs*/
-#define EL3_SYS_REG_SIZE (12 * REG_SIZE)
-/* The non EL3 sys regs set-0 */
-#define NON_EL3_SYS_0_REG_SIZE (18 * REG_SIZE)
-/* The non EL3 sys regs set-1 */
-#define NON_EL3_SYS_1_REG_SIZE (18 * REG_SIZE)
-
- .macro print_caller_saved_regs
- sub sp, sp, #CALLER_SAVED_REG_SIZE
- stp x0, x1, [sp]
- stp x2, x3, [sp, #(REG_SIZE * 2)]
- stp x4, x5, [sp, #(REG_SIZE * 4)]
- stp x6, x7, [sp, #(REG_SIZE * 6)]
- stp x8, x9, [sp, #(REG_SIZE * 8)]
- stp x10, x11, [sp, #(REG_SIZE * 10)]
- stp x12, x13, [sp, #(REG_SIZE * 12)]
- stp x14, x15, [sp, #(REG_SIZE * 14)]
- stp x16, x17, [sp, #(REG_SIZE * 16)]
- stp x18, xzr, [sp, #(REG_SIZE * 18)]
- adr x0, caller_saved_regs
- mov x1, sp
- bl print_string_value
- add sp, sp, #CALLER_SAVED_REG_SIZE
- .endm
-
- .macro print_callee_saved_regs
- sub sp, sp, CALLEE_SAVED_REG_SIZE
- stp x19, x20, [sp]
- stp x21, x22, [sp, #(REG_SIZE * 2)]
- stp x23, x24, [sp, #(REG_SIZE * 4)]
- stp x25, x26, [sp, #(REG_SIZE * 6)]
- stp x27, x28, [sp, #(REG_SIZE * 8)]
- stp x29, x30, [sp, #(REG_SIZE * 10)]
- adr x0, callee_saved_regs
+ /* ------------------------------------------------------
+ * This macro calculates the offset to crash buf from
+ * cpu_data and stores it in tpidr_el3. It also saves x0
+ * and x1 in the crash buf by using sp as a temporary
+ * register.
+ * ------------------------------------------------------
+ */
+ .macro prepare_crash_buf_save_x0_x1
+ /* we can corrupt this reg to free up x0 */
+ mov sp, x0
+ /* tpidr_el3 contains the address to cpu_data structure */
+ mrs x0, tpidr_el3
+ /* Calculate the Crash buffer offset in cpu_data */
+ add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET
+ /* Store crash buffer address in tpidr_el3 */
+ msr tpidr_el3, x0
+ str x1, [x0, #REG_SIZE]
mov x1, sp
- bl print_string_value
- add sp, sp, #CALLEE_SAVED_REG_SIZE
+ str x1, [x0]
.endm
- .macro print_el3_sys_regs
- sub sp, sp, #EL3_SYS_REG_SIZE
- mrs x9, scr_el3
- mrs x10, sctlr_el3
- mrs x11, cptr_el3
- mrs x12, tcr_el3
- mrs x13, daif
- mrs x14, mair_el3
- mrs x15, spsr_el3 /*save the elr and spsr regs seperately*/
- mrs x16, elr_el3
- mrs x17, ttbr0_el3
- mrs x8, esr_el3
- mrs x7, far_el3
-
- stp x9, x10, [sp]
- stp x11, x12, [sp, #(REG_SIZE * 2)]
- stp x13, x14, [sp, #(REG_SIZE * 4)]
- stp x15, x16, [sp, #(REG_SIZE * 6)]
- stp x17, x8, [sp, #(REG_SIZE * 8)]
- stp x0, x7, [sp, #(REG_SIZE * 10)] /* sp_el3 is in x0 */
-
- adr x0, el3_sys_regs
- mov x1, sp
- bl print_string_value
- add sp, sp, #EL3_SYS_REG_SIZE
- .endm
+ /* -----------------------------------------------------
+ * This function allows to report a crash (if crash
+ * reporting is enabled) when an unhandled exception
+ * occurs. It prints the CPU state via the crash console
+ * making use of the crash buf. This function will
+ * not return.
+ * -----------------------------------------------------
+ */
+func report_unhandled_exception
+ prepare_crash_buf_save_x0_x1
+ adr x0, excpt_msg
+ mov sp, x0
+ /* This call will not return */
+ b do_crash_reporting
- .macro print_non_el3_sys_0_regs
- sub sp, sp, #NON_EL3_SYS_0_REG_SIZE
- mrs x9, spsr_el1
- mrs x10, elr_el1
- mrs x11, spsr_abt
- mrs x12, spsr_und
- mrs x13, spsr_irq
- mrs x14, spsr_fiq
- mrs x15, sctlr_el1
- mrs x16, actlr_el1
- mrs x17, cpacr_el1
- mrs x8, csselr_el1
- stp x9, x10, [sp]
- stp x11, x12, [sp, #(REG_SIZE * 2)]
- stp x13, x14, [sp, #(REG_SIZE * 4)]
- stp x15, x16, [sp, #(REG_SIZE * 6)]
- stp x17, x8, [sp, #(REG_SIZE * 8)]
+ /* -----------------------------------------------------
+ * This function allows to report a crash (if crash
+ * reporting is enabled) when an unhandled interrupt
+ * occurs. It prints the CPU state via the crash console
+ * making use of the crash buf. This function will
+ * not return.
+ * -----------------------------------------------------
+ */
+func report_unhandled_interrupt
+ prepare_crash_buf_save_x0_x1
+ adr x0, intr_excpt_msg
+ mov sp, x0
+ /* This call will not return */
+ b do_crash_reporting
+ /* -----------------------------------------------------
+ * This function allows to report a crash (if crash
+ * reporting is enabled) when panic() is invoked from
+ * C Runtime. It prints the CPU state via the crash
+ * console making use of the crash buf. This function
+ * will not return.
+ * -----------------------------------------------------
+ */
+func el3_panic
+ msr spsel, #1
+ prepare_crash_buf_save_x0_x1
+ adr x0, panic_msg
+ mov sp, x0
+ /* This call will not return */
+ b do_crash_reporting
+
+ /* ------------------------------------------------------------
+ * The common crash reporting functionality. It requires x0
+ * and x1 has already been stored in crash buf, sp points to
+ * crash message and tpidr_el3 contains the crash buf address.
+ * The function does the following:
+ * - Retrieve the crash buffer from tpidr_el3
+ * - Store x2 to x6 in the crash buffer
+ * - Initialise the crash console.
+ * - Print the crash message by using the address in sp.
+ * - Print x30 value to the crash console.
+ * - Print x0 - x7 from the crash buf to the crash console.
+ * - Print x8 - x29 (in groups of 8 registers) using the
+ * crash buf to the crash console.
+ * - Print el3 sys regs (in groups of 8 registers) using the
+ * crash buf to the crash console.
+ * - Print non el3 sys regs (in groups of 8 registers) using
+ * the crash buf to the crash console.
+ * ------------------------------------------------------------
+ */
+func do_crash_reporting
+ /* Retrieve the crash buf from tpidr_el3 */
+ mrs x0, tpidr_el3
+ /* Store x2 - x6, x30 in the crash buffer */
+ stp x2, x3, [x0, #REG_SIZE * 2]
+ stp x4, x5, [x0, #REG_SIZE * 4]
+ stp x6, x30, [x0, #REG_SIZE * 6]
+ /* Initialize the crash console */
+ bl plat_crash_console_init
+ /* Verify the console is initialized */
+ cbz x0, crash_panic
+ /* Print the crash message. sp points to the crash message */
+ mov x4, sp
+ bl asm_print_str
+ /* load the crash buf address */
+ mrs x0, tpidr_el3
+ /* report x30 first from the crash buf */
+ ldr x4, [x0, #REG_SIZE * 7]
+ bl asm_print_hex
+ bl print_newline
+ /* Load the crash buf address */
+ mrs x0, tpidr_el3
+ /* Now mov x7 into crash buf */
+ str x7, [x0, #REG_SIZE * 7]
+
+ /* Report x0 - x29 values stored in crash buf*/
+ /* Store the ascii list pointer in x6 */
+ adr x6, gp_regs
+ /* Print x0 to x7 from the crash buf */
+ bl size_controlled_print
+ /* Store x8 - x15 in crash buf and print */
+ bl str_in_crash_buf_print
+ /* Load the crash buf address */
+ mrs x0, tpidr_el3
+ /* Store the rest of gp regs and print */
+ stp x16, x17, [x0]
+ stp x18, x19, [x0, #REG_SIZE * 2]
+ stp x20, x21, [x0, #REG_SIZE * 4]
+ stp x22, x23, [x0, #REG_SIZE * 6]
+ bl size_controlled_print
+ /* Load the crash buf address */
+ mrs x0, tpidr_el3
+ stp x24, x25, [x0]
+ stp x26, x27, [x0, #REG_SIZE * 2]
+ stp x28, x29, [x0, #REG_SIZE * 4]
+ bl size_controlled_print
+
+ /* Print the el3 sys registers */
+ adr x6, el3_sys_regs
+ mrs x8, scr_el3
+ mrs x9, sctlr_el3
+ mrs x10, cptr_el3
+ mrs x11, tcr_el3
+ mrs x12, daif
+ mrs x13, mair_el3
+ mrs x14, spsr_el3
+ mrs x15, elr_el3
+ bl str_in_crash_buf_print
+ mrs x8, ttbr0_el3
+ mrs x9, esr_el3
+ mrs x10, far_el3
+ bl str_in_crash_buf_print
+
+ /* Print the non el3 sys registers */
+ adr x6, non_el3_sys_regs
+ mrs x8, spsr_el1
+ mrs x9, elr_el1
+ mrs x10, spsr_abt
+ mrs x11, spsr_und
+ mrs x12, spsr_irq
+ mrs x13, spsr_fiq
+ mrs x14, sctlr_el1
+ mrs x15, actlr_el1
+ bl str_in_crash_buf_print
+ mrs x8, cpacr_el1
+ mrs x9, csselr_el1
mrs x10, sp_el1
mrs x11, esr_el1
mrs x12, ttbr0_el1
mrs x13, ttbr1_el1
mrs x14, mair_el1
mrs x15, amair_el1
- mrs x16, tcr_el1
- mrs x17, tpidr_el1
-
- stp x10, x11, [sp, #(REG_SIZE * 10)]
- stp x12, x13, [sp, #(REG_SIZE * 12)]
- stp x14, x15, [sp, #(REG_SIZE * 14)]
- stp x16, x17, [sp, #(REG_SIZE * 16)]
-
- adr x0, non_el3_sys_0_regs
- mov x1, sp
- bl print_string_value
- add sp, sp, #NON_EL3_SYS_0_REG_SIZE
- .endm
-
- .macro print_non_el3_sys_1_regs
- sub sp, sp, #NON_EL3_SYS_1_REG_SIZE
-
- mrs x9, tpidr_el0
- mrs x10, tpidrro_el0
- mrs x11, dacr32_el2
- mrs x12, ifsr32_el2
- mrs x13, par_el1
- mrs x14, far_el1
- mrs x15, afsr0_el1
- mrs x16, afsr1_el1
- mrs x17, contextidr_el1
- mrs x8, vbar_el1
-
- stp x9, x10, [sp]
- stp x11, x12, [sp, #(REG_SIZE * 2)]
- stp x13, x14, [sp, #(REG_SIZE * 4)]
- stp x15, x16, [sp, #(REG_SIZE * 6)]
- stp x17, x8, [sp, #(REG_SIZE * 8)]
-
- mrs x10, cntp_ctl_el0
- mrs x11, cntp_cval_el0
- mrs x12, cntv_ctl_el0
- mrs x13, cntv_cval_el0
- mrs x14, cntkctl_el1
- mrs x15, fpexc32_el2
- mrs x8, sp_el0
-
- stp x10, x11, [sp, #(REG_SIZE *10)]
- stp x12, x13, [sp, #(REG_SIZE * 12)]
- stp x14, x15, [sp, #(REG_SIZE * 14)]
- stp x8, xzr, [sp, #(REG_SIZE * 16)]
-
- adr x0, non_el3_sys_1_regs
- mov x1, sp
- bl print_string_value
- add sp, sp, #NON_EL3_SYS_1_REG_SIZE
- .endm
-
- .macro init_crash_stack
- msr cntfrq_el0, x0 /* we can corrupt this reg to free up x0 */
- mrs x0, tpidr_el3
-
- /* Check if tpidr is initialized */
- cbz x0, infinite_loop
-
- ldr x0, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
- /* store the x30 and sp to stack */
- str x30, [x0, #-(REG_SIZE)]!
- mov x30, sp
- str x30, [x0, #-(REG_SIZE)]!
- mov sp, x0
- mrs x0, cntfrq_el0
- .endm
-
- /* ---------------------------------------------------
- * The below function initializes the crash dump stack ,
- * and prints the system state. This function
- * will not return.
- * ---------------------------------------------------
- */
-func dump_state_and_die
- init_crash_stack
- print_caller_saved_regs
- b print_state
-
-func dump_intr_state_and_die
- init_crash_stack
- print_caller_saved_regs
- plat_print_gic_regs /* fall through to print_state */
-
-print_state:
- /* copy the original x30 from stack */
- ldr x30, [sp, #REG_SIZE]
- print_callee_saved_regs
- /* copy the original SP_EL3 from stack to x0 and rewind stack */
- ldr x0, [sp], #(REG_SIZE * 2)
- print_el3_sys_regs
- print_non_el3_sys_0_regs
- print_non_el3_sys_1_regs
-
-#else /* CRASH_REPORING */
-
-func dump_state_and_die
-dump_intr_state_and_die:
-
+ bl str_in_crash_buf_print
+ mrs x8, tcr_el1
+ mrs x9, tpidr_el1
+ mrs x10, tpidr_el0
+ mrs x11, tpidrro_el0
+ mrs x12, dacr32_el2
+ mrs x13, ifsr32_el2
+ mrs x14, par_el1
+ mrs x15, mpidr_el1
+ bl str_in_crash_buf_print
+ mrs x8, afsr0_el1
+ mrs x9, afsr1_el1
+ mrs x10, contextidr_el1
+ mrs x11, vbar_el1
+ mrs x12, cntp_ctl_el0
+ mrs x13, cntp_cval_el0
+ mrs x14, cntv_ctl_el0
+ mrs x15, cntv_cval_el0
+ bl str_in_crash_buf_print
+ mrs x8, cntkctl_el1
+ mrs x9, fpexc32_el2
+ mrs x10, sp_el0
+ bl str_in_crash_buf_print
+
+ /* Print the CPUECTLR_EL1 reg */
+ mrs x0, midr_el1
+ lsr x0, x0, #MIDR_PN_SHIFT
+ and x0, x0, #MIDR_PN_MASK
+ cmp x0, #MIDR_PN_A57
+ b.eq 1f
+ cmp x0, #MIDR_PN_A53
+ b.ne 2f
+1:
+ adr x4, cpu_ectlr_reg
+ bl asm_print_str
+ mrs x4, CPUECTLR_EL1
+ bl asm_print_hex
+ bl print_newline
+2:
+
+ /* Print the gic registers */
+ plat_print_gic_regs
+
+ /* Print the interconnect registers */
+ plat_print_interconnect_regs
+
+ /* Done reporting */
+ b crash_panic
+
+#else /* CRASH_REPORTING */
+func report_unhandled_exception
+report_unhandled_interrupt:
+ b crash_panic
#endif /* CRASH_REPORING */
-infinite_loop:
- b infinite_loop
-
-
-#define PCPU_CRASH_STACK_SIZE 0x140
-
- /* -----------------------------------------------------
- * Per-cpu crash stacks in normal memory.
- * -----------------------------------------------------
- */
-declare_stack pcpu_crash_stack, tzfw_normal_stacks, \
- PCPU_CRASH_STACK_SIZE, PLATFORM_CORE_COUNT
- /* -----------------------------------------------------
- * Provides each CPU with a small stacks for reporting
- * unhandled exceptions, and stores the stack address
- * in cpu_data
- *
- * This can be called without a runtime stack
- * clobbers: x0 - x4
- * -----------------------------------------------------
- */
-func init_crash_reporting
- mov x4, x30
- mov x2, #0
- adr x3, pcpu_crash_stack
-init_crash_loop:
- mov x0, x2
- bl _cpu_data_by_index
- add x3, x3, #PCPU_CRASH_STACK_SIZE
- str x3, [x0, #CPU_DATA_CRASH_STACK_OFFSET]
- add x2, x2, #1
- cmp x2, #PLATFORM_CORE_COUNT
- b.lo init_crash_loop
- ret x4
+func crash_panic
+ b crash_panic
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index a11cd71f..996dedcb 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -60,7 +60,7 @@
* -----------------------------------------------------
*/
- bl dump_state_and_die
+ bl report_unhandled_exception
.endm
@@ -142,7 +142,7 @@ interrupt_exit_\label:
* where the interrupt was generated.
*/
interrupt_error_\label:
- bl dump_intr_state_and_die
+ bl report_unhandled_interrupt
.endm
@@ -158,7 +158,6 @@ interrupt_error_\label:
.endm
.section .vectors, "ax"; .align 11
-
.align 7
runtime_exceptions:
/* -----------------------------------------------------
@@ -170,7 +169,7 @@ sync_exception_sp_el0:
* We don't expect any synchronous exceptions from EL3
* -----------------------------------------------------
*/
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size sync_exception_sp_el0
.align 7
@@ -180,17 +179,17 @@ sync_exception_sp_el0:
* -----------------------------------------------------
*/
irq_sp_el0:
- bl dump_intr_state_and_die
+ bl report_unhandled_interrupt
check_vector_size irq_sp_el0
.align 7
fiq_sp_el0:
- bl dump_intr_state_and_die
+ bl report_unhandled_interrupt
check_vector_size fiq_sp_el0
.align 7
serror_sp_el0:
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size serror_sp_el0
/* -----------------------------------------------------
@@ -206,22 +205,22 @@ sync_exception_sp_elx:
* There is a high probability that SP_EL3 is corrupted.
* -----------------------------------------------------
*/
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size sync_exception_sp_elx
.align 7
irq_sp_elx:
- bl dump_intr_state_and_die
+ bl report_unhandled_interrupt
check_vector_size irq_sp_elx
.align 7
fiq_sp_elx:
- bl dump_intr_state_and_die
+ bl report_unhandled_interrupt
check_vector_size fiq_sp_elx
.align 7
serror_sp_elx:
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size serror_sp_elx
/* -----------------------------------------------------
@@ -258,7 +257,7 @@ fiq_aarch64:
.align 7
serror_aarch64:
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size serror_aarch64
/* -----------------------------------------------------
@@ -295,7 +294,7 @@ fiq_aarch32:
.align 7
serror_aarch32:
- bl dump_state_and_die
+ bl report_unhandled_exception
check_vector_size serror_aarch32
.align 7
@@ -403,7 +402,7 @@ smc_handler64:
mrs x17, elr_el3
mrs x18, scr_el3
stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
- stp x18, xzr, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
/* Copy SCR_EL3.NS bit to the flag to indicate caller's security */
bfi x7, x18, #0, #1
@@ -446,7 +445,7 @@ el3_exit: ; .type el3_exit, %function
* Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET
* -----------------------------------------------------
*/
- ldp x18, xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
+ ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3]
ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3]
msr scr_el3, x18
msr spsr_el3, x16
@@ -473,7 +472,7 @@ smc_prohibited:
rt_svc_fw_critical_error:
msr spsel, #1 /* Switch to SP_ELx */
- bl dump_state_and_die
+ bl report_unhandled_exception
/* -----------------------------------------------------
* The following functions are used to saved and restore
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 5555c319..fb17a2e6 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -48,6 +48,7 @@ BL31_SOURCES += bl31/bl31_main.c \
services/std_svc/psci/psci_afflvl_suspend.c \
services/std_svc/psci/psci_common.c \
services/std_svc/psci/psci_entry.S \
+ services/std_svc/psci/psci_helpers.S \
services/std_svc/psci/psci_main.c \
services/std_svc/psci/psci_setup.c
diff --git a/bl31/cpu_data_array.c b/bl31/cpu_data_array.c
index b0042a16..4cba1184 100644
--- a/bl31/cpu_data_array.c
+++ b/bl31/cpu_data_array.c
@@ -32,13 +32,5 @@
#include <cpu_data.h>
#include <platform_def.h>
-/* verify assembler offsets match data structures */
-CASSERT(CPU_DATA_CRASH_STACK_OFFSET == __builtin_offsetof
- (cpu_data_t, crash_stack),
- assert_cpu_data_crash_stack_offset_mismatch);
-
-CASSERT((1 << CPU_DATA_LOG2SIZE) == sizeof(cpu_data_t),
- assert_cpu_data_log2size_mismatch);
-
/* The per_cpu_ptr_cache_t space allocation */
cpu_data_t percpu_data[PLATFORM_CORE_COUNT];