xref: /rk3399_ARM-atf/plat/common/aarch64/crash_console_helpers.S (revision 806b315c83d4c18b3a9bd82b4ded7fb1b9a04642)
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