diff options
| author | Marius Strobl <marius@FreeBSD.org> | 2010-04-05 18:22:48 +0000 |
|---|---|---|
| committer | Marius Strobl <marius@FreeBSD.org> | 2010-04-05 18:22:48 +0000 |
| commit | 8d6acfc69de85378103885874c280c690110c054 (patch) | |
| tree | 723bc22565b8ea8989da2217dd9580b1b22c358a /sys | |
| parent | 6d07d8a8ba33de41c3db34be896ef07cf555d1f7 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/sparc64/sparc64/trap.c | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index eddf5a2ee361..64dd751f3a36 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$"); void trap(struct trapframe *tf); void syscall(struct trapframe *tf); +static int trap_cecc(void); static int trap_pfault(struct thread *td, struct trapframe *tf); extern char copy_fault[]; @@ -229,6 +230,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, @@ -297,10 +302,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; } @@ -389,18 +400,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; |
