zephyr/arch/sparc/core/fault_trap.S
Martin Åberg 83f733ce59 SPARC: improve fatal log
The fatal log now contains
- Trap type in human readable representation
- Integer registers visible to the program when trap was taken
- Special register values such as PC and PSR
- Backtrace with PC and SP

If CONFIG_EXTRA_EXCEPTION_INFO is enabled, then all the above is
logged. If not, only the special registers are logged.

The format is inspired by the GRMON debug monitor and TSIM simulator.
A quick guide on how to use the values is in fatal.c.

It now looks like this:

E: tt = 0x02, illegal_instruction
E:
E:       INS        LOCALS     OUTS       GLOBALS
E:   0:  00000000   f3900fc0   40007c50   00000000
E:   1:  00000000   40004bf0   40008d30   40008c00
E:   2:  00000000   40004bf4   40008000   00000003
E:   3:  40009158   00000000   40009000   00000002
E:   4:  40008fa8   40003c00   40008fa8   00000008
E:   5:  40009000   f3400fc0   00000000   00000080
E:   6:  4000a1f8   40000050   4000a190   00000000
E:   7:  40002308   00000000   40001fb8   000000c1
E:
E: psr: f30000c7   wim: 00000008   tbr: 40000020   y: 00000000
E:  pc: 4000a1f4   npc: 4000a1f8
E:
E:       pc         sp
E:  #0   4000a1f4   4000a190
E:  #1   40002308   4000a1f8
E:  #2   40003b24   4000a258

Signed-off-by: Martin Åberg <martin.aberg@gaisler.com>
2021-03-25 17:48:23 +01:00

134 lines
3.2 KiB
ArmAsm

/*
* Copyright (c) 2019-2020 Cobham Gaisler AB
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <linker/sections.h>
#include <offsets_short.h>
#include <arch/sparc/sparc.h>
GTEXT(__sparc_trap_except_reason)
GTEXT(__sparc_trap_fault)
/*
* Fault trap handler
*
* - IU state is saved and restored
*
* On entry:
* %l0: psr (set by trap code)
* %l1: pc
* %l2: npc
* %l6: tbr (set by trap code)
* %fp: %sp of current register window at trap time
* %g1: reason
*
* This trap handler will trash some of the global registers, which is OK since
* we will not return to where we trapped.
*/
SECTION_FUNC(TEXT, __sparc_trap_except_reason)
mov %g1, %l7
.Ldoit:
/* %g2, %g3 are used at manual window overflow so save temporarily */
mov %g2, %l4
mov %g3, %l5
/* We may have trapped into the invalid window. If so, make it valid. */
rd %wim, %g2
mov %g2, %l3
srl %g2, %l0, %g3
cmp %g3, 1
bne .Lwodone
nop
/* Do the window overflow. */
sll %g2, (CONFIG_SPARC_NWIN-1), %g3
srl %g2, 1, %g2
or %g2, %g3, %g2
/* Enter window to save. */
save
/* Install new wim calculated above. */
mov %g2, %wim
nop
nop
nop
/* Put registers on the dedicated save area of the ABI stack frame. */
std %l0, [%sp + 0x00]
std %l2, [%sp + 0x08]
std %l4, [%sp + 0x10]
std %l6, [%sp + 0x18]
std %i0, [%sp + 0x20]
std %i2, [%sp + 0x28]
std %i4, [%sp + 0x30]
std %i6, [%sp + 0x38]
/* Leave saved window. */
restore
.Lwodone:
mov %l4, %g2
mov %l5, %g3
/* Allocate an ABI stack frame and exception stack frame */
sub %fp, 96 + __z_arch_esf_t_SIZEOF, %sp
/*
* %fp: %sp of interrupted task
* %sp: %sp of interrupted task - ABI_frame - esf
*/
mov %l7, %o0
/* Fill in the content of the exception stack frame */
#if defined(CONFIG_EXTRA_EXCEPTION_INFO)
std %i0, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x00]
std %i2, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x08]
std %i4, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x10]
std %i6, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x18]
std %g0, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x00]
std %g2, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x08]
std %g4, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x10]
std %g6, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x18]
#endif
std %l0, [%sp + 96 + __z_arch_esf_t_psr_OFFSET] /* psr pc */
std %l2, [%sp + 96 + __z_arch_esf_t_npc_OFFSET] /* npc wim */
rd %y, %l7
std %l6, [%sp + 96 + __z_arch_esf_t_tbr_OFFSET] /* tbr y */
/* Enable traps, raise PIL to mask all maskable interrupts. */
or %l0, PSR_PIL, %o2
wr %o2, PSR_ET, %psr
nop
nop
nop
#if defined(CONFIG_EXTRA_EXCEPTION_INFO)
/* Flush all register windows to the stack. */
.rept CONFIG_SPARC_NWIN-1
save %sp, -64, %sp
.endr
.rept CONFIG_SPARC_NWIN-1
restore
.endr
#endif
/*
* reason is the first argument.
* Exception stack frame prepared earlier is the second argument.
*/
call z_sparc_fatal_error
add %sp, 96, %o1
/*
* Entry for trap we don't handle explicitly
*
* Just drop into __sparc_trap_except_reason with reason set to
* K_ERR_CPU_EXCEPTION. Note that "reason" is transported in %l7 of the
* trapped-into window and global %g1 is preserved.
*/
SECTION_FUNC(TEXT, __sparc_trap_fault)
b .Ldoit
/* K_ERR_CPU_EXCEPTION */
mov %g0, %l7