diff options
Diffstat (limited to 'bl31')
-rw-r--r-- | bl31/aarch64/bl31_arch_setup.c | 14 | ||||
-rw-r--r-- | bl31/aarch64/bl31_entrypoint.S | 61 | ||||
-rw-r--r-- | bl31/aarch64/context.S | 44 | ||||
-rw-r--r-- | bl31/aarch64/crash_reporting.S | 561 | ||||
-rw-r--r-- | bl31/aarch64/runtime_exceptions.S | 31 | ||||
-rw-r--r-- | bl31/bl31.mk | 1 | ||||
-rw-r--r-- | bl31/cpu_data_array.c | 8 |
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]; |