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