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> 13*09d40e0eSAntonio Nino Diaz#include <drivers/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 2363c52d00SJulius Werner /* 2463c52d00SJulius Werner * Spinlock to syncronize access to crash_console_triggered. We cannot 2563c52d00SJulius Werner * acquire spinlocks when the cache is disabled, so in some cases (like 2663c52d00SJulius Werner * late during CPU suspend) some risk remains. 2763c52d00SJulius Werner */ 2863c52d00SJulius Werner.section .data.crash_console_spinlock 2963c52d00SJulius Werner define_asm_spinlock crash_console_spinlock 3063c52d00SJulius Werner 3163c52d00SJulius Werner /* 3263c52d00SJulius Werner * Flag to make sure that only one CPU can write a crash dump even if 3363c52d00SJulius Werner * multiple crash at the same time. Interleaving crash dumps on the same 3463c52d00SJulius Werner * console would just make the output unreadable, so it's better to only 3563c52d00SJulius Werner * get a single but uncorrupted dump. This also means that we don't have 3663c52d00SJulius Werner * to duplicate the reg_stash below for each CPU. 3763c52d00SJulius Werner */ 3863c52d00SJulius Werner.section .data.crash_console_triggered 3963c52d00SJulius Werner crash_console_triggered: .byte 0 4063c52d00SJulius Werner 4163c52d00SJulius Werner /* 4263c52d00SJulius Werner * Space to stash away some register values while we're calling into 4363c52d00SJulius Werner * console drivers and don't have a real stack available. We need x14, 4463c52d00SJulius Werner * x15 and x30 for bookkeeping within the plat_crash_console functions 4563c52d00SJulius Werner * themselves, and some console drivers use x16 and x17 as additional 4663c52d00SJulius Werner * scratch space that is not preserved by the main crash reporting 4763c52d00SJulius Werner * framework. (Note that x16 and x17 should really never be expected to 4863c52d00SJulius Werner * retain their values across any function call, even between carefully 4963c52d00SJulius Werner * designed assembly functions, since the linker is always free to 5063c52d00SJulius Werner * insert a function call veneer that uses these registers as scratch 5163c52d00SJulius Werner * space at any time. The current crash reporting framework doesn't 5263c52d00SJulius Werner * really respect that, but since TF is usually linked as a single 5363c52d00SJulius Werner * contiguous binary of less than 128MB, it seems to work in practice.) 5463c52d00SJulius Werner */ 5563c52d00SJulius Werner.section .data.crash_console_reg_stash 5663c52d00SJulius Werner .align 3 5763c52d00SJulius Werner crash_console_reg_stash: .quad 0, 0, 0, 0, 0 5863c52d00SJulius Werner 5963c52d00SJulius Werner /* -------------------------------------------------------------------- 606c9ada31SAntonio Nino Diaz * int plat_crash_console_init(void) 6163c52d00SJulius Werner * Takes the crash console spinlock (if possible) and checks the trigger 6263c52d00SJulius Werner * flag to make sure we're the first CPU to dump. If not, return an 6363c52d00SJulius Werner * error (so crash dumping will fail but the CPU will still call 6463c52d00SJulius Werner * plat_panic_handler() which may do important platform-specific tasks 6563c52d00SJulius Werner * that may be needed on all crashing CPUs). In either case, the lock 6663c52d00SJulius Werner * will be released so other CPUs can make forward progress on this. 6763c52d00SJulius Werner * Clobbers: x0 - x4, x30 6863c52d00SJulius Werner * -------------------------------------------------------------------- 696c9ada31SAntonio Nino Diaz */ 706c9ada31SAntonio Nino Diazfunc plat_crash_console_init 7163c52d00SJulius Werner#if defined(IMAGE_BL31) 7263c52d00SJulius Werner mov x4, x30 /* x3 and x4 are not clobbered by spin_lock() */ 7363c52d00SJulius Werner mov x3, #0 /* return value */ 7463c52d00SJulius Werner 7563c52d00SJulius Werner mrs x1, sctlr_el3 7663c52d00SJulius Werner tst x1, #SCTLR_C_BIT 7763c52d00SJulius Werner beq skip_spinlock /* can't synchronize when cache disabled */ 7863c52d00SJulius Werner 7963c52d00SJulius Werner adrp x0, crash_console_spinlock 8063c52d00SJulius Werner add x0, x0, :lo12:crash_console_spinlock 8163c52d00SJulius Werner bl spin_lock 8263c52d00SJulius Werner 8363c52d00SJulius Wernerskip_spinlock: 8463c52d00SJulius Werner adrp x1, crash_console_triggered 8563c52d00SJulius Werner add x1, x1, :lo12:crash_console_triggered 8663c52d00SJulius Werner ldarb w2, [x1] 8763c52d00SJulius Werner cmp w2, #0 8863c52d00SJulius Werner bne init_error 8963c52d00SJulius Werner 9063c52d00SJulius Werner mov x3, #1 /* set return value to success */ 9163c52d00SJulius Werner stlrb w3, [x1] 9263c52d00SJulius Werner 9363c52d00SJulius Wernerinit_error: 9463c52d00SJulius Werner bl spin_unlock /* harmless if we didn't acquire the lock */ 9563c52d00SJulius Werner mov x0, x3 9663c52d00SJulius Werner ret x4 9763c52d00SJulius Werner#else /* Only one CPU in BL1/BL2, no need to synchronize anything */ 986c9ada31SAntonio Nino Diaz mov x0, #1 9963c52d00SJulius Werner ret 1006c9ada31SAntonio Nino Diaz#endif 1016c9ada31SAntonio Nino Diazendfunc plat_crash_console_init 1026c9ada31SAntonio Nino Diaz 10363c52d00SJulius Werner /* -------------------------------------------------------------------- 10463c52d00SJulius Werner * int plat_crash_console_putc(char c) 10563c52d00SJulius Werner * Prints the character on all consoles registered with the console 10663c52d00SJulius Werner * framework that have CONSOLE_FLAG_CRASH set. Note that this is only 10763c52d00SJulius Werner * helpful for crashes that occur after the platform intialization code 10863c52d00SJulius Werner * has registered a console. Platforms using this implementation need to 10963c52d00SJulius Werner * ensure that all console drivers they use that have the CRASH flag set 11063c52d00SJulius Werner * support this (i.e. are written in assembly and comply to the register 11163c52d00SJulius Werner * clobber requirements of plat_crash_console_putc(). 11263c52d00SJulius Werner * -------------------------------------------------------------------- 1136c9ada31SAntonio Nino Diaz */ 1146c9ada31SAntonio Nino Diazfunc plat_crash_console_putc 11563c52d00SJulius Werner adrp x1, crash_console_reg_stash 11663c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 11763c52d00SJulius Werner stp x14, x15, [x1] 11863c52d00SJulius Werner stp x16, x17, [x1, #16] 11963c52d00SJulius Werner str x30, [x1, #32] 12063c52d00SJulius Werner 12163c52d00SJulius Werner mov w14, w0 /* W14 = character to print */ 12263c52d00SJulius Werner adrp x15, console_list 12363c52d00SJulius Werner ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ 12463c52d00SJulius Werner 12563c52d00SJulius Wernerputc_loop: 12663c52d00SJulius Werner cbz x15, putc_done 12763c52d00SJulius Werner ldr w1, [x15, #CONSOLE_T_FLAGS] 12863c52d00SJulius Werner tst w1, #CONSOLE_FLAG_CRASH 12963c52d00SJulius Werner b.eq putc_continue 13063c52d00SJulius Werner ldr x2, [x15, #CONSOLE_T_PUTC] 13163c52d00SJulius Werner cbz x2, putc_continue 13263c52d00SJulius Werner mov x1, x15 13363c52d00SJulius Werner blr x2 13463c52d00SJulius Werner mov w0, w14 13563c52d00SJulius Wernerputc_continue: 13663c52d00SJulius Werner ldr x15, [x15] /* X15 = next struct */ 13763c52d00SJulius Werner b putc_loop 13863c52d00SJulius Werner 13963c52d00SJulius Wernerputc_done: 14063c52d00SJulius Werner adrp x1, crash_console_reg_stash 14163c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 14263c52d00SJulius Werner ldp x14, x15, [x1] 14363c52d00SJulius Werner ldp x16, x17, [x1, #16] 14463c52d00SJulius Werner ldr x30, [x1, #32] 14563c52d00SJulius Werner ret 1466c9ada31SAntonio Nino Diazendfunc plat_crash_console_putc 1476c9ada31SAntonio Nino Diaz 14863c52d00SJulius Werner /* -------------------------------------------------------------------- 14963c52d00SJulius Werner * int plat_crash_console_flush(char c) 15063c52d00SJulius Werner * Flushes all consoles registered with the console framework that have 15163c52d00SJulius Werner * CONSOLE_FLAG_CRASH set. Same requirements as putc(). 15263c52d00SJulius Werner * -------------------------------------------------------------------- 1536c9ada31SAntonio Nino Diaz */ 1546c9ada31SAntonio Nino Diazfunc plat_crash_console_flush 15563c52d00SJulius Werner adrp x1, crash_console_reg_stash 15663c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 15763c52d00SJulius Werner stp x30, x15, [x1] 15863c52d00SJulius Werner stp x16, x17, [x1, #16] 15963c52d00SJulius Werner 16063c52d00SJulius Werner adrp x15, console_list 16163c52d00SJulius Werner ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */ 16263c52d00SJulius Werner 16363c52d00SJulius Wernerflush_loop: 16463c52d00SJulius Werner cbz x15, flush_done 16563c52d00SJulius Werner ldr w1, [x15, #CONSOLE_T_FLAGS] 16663c52d00SJulius Werner tst w1, #CONSOLE_FLAG_CRASH 16763c52d00SJulius Werner b.eq flush_continue 16863c52d00SJulius Werner ldr x2, [x15, #CONSOLE_T_FLUSH] 16963c52d00SJulius Werner cbz x2, flush_continue 17063c52d00SJulius Werner mov x0, x15 17163c52d00SJulius Werner blr x2 17263c52d00SJulius Wernerflush_continue: 17363c52d00SJulius Werner ldr x15, [x15] /* X15 = next struct */ 17463c52d00SJulius Werner b flush_loop 17563c52d00SJulius Werner 17663c52d00SJulius Wernerflush_done: 17763c52d00SJulius Werner adrp x1, crash_console_reg_stash 17863c52d00SJulius Werner add x1, x1, :lo12:crash_console_reg_stash 17963c52d00SJulius Werner ldp x30, x15, [x1] 18063c52d00SJulius Werner ldp x16, x17, [x1, #16] 18163c52d00SJulius Werner ret 1826c9ada31SAntonio Nino Diazendfunc plat_crash_console_flush 183