blob: 75b4208933254fff1e04c3dabe7edcc53efebfb2 [file] [log] [blame]
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +01001/*
Masahiro Yamada269a8ad2019-07-23 12:32:58 +09002 * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * If a platform wishes to use the functions in this file it has to be added to
9 * the Makefile of the platform. It is not included in the common Makefile.
10 */
11
12#include <asm_macros.S>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <drivers/console.h>
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010014
15 .globl plat_crash_console_init
16 .globl plat_crash_console_putc
17 .globl plat_crash_console_flush
18
Julius Werner1338c9c2018-11-19 14:25:55 -080019 /*
20 * Spinlock to syncronize access to crash_console_triggered. We cannot
21 * acquire spinlocks when the cache is disabled, so in some cases (like
22 * late during CPU suspend) some risk remains.
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010023 */
Julius Werner1338c9c2018-11-19 14:25:55 -080024.section .data.crash_console_spinlock
25 define_asm_spinlock crash_console_spinlock
26
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010027 /*
Julius Werner1338c9c2018-11-19 14:25:55 -080028 * Flag to make sure that only one CPU can write a crash dump even if
29 * multiple crash at the same time. Interleaving crash dumps on the same
30 * console would just make the output unreadable, so it's better to only
31 * get a single but uncorrupted dump. This also means that we don't have
32 * to duplicate the reg_stash below for each CPU.
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010033 */
Julius Werner1338c9c2018-11-19 14:25:55 -080034.section .data.crash_console_triggered
35 crash_console_triggered: .byte 0
36
37 /*
38 * Space to stash away some register values while we're calling into
39 * console drivers and don't have a real stack available. We need x14,
40 * x15 and x30 for bookkeeping within the plat_crash_console functions
41 * themselves, and some console drivers use x16 and x17 as additional
42 * scratch space that is not preserved by the main crash reporting
43 * framework. (Note that x16 and x17 should really never be expected to
44 * retain their values across any function call, even between carefully
45 * designed assembly functions, since the linker is always free to
46 * insert a function call veneer that uses these registers as scratch
47 * space at any time. The current crash reporting framework doesn't
48 * really respect that, but since TF is usually linked as a single
49 * contiguous binary of less than 128MB, it seems to work in practice.)
50 */
51.section .data.crash_console_reg_stash
52 .align 3
53 crash_console_reg_stash: .quad 0, 0, 0, 0, 0
54
55 /* --------------------------------------------------------------------
56 * int plat_crash_console_init(void)
57 * Takes the crash console spinlock (if possible) and checks the trigger
58 * flag to make sure we're the first CPU to dump. If not, return an
59 * error (so crash dumping will fail but the CPU will still call
60 * plat_panic_handler() which may do important platform-specific tasks
61 * that may be needed on all crashing CPUs). In either case, the lock
62 * will be released so other CPUs can make forward progress on this.
63 * Clobbers: x0 - x4, x30
64 * --------------------------------------------------------------------
65 */
66func plat_crash_console_init
67#if defined(IMAGE_BL31)
68 mov x4, x30 /* x3 and x4 are not clobbered by spin_lock() */
69 mov x3, #0 /* return value */
70
Baruch Siacheef258b2022-11-24 10:34:06 +020071 adrp x0, crash_console_spinlock
72 add x0, x0, :lo12:crash_console_spinlock
73
Julius Werner1338c9c2018-11-19 14:25:55 -080074 mrs x1, sctlr_el3
75 tst x1, #SCTLR_C_BIT
76 beq skip_spinlock /* can't synchronize when cache disabled */
Julius Werner1338c9c2018-11-19 14:25:55 -080077 bl spin_lock
78
79skip_spinlock:
80 adrp x1, crash_console_triggered
81 add x1, x1, :lo12:crash_console_triggered
82 ldarb w2, [x1]
83 cmp w2, #0
84 bne init_error
85
86 mov x3, #1 /* set return value to success */
87 stlrb w3, [x1]
88
89init_error:
90 bl spin_unlock /* harmless if we didn't acquire the lock */
91 mov x0, x3
92 ret x4
93#else /* Only one CPU in BL1/BL2, no need to synchronize anything */
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010094 mov x0, #1
Julius Werner1338c9c2018-11-19 14:25:55 -080095 ret
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +010096#endif
97endfunc plat_crash_console_init
98
Julius Werner1338c9c2018-11-19 14:25:55 -080099 /* --------------------------------------------------------------------
100 * int plat_crash_console_putc(char c)
101 * Prints the character on all consoles registered with the console
102 * framework that have CONSOLE_FLAG_CRASH set. Note that this is only
103 * helpful for crashes that occur after the platform intialization code
104 * has registered a console. Platforms using this implementation need to
105 * ensure that all console drivers they use that have the CRASH flag set
106 * support this (i.e. are written in assembly and comply to the register
107 * clobber requirements of plat_crash_console_putc().
108 * --------------------------------------------------------------------
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +0100109 */
110func plat_crash_console_putc
Julius Werner1338c9c2018-11-19 14:25:55 -0800111 adrp x1, crash_console_reg_stash
112 add x1, x1, :lo12:crash_console_reg_stash
113 stp x14, x15, [x1]
114 stp x16, x17, [x1, #16]
115 str x30, [x1, #32]
116
117 mov w14, w0 /* W14 = character to print */
118 adrp x15, console_list
119 ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */
120
121putc_loop:
122 cbz x15, putc_done
123 ldr w1, [x15, #CONSOLE_T_FLAGS]
124 tst w1, #CONSOLE_FLAG_CRASH
125 b.eq putc_continue
126 ldr x2, [x15, #CONSOLE_T_PUTC]
127 cbz x2, putc_continue
Masahiro Yamada269a8ad2019-07-23 12:32:58 +0900128 cmp w14, #'\n'
129 b.ne putc
130 tst w1, #CONSOLE_FLAG_TRANSLATE_CRLF
131 b.eq putc
Julius Werner1338c9c2018-11-19 14:25:55 -0800132 mov x1, x15
Masahiro Yamada269a8ad2019-07-23 12:32:58 +0900133 mov w0, #'\r'
Julius Werner1338c9c2018-11-19 14:25:55 -0800134 blr x2
Masahiro Yamada269a8ad2019-07-23 12:32:58 +0900135 ldr x2, [x15, #CONSOLE_T_PUTC]
136putc:
137 mov x1, x15
Julius Werner1338c9c2018-11-19 14:25:55 -0800138 mov w0, w14
Masahiro Yamada269a8ad2019-07-23 12:32:58 +0900139 blr x2
Julius Werner1338c9c2018-11-19 14:25:55 -0800140putc_continue:
141 ldr x15, [x15] /* X15 = next struct */
142 b putc_loop
143
144putc_done:
145 adrp x1, crash_console_reg_stash
146 add x1, x1, :lo12:crash_console_reg_stash
147 ldp x14, x15, [x1]
148 ldp x16, x17, [x1, #16]
149 ldr x30, [x1, #32]
150 ret
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +0100151endfunc plat_crash_console_putc
152
Julius Werner1338c9c2018-11-19 14:25:55 -0800153 /* --------------------------------------------------------------------
154 * int plat_crash_console_flush(char c)
155 * Flushes all consoles registered with the console framework that have
156 * CONSOLE_FLAG_CRASH set. Same requirements as putc().
157 * --------------------------------------------------------------------
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +0100158 */
159func plat_crash_console_flush
Julius Werner1338c9c2018-11-19 14:25:55 -0800160 adrp x1, crash_console_reg_stash
161 add x1, x1, :lo12:crash_console_reg_stash
162 stp x30, x15, [x1]
163 stp x16, x17, [x1, #16]
164
165 adrp x15, console_list
166 ldr x15, [x15, :lo12:console_list] /* X15 = first console struct */
167
168flush_loop:
169 cbz x15, flush_done
170 ldr w1, [x15, #CONSOLE_T_FLAGS]
171 tst w1, #CONSOLE_FLAG_CRASH
172 b.eq flush_continue
173 ldr x2, [x15, #CONSOLE_T_FLUSH]
174 cbz x2, flush_continue
175 mov x0, x15
176 blr x2
177flush_continue:
178 ldr x15, [x15] /* X15 = next struct */
179 b flush_loop
180
181flush_done:
182 adrp x1, crash_console_reg_stash
183 add x1, x1, :lo12:crash_console_reg_stash
184 ldp x30, x15, [x1]
185 ldp x16, x17, [x1, #16]
186 ret
Antonio Nino Diaz4bac0452018-10-16 14:32:34 +0100187endfunc plat_crash_console_flush