diff options
author | marius <marius@FreeBSD.org> | 2010-04-02 10:36:40 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2010-04-02 10:36:40 +0000 |
commit | 6095f153a8d278b211795821aea246185b86e58c (patch) | |
tree | 63665930cabab1fb89dcc35f3a542b94c72ce296 | |
parent | e14ccde629ef57d3eb9b2e301b0789029e6ba32d (diff) | |
download | FreeBSD-src-6095f153a8d278b211795821aea246185b86e58c.zip FreeBSD-src-6095f153a8d278b211795821aea246185b86e58c.tar.gz |
- Try do deal gracefully with correctable ECC errors.
- Improve the reporting of unhandled kernel and user traps.
-rw-r--r-- | sys/sparc64/sparc64/trap.c | 58 |
1 files changed, 52 insertions, 6 deletions
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index 3df335b..bbbe902 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -106,6 +106,7 @@ void trap(struct trapframe *tf); void syscall(struct trapframe *tf); static int fetch_syscall_args(struct thread *td, struct syscall_args *sa); +static int trap_cecc(void); static int trap_pfault(struct thread *td, struct trapframe *tf); extern char copy_fault[]; @@ -240,6 +241,10 @@ int debugger_on_signal = 0; SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW, &debugger_on_signal, 0, ""); +u_int corrected_ecc = 0; +SYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0, + "corrected ECC errors"); + /* * SUNW,set-trap-table allows to take over %tba from the PROM, which * will turn off interrupts and handle outstanding ones while doing so, @@ -308,10 +313,16 @@ trap(struct trapframe *tf) case T_SPILL: sig = rwindow_save(td); break; + case T_CORRECTED_ECC_ERROR: + sig = trap_cecc(); + break; default: - if (tf->tf_type < 0 || tf->tf_type >= T_MAX || - trap_sig[tf->tf_type] == -1) - panic("trap: bad trap type"); + if (tf->tf_type < 0 || tf->tf_type >= T_MAX) + panic("trap: bad trap type %#lx (user)", + tf->tf_type); + else if (trap_sig[tf->tf_type] == -1) + panic("trap: %s (user)", + trap_msg[tf->tf_type]); sig = trap_sig[tf->tf_type]; break; } @@ -400,18 +411,53 @@ trap(struct trapframe *tf) } error = 1; break; + case T_CORRECTED_ECC_ERROR: + error = trap_cecc(); + break; default: error = 1; break; } - if (error != 0) - panic("trap: %s", trap_msg[tf->tf_type & ~T_KERNEL]); + if (error != 0) { + tf->tf_type &= ~T_KERNEL; + if (tf->tf_type < 0 || tf->tf_type >= T_MAX) + panic("trap: bad trap type %#lx (kernel)", + tf->tf_type); + else if (trap_sig[tf->tf_type] == -1) + panic("trap: %s (kernel)", + trap_msg[tf->tf_type]); + } } CTR1(KTR_TRAP, "trap: td=%p return", td); } static int +trap_cecc(void) +{ + u_long eee; + + /* + * Turn off (non-)correctable error reporting while we're dealing + * with the error. + */ + eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG); + stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN | + AA_ESTATE_CEEN)); + /* Flush the caches in order ensure no corrupt data got installed. */ + cache_flush(); + /* Ensure the caches are still turned on (should be). */ + cache_enable(PCPU_GET(impl)); + /* Clear the the error from the AFSR. */ + stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR)); + corrected_ecc++; + printf("corrected ECC error\n"); + /* Turn (non-)correctable error reporting back on. */ + stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee); + return (0); +} + +static int trap_pfault(struct thread *td, struct trapframe *tf) { struct vmspace *vm; @@ -664,7 +710,7 @@ syscall(struct trapframe *tf) */ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ? - syscallnames[sa.code] : "???"); + syscallnames[sa.code] : "???"); KASSERT(td->td_critnest == 0, ("System call %s returning in a critical section", (sa.code >= 0 && sa.code < SYS_MAXSYSCALL) ? |