16c9ada31SAntonio Nino Diaz/* 26c9ada31SAntonio Nino Diaz * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 36c9ada31SAntonio Nino Diaz * 46c9ada31SAntonio Nino Diaz * SPDX-License-Identifier: BSD-3-Clause 56c9ada31SAntonio Nino Diaz */ 66c9ada31SAntonio Nino Diaz 76c9ada31SAntonio Nino Diaz/* 86c9ada31SAntonio Nino Diaz * If a platform wishes to use the functions in this file it has to be added to 96c9ada31SAntonio Nino Diaz * the Makefile of the platform. It is not included in the common Makefile. 106c9ada31SAntonio Nino Diaz */ 116c9ada31SAntonio Nino Diaz 126c9ada31SAntonio Nino Diaz#include <asm_macros.S> 136c9ada31SAntonio Nino Diaz#include <console.h> 146c9ada31SAntonio Nino Diaz 156c9ada31SAntonio Nino Diaz .globl plat_crash_console_init 166c9ada31SAntonio Nino Diaz .globl plat_crash_console_putc 176c9ada31SAntonio Nino Diaz .globl plat_crash_console_flush 186c9ada31SAntonio Nino Diaz 19b2f7c9ddSJulius Werner#if !MULTI_CONSOLE_API 20b2f7c9ddSJulius Werner#error "This crash console implementation only works with the MULTI_CONSOLE_API!" 21b2f7c9ddSJulius Werner#endif 226c9ada31SAntonio Nino Diaz 23*63c52d00SJulius Werner /* 24*63c52d00SJulius Werner * Spinlock to syncronize access to crash_console_triggered. We cannot 25*63c52d00SJulius Werner * acquire spinlocks when the cache is disabled, so in some cases (like 26*63c52d00SJulius Werner * late during CPU suspend) some risk remains. 27*63c52d00SJulius Werner */ 28*63c52d00SJulius Werner.section .data.crash_console_spinlock 29*63c52d00SJulius Werner define_asm_spinlock crash_console_spinlock 30*63c52d00SJulius Werner 31*63c52d00SJulius Werner /* 32*63c52d00SJulius Werner * Flag to make sure that only one CPU can write a crash dump even if 33*63c52d00SJulius Werner * multiple crash at the same time. Interleaving crash dumps on the same 34*63c52d00SJulius Werner * console would just make the output unreadable, so it's better to only 35*63c52d00SJulius Werner * get a single but uncorrupted dump. This also means that we don't have 36*63c52d00SJulius Werner * to duplicate the reg_stash below for each CPU. 37*63c52d00SJulius Werner */ 38*63c52d00SJulius Werner.section .data.crash_console_triggered 39*63c52d00SJulius Werner crash_console_triggered: .byte 0 40*63c52d00SJulius Werner 41*63c52d00SJulius Werner /* 42*63c52d00SJulius Werner * Space to stash away some register values while we're calling into 43*63c52d00SJulius Werner * console drivers and don't have a real stack available. We need x14, 44*63c52d00SJulius Werner * x15 and x30 for bookkeeping within the plat_crash_console functions 45*63c52d00SJulius Werner * themselves, and some console drivers use x16 and x17 as additional 46*63c52d00SJulius Werner * scratch space that is not preserved by the main crash reporting 47*63c52d00SJulius Werner * framework. (Note that x16 and x17 should really never be expected to 48*63c52d00SJulius Werner * retain their values across any function call, even between carefully 49*63c52d00SJulius Werner * designed assembly functions, since the linker is always free to 50*63c52d00SJulius Werner * insert a function call veneer that uses these registers as scratch 51*63c52d00SJulius Werner * space at any time. The current crash reporting framework doesn't 52*63c52d00SJulius Werner * really respect that, but since TF is usually linked as a single 53*63c52d00SJulius Werner * contiguous binary of less than 128MB, it seems to work in practice.) 54*63c52d00SJulius Werner */ 55*63c52d00SJulius Werner.section .data.crash_console_reg_stash 56*63c52d00SJulius Werner .align 3 57*63c52d00SJulius Werner crash_console_reg_stash: .quad 0, 0, 0, 0, 0 58*63c52d00SJulius Werner 59*63c52d00SJulius Werner /* -------------------------------------------------------------------- 606c9ada31SAntonio Nino Diaz * int plat_crash_console_init(void) 61*63c52d00SJulius Werner * Takes the crash console spinlock (if possible) and checks the trigger 62*63c52d00SJulius Werner * flag to make sure we're the first CPU to dump. If not, return an 63*63c52d00SJulius Werner * error (so crash dumping will fail but the CPU will still call 64*63c52d00SJulius Werner * plat_panic_handler() which may do important platform-specific tasks 65*63c52d00SJulius Werner * that may be needed on all crashing CPUs). In either case, the lock 66*63c52d00SJulius Werner * will be released so other CPUs can make forward progress on this. 67*63c52d00SJulius Werner * Clobbers: x0 - x4, x30 68*63c52d00SJulius Werner * -------------------------------------------------------------------- 696c9ada31SAntonio Nino Diaz */ 706c9ada31SAntonio Nino Diazfunc plat_crash_console_init 71*63c52d00SJulius Werner#if defined(IMAGE_BL31) 72*63c52d00SJulius Werner mov x4, x30 /* x3 and x4 are not clobbered by spin_lock() */ 73*63c52d00SJulius Werner mov x3, #0 /* return value */ 74*63c52d00SJulius Werner 75*63c52d00SJulius Werner mrs x1, sctlr_el3 76*63c52d00SJulius Werner tst x1, #SCTLR_C_BIT 77*63c52d00SJulius Werner beq skip_spinlock /* can't synchronize when cache disabled */ 78*63c52d00SJulius Werner 79*63c52d00SJulius Werner adrp x0, crash_console_spinlock 80*63c52d00SJulius Werner add x0, x0, :lo12:crash_console_spinlock 81*63c52d00SJulius Werner bl spin_lock 82*63c52d00SJulius Werner 83*63c52d00SJulius Wernerskip_spinlock: 84*63c52d00SJulius Werner adrp x1, crash_console_triggered 85*63c52d00SJulius Werner add x1, x1, :lo12:crash_console_triggered 86*63c52d00SJulius Werner ldarb w2, [x1] 87*63c52d00SJulius Werner cmp w2, #0 88*63c52d00SJulius Werner bne init_error 89*63c52d00SJulius Werner 90*63c52d00SJulius Werner mov x3, #1 /* set return value to success */ 91*63c52d00SJulius Werner stlrb w3, [x1] 92*63c52d00SJulius Werner 93*63c52d00SJulius Wernerinit_error: 94*63c52d00SJulius Werner bl spin_unlock /* harmless if we didn't acquire the lock */ 95*63c52d00SJulius Werner mov x0, x3 96*63c52d00SJulius Werner ret x4 97*63c52d00SJulius Werner#else /* Only one CPU in BL1/BL2, no need to synchronize anything */ 986c9ada31SAntonio Nino Diaz mov x0, #1 99*63c52d00SJulius Werner ret 1006c9ada31SAntonio Nino Diaz#endif 1016c9ada31SAntonio Nino Diazendfunc plat_crash_console_init 1026c9ada31SAntonio Nino Diaz 103*63c52d00SJulius Werner /* -------------------------------------------------------------------- 104*63c52d00SJulius Werner * int plat_crash_console_putc(char c) 105*63c52d00SJulius Werner * Prints the character on all consoles registered with the console 106*63c52d00SJulius Werner * framework that have CONSOLE_FLAG_CRASH set. Note that this is only 107*63c52d00SJulius Werner * helpful for crashes that occur after the platform intialization code 108*63c52d00SJulius Werner * has registered a console. Platforms using this implementation need to 109*63c52d00SJulius Werner * ensure that all console drivers they use that have the CRASH flag set 110*63c52d00SJulius Werner * support this (i.e. are written in assembly and comply to the register 111*63c52d00SJulius Werner * clobber requirements of plat_crash_console_putc(). 112*63c52d00SJulius Werner * -------------------------------------------------------------------- 1136c9ada31SAntonio Nino Diaz */ 1146c9ada31SAntonio Nino Diazfunc plat_crash_console_putc 115*63c52d00SJulius Werner adrp x1, crash_console_reg_stash 116*63c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 117*63c52d00SJulius Werner stp x14, x15, [x1] 118*63c52d00SJulius Werner stp x16, x17, [x1, #16] 119*63c52d00SJulius Werner str x30, [x1, #32] 120*63c52d00SJulius Werner 121*63c52d00SJulius Werner mov w14, w0 /* W14 = character to print */ 122*63c52d00SJulius Werner adrp x15, console_list 123*63c52d00SJulius Werner ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ 124*63c52d00SJulius Werner 125*63c52d00SJulius Wernerputc_loop: 126*63c52d00SJulius Werner cbz x15, putc_done 127*63c52d00SJulius Werner ldr w1, [x15, #CONSOLE_T_FLAGS] 128*63c52d00SJulius Werner tst w1, #CONSOLE_FLAG_CRASH 129*63c52d00SJulius Werner b.eq putc_continue 130*63c52d00SJulius Werner ldr x2, [x15, #CONSOLE_T_PUTC] 131*63c52d00SJulius Werner cbz x2, putc_continue 132*63c52d00SJulius Werner mov x1, x15 133*63c52d00SJulius Werner blr x2 134*63c52d00SJulius Werner mov w0, w14 135*63c52d00SJulius Wernerputc_continue: 136*63c52d00SJulius Werner ldr x15, [x15] /* X15 = next struct */ 137*63c52d00SJulius Werner b putc_loop 138*63c52d00SJulius Werner 139*63c52d00SJulius Wernerputc_done: 140*63c52d00SJulius Werner adrp x1, crash_console_reg_stash 141*63c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 142*63c52d00SJulius Werner ldp x14, x15, [x1] 143*63c52d00SJulius Werner ldp x16, x17, [x1, #16] 144*63c52d00SJulius Werner ldr x30, [x1, #32] 145*63c52d00SJulius Werner ret 1466c9ada31SAntonio Nino Diazendfunc plat_crash_console_putc 1476c9ada31SAntonio Nino Diaz 148*63c52d00SJulius Werner /* -------------------------------------------------------------------- 149*63c52d00SJulius Werner * int plat_crash_console_flush(char c) 150*63c52d00SJulius Werner * Flushes all consoles registered with the console framework that have 151*63c52d00SJulius Werner * CONSOLE_FLAG_CRASH set. Same requirements as putc(). 152*63c52d00SJulius Werner * -------------------------------------------------------------------- 1536c9ada31SAntonio Nino Diaz */ 1546c9ada31SAntonio Nino Diazfunc plat_crash_console_flush 155*63c52d00SJulius Werner adrp x1, crash_console_reg_stash 156*63c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 157*63c52d00SJulius Werner stp x30, x15, [x1] 158*63c52d00SJulius Werner stp x16, x17, [x1, #16] 159*63c52d00SJulius Werner 160*63c52d00SJulius Werner adrp x15, console_list 161*63c52d00SJulius Werner ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ 162*63c52d00SJulius Werner 163*63c52d00SJulius Wernerflush_loop: 164*63c52d00SJulius Werner cbz x15, flush_done 165*63c52d00SJulius Werner ldr w1, [x15, #CONSOLE_T_FLAGS] 166*63c52d00SJulius Werner tst w1, #CONSOLE_FLAG_CRASH 167*63c52d00SJulius Werner b.eq flush_continue 168*63c52d00SJulius Werner ldr x2, [x15, #CONSOLE_T_FLUSH] 169*63c52d00SJulius Werner cbz x2, flush_continue 170*63c52d00SJulius Werner mov x0, x15 171*63c52d00SJulius Werner blr x2 172*63c52d00SJulius Wernerflush_continue: 173*63c52d00SJulius Werner ldr x15, [x15] /* X15 = next struct */ 174*63c52d00SJulius Werner b flush_loop 175*63c52d00SJulius Werner 176*63c52d00SJulius Wernerflush_done: 177*63c52d00SJulius Werner adrp x1, crash_console_reg_stash 178*63c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 179*63c52d00SJulius Werner ldp x30, x15, [x1] 180*63c52d00SJulius Werner ldp x16, x17, [x1, #16] 181*63c52d00SJulius Werner ret 1826c9ada31SAntonio Nino Diazendfunc plat_crash_console_flush 183