Add default crash console code to hook up to new console API

This patch expands the weak stubs for the plat_crash_console_xxx
functions in common platform code to use the new console API for crash
output. This should make crash console output "just work" for most cases
without the need for the platform to explicitly set up a crash console.
For cases where the normal console framework doesn't work (e.g. very
early crashes, before the platform can register any consoles), platforms
are still able to override the functions just like before.

This feature requires the MULTI_CONSOLE_API compile-time flag to work.
For builds which don't have it set, this patch has no practical effect.

Change-Id: I80dd161cb43f9db59a0bad2dae33c6560cfac584
Signed-off-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
Julius Werner 2017-09-18 16:49:48 -07:00
parent 9536bae6df
commit 17cd67d2af
2 changed files with 108 additions and 27 deletions

View File

@ -1846,12 +1846,8 @@ Function : bl31\_plat\_runtime\_setup() [optional]
The purpose of this function is allow the platform to perform any BL31 runtime
setup just prior to BL31 exit during cold boot. The default weak
implementation of this function will invoke ``console_uninit()`` which will
suppress any BL31 runtime logs.
In ARM Standard platforms, this function will initialize the BL31 runtime
console which will cause all further BL31 logs to be output to the
runtime console.
implementation of this function will invoke ``console_switch_state()`` to switch
console output to consoles marked for use in the ``runtime`` state.
Function : bl31\_get\_next\_image\_info() [mandatory]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2619,14 +2615,20 @@ as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt.
Crash Reporting mechanism (in BL31)
-----------------------------------
BL31 implements a crash reporting mechanism which prints the various registers
of the CPU to enable quick crash analysis and debugging. It requires that a
console is designated as the crash console by the platform which will be used to
print the register dump.
NOTE: This section assumes that your platform is enabling the MULTI_CONSOLE_API
flag in its platform.mk. Not using this flag is deprecated for new platforms.
The following functions must be implemented by the platform if it wants crash
reporting mechanism in BL31. The functions are implemented in assembly so that
they can be invoked without a C Runtime stack.
BL31 implements a crash reporting mechanism which prints the various registers
of the CPU to enable quick crash analysis and debugging. By default, the
definitions in ``plat/common/aarch64/platform\_helpers.S`` will cause the crash
output to be routed over the normal console infrastructure and get printed on
consoles configured to output in crash state. ``console_set_scope()`` can be
used to control whether a console is used for crash output.
In some cases (such as debugging very early crashes that happen before the
normal boot console can be set up), platforms may want to control crash output
more explicitly. For these, the following functions can be overridden by
platform code. They are executed outside of a C environment and without a stack.
Function : plat\_crash\_console\_init
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2637,9 +2639,30 @@ Function : plat\_crash\_console\_init
Return : int
This API is used by the crash reporting mechanism to initialize the crash
console. It must only use the general purpose registers x0 to x4 to do the
console. It must only use the general purpose registers x0 through x7 to do the
initialization and returns 1 on success.
If you are trying to debug crashes before the console driver would normally get
registered, you can use this to register a driver from assembly with hardcoded
parameters. For example, you could register the 16550 driver like this:
::
.section .data.crash_console /* Reserve space for console structure */
crash_console:
.zero 6 * 8 /* console_16550_t has 6 8-byte words */
func plat_crash_console_init
ldr x0, =YOUR_16550_BASE_ADDR
ldr x1, =YOUR_16550_SRCCLK_IN_HZ
ldr x2, =YOUR_16550_TARGET_BAUD_RATE
adrp x3, crash_console
add x3, x3, :lo12:crash_console
b console_16550_register /* tail call, returns 1 on success */
endfunc plat_crash_console_init
If you're trying to debug crashes in BL1, you can call the console_xxx_core_init
function exported by some console drivers from here.
Function : plat\_crash\_console\_putc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2653,6 +2676,12 @@ designated crash console. It must only use general purpose registers x1 and
x2 to do its work. The parameter and the return value are in general purpose
register x0.
If you have registered a normal console driver in ``plat_crash_console_init``,
you can keep the default implementation here (which calls ``console_putc()``).
If you're trying to debug crashes in BL1, you can call the console_xxx_core_putc
function exported by some console drivers from here.
Function : plat\_crash\_console\_flush
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2663,9 +2692,15 @@ Function : plat\_crash\_console\_flush
This API is used by the crash reporting mechanism to force write of all buffered
data on the designated crash console. It should only use general purpose
registers x0 and x1 to do its work. The return value is 0 on successful
registers x0 through x5 to do its work. The return value is 0 on successful
completion; otherwise the return value is -1.
If you have registered a normal console driver in ``plat_crash_console_init``,
you can keep the default implementation here (which calls ``console_flush()``).
If you're trying to debug crashes in BL1, you can call the console_xx_core_flush
function exported by some console drivers from here.
Build flags
-----------

View File

@ -6,6 +6,7 @@
#include <arch.h>
#include <asm_macros.S>
#include <console.h>
#include <platform_def.h>
.weak plat_report_exception
@ -56,9 +57,63 @@ func plat_report_exception
ret
endfunc plat_report_exception
#if MULTI_CONSOLE_API
/* -----------------------------------------------------
* Placeholder function which should be redefined by
* each platform.
* int plat_crash_console_init(void)
* Use normal console by default. Switch it to crash
* mode so serial consoles become active again.
* NOTE: This default implementation will only work for
* crashes that occur after a normal console (marked
* valid for the crash state) has been registered with
* the console framework. To debug crashes that occur
* earlier, the platform has to override these functions
* with an implementation that initializes a console
* driver with hardcoded parameters. See
* docs/porting-guide.rst for more information.
* -----------------------------------------------------
*/
func plat_crash_console_init
#if defined(IMAGE_BL1)
/*
* BL1 code can possibly crash so early that the data segment is not yet
* accessible. Don't risk undefined behavior by trying to run the normal
* console framework. Platforms that want to debug BL1 will need to
* override this with custom functions that can run from registers only.
*/
mov x0, #0
ret
#else /* IMAGE_BL1 */
mov x3, x30
mov x0, #CONSOLE_FLAG_CRASH
bl console_switch_state
mov x0, #1
ret x3
#endif
endfunc plat_crash_console_init
/* -----------------------------------------------------
* void plat_crash_console_putc(int character)
* Output through the normal console by default.
* -----------------------------------------------------
*/
func plat_crash_console_putc
b console_putc
endfunc plat_crash_console_putc
/* -----------------------------------------------------
* void plat_crash_console_flush(void)
* Flush normal console by default.
* -----------------------------------------------------
*/
func plat_crash_console_flush
b console_flush
endfunc plat_crash_console_flush
#else /* MULTI_CONSOLE_API */
/* -----------------------------------------------------
* In the old API these are all no-op stubs that need to
* be overridden by the platform to be useful.
* -----------------------------------------------------
*/
func plat_crash_console_init
@ -66,23 +121,14 @@ func plat_crash_console_init
ret
endfunc plat_crash_console_init
/* -----------------------------------------------------
* Placeholder function which should be redefined by
* each platform.
* -----------------------------------------------------
*/
func plat_crash_console_putc
ret
endfunc plat_crash_console_putc
/* -----------------------------------------------------
* Placeholder function which should be redefined by
* each platform.
* -----------------------------------------------------
*/
func plat_crash_console_flush
ret
endfunc plat_crash_console_flush
#endif
/* -----------------------------------------------------
* Placeholder function which should be redefined by