Commit 482cf40c authored by David S. Miller's avatar David S. Miller

SPARC64: Ultra-III+ bug fix and better bad trap logging.

- Do not use PC-relative branch/call in Ultra-III+ parity error
trap vectors, we patch this into the trap table and then the PC-relative
values are wrong.
- When we take an irrecoverable trap at tl > 0, save away the full
trap stack to the kernel stack, then log it from the C code handler.
parent 8b1cec3e
......@@ -774,7 +774,14 @@ __do_instruction_access_exception_tl1:
membar #Sync
sethi %hi(109f), %g7
ba,pt %xcc, etraptl1
or %g7, %lo(109f), %g7 ! Merge in below
109: or %g7, %lo(109b), %g7
mov %l4, %o1
mov %l5, %o2
call instruction_access_exception_tl1
add %sp, STACK_BIAS + REGWIN_SZ, %o0
ba,pt %xcc, rtrap
clr %l6
__do_instruction_access_exception:
rdpr %pstate, %g4
wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
......@@ -1084,6 +1091,15 @@ cheetah_deferred_trap_vector_tl1:
.globl cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
cheetah_plus_dcpe_trap_vector:
membar #Sync
sethi %hi(do_cheetah_plus_data_parity), %g7
jmpl %g7 + %lo(do_cheetah_plus_data_parity), %g0
nop
nop
nop
nop
nop
do_cheetah_plus_data_parity:
ba,pt %xcc, etrap
rd %pc, %g7
mov 0x0, %o0
......@@ -1091,6 +1107,7 @@ cheetah_plus_dcpe_trap_vector:
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
cheetah_plus_dcpe_trap_vector_tl1:
membar #Sync
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
......@@ -1104,6 +1121,15 @@ cheetah_plus_dcpe_trap_vector_tl1:
.globl cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
cheetah_plus_icpe_trap_vector:
membar #Sync
sethi %hi(do_cheetah_plus_insn_parity), %g7
jmpl %g7 + %lo(do_cheetah_plus_insn_parity), %g0
nop
nop
nop
nop
nop
do_cheetah_plus_insn_parity:
ba,pt %xcc, etrap
rd %pc, %g7
mov 0x1, %o0
......@@ -1111,6 +1137,7 @@ cheetah_plus_icpe_trap_vector:
add %sp, STACK_BIAS + REGWIN_SZ, %o1
ba,pt %xcc, rtrap
clr %l6
cheetah_plus_icpe_trap_vector_tl1:
membar #Sync
wrpr PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
......
......@@ -109,8 +109,56 @@ etrap_irq:
stb %g0, [%l4 + %l3] ! Store Group
nop
etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles
sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1
etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
* We place this right after pt_regs on the trap stack. The layout
* is:
* 0x00 TL1's TSTATE
* 0x08 TL1's TPC
* 0x10 TL1's TNPC
* ...
* 0x58 TL4's TNPC
* 0x60 TL
*/
sub %sp, (24 * 8) + 8, %g2
rdpr %tl, %g1
wrpr %g0, 1, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x00]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x08]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x10]
wrpr %g0, 2, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x18]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x20]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x28]
wrpr %g0, 3, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x30]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x38]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x40]
wrpr %g0, 4, %tl
rdpr %tstate, %g3
stx %g3, [%g2 + STACK_BIAS + 0x48]
rdpr %tpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x50]
rdpr %tnpc, %g3
stx %g3, [%g2 + STACK_BIAS + 0x58]
wrpr %g1, %tl
stx %g1, [%g2 + STACK_BIAS + 0x60]
rdpr %tstate, %g1 ! Single Group+4bubbles
sub %g2, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1
ba,pt %xcc, 1b ! CTI Group
andcc %g1, TSTATE_PRIV, %g0 ! IEU0
......
......@@ -37,6 +37,33 @@
#include <linux/kmod.h>
#endif
/* When an irrecoverable trap occurs at tl > 0, the trap entry
* code logs the trap state registers at every level in the trap
* stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout
* is as follows:
*/
struct tl1_traplog {
struct {
unsigned long tstate;
unsigned long tpc;
unsigned long tnpc;
} trapstack[4];
unsigned long tl;
};
static void dump_tl1_traplog(struct tl1_traplog *p)
{
int i;
printk("TRAPLOG: Error at trap level 0x%lx, dumping track stack.\n",
p->tl);
for (i = 0; i < 4; i++) {
printk("TRAPLOG: Trap level %d TSTATE[%016lx] TPC[%016lx] TNPC[%016lx]\n",
i + 1,
p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc);
}
}
void bad_trap (struct pt_regs *regs, long lvl)
{
char buffer[32];
......@@ -66,8 +93,10 @@ void bad_trap (struct pt_regs *regs, long lvl)
void bad_trap_tl1 (struct pt_regs *regs, long lvl)
{
char buffer[24];
char buffer[32];
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
sprintf (buffer, "Bad trap %lx at tl>0", lvl);
die_if_kernel (buffer, regs);
}
......@@ -80,8 +109,8 @@ void do_BUG(const char *file, int line)
}
#endif
void instruction_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
void instruction_access_exception(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
siginfo_t info;
......@@ -102,6 +131,13 @@ void instruction_access_exception (struct pt_regs *regs,
force_sig_info(SIGSEGV, &info, current);
}
void instruction_access_exception_tl1(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
instruction_access_exception(regs, sfsr, sfar);
}
void data_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
......@@ -1689,56 +1725,67 @@ void do_cee(struct pt_regs *regs)
void do_cee_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Cache Error Exception", regs);
}
void do_dae_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Data Access Exception", regs);
}
void do_iae_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Instruction Access Exception", regs);
}
void do_div0_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: DIV0 Exception", regs);
}
void do_fpdis_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU Disabled", regs);
}
void do_fpieee_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU IEEE Exception", regs);
}
void do_fpother_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: FPU Other Exception", regs);
}
void do_ill_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Illegal Instruction Exception", regs);
}
void do_irq_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: IRQ Exception", regs);
}
void do_lddfmna_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: LDDF Exception", regs);
}
void do_stdfmna_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: STDF Exception", regs);
}
......@@ -1749,6 +1796,7 @@ void do_paw(struct pt_regs *regs)
void do_paw_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Phys Watchpoint Exception", regs);
}
......@@ -1759,11 +1807,13 @@ void do_vaw(struct pt_regs *regs)
void do_vaw_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Virt Watchpoint Exception", regs);
}
void do_tof_tl1(struct pt_regs *regs)
{
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
die_if_kernel("TL1: Tag Overflow Exception", regs);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment