summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-06-03 09:23:20 +0000
commitac5ff8f4a72f7b4e66f73c3c6cb9fe7758cf6f12 (patch)
tree9fc7f8ce32e0d9a4aa055b2a58a05a5d727b333c /arch/sparc64/kernel/traps.c
parent52662ff3e66770fd7e4fc508c91056d29c08bff0 (diff)
Sync with Linux 2.1.42.
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r--arch/sparc64/kernel/traps.c305
1 files changed, 265 insertions, 40 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index c9774df06..6f96408ad 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.10 1997/05/18 08:42:16 davem Exp $
+/* $Id: traps.c,v 1.13 1997/05/27 19:30:08 jj Exp $
* arch/sparc/kernel/traps.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -24,76 +24,271 @@
#include <asm/unistd.h>
#include <asm/uaccess.h>
-/* #define TRAP_DEBUG */
+/* #define SYSCALL_TRACING */
+/* #define VERBOSE_SYSCALL_TRACING */
-struct trap_trace_entry {
- unsigned long pc;
- unsigned long type;
+#ifdef SYSCALL_TRACING
+#ifdef VERBOSE_SYSCALL_TRACING
+struct sdesc {
+ int scall_num;
+ char *name;
+ int num_args;
+ char arg_is_string[6];
+} sdesc_entries[] = {
+ { 0, "setup", 0, },
+ { 1, "exit", 1, { 0, } },
+ { 2, "fork", 0, },
+ { 3, "read", 3, { 0, 0, 0, } },
+ { 4, "write", 3, { 0, 0, 0, } },
+ { 5, "open", 3, { 1, 0, 0, } },
+ { 6, "close", 1, { 0, } },
+ { 7, "wait4", 4, { 0, 0, 0, 0, } },
+ { 8, "creat", 2, { 1, 0, } },
+ { 9, "link", 2, { 1, 1, } },
+ { 10, "unlink", 1, { 1, } },
+ { 11, "execv", 2, { 1, 0, } },
+ { 12, "chdir", 1, { 1, } },
+ { 15, "chmod", 2, { 1, 0, } },
+ { 16, "chown", 3, { 1, 0, 0, } },
+ { 17, "brk", 1, { 0, } },
+ { 19, "lseek", 3, { 0, 0, 0, } },
+ { 27, "alarm", 1, { 0, } },
+ { 29, "pause", 0, },
+ { 33, "access", 2, { 1, 0, } },
+ { 36, "sync", 0, },
+ { 37, "kill", 2, { 0, 0, } },
+ { 38, "stat", 2, { 1, 0, } },
+ { 40, "lstat", 2, { 1, 0, } },
+ { 41, "dup", 1, { 0, } },
+ { 42, "pipd", 0, },
+ { 54, "ioctl", 3, { 0, 0, 0, } },
+ { 57, "symlink", 2, { 1, 1, } },
+ { 58, "readlink", 3, { 1, 0, 0, } },
+ { 59, "execve", 3, { 1, 0, 0, } },
+ { 60, "umask", 1, { 0, } },
+ { 62, "fstat", 2, { 0, 0, } },
+ { 64, "getpagesize", 0, },
+ { 71, "mmap", 6, { 0, 0, 0, 0, 0, 0, } },
+ { 73, "munmap", 2, { 0, 0, } },
+ { 74, "mprotect", 3, { 0, 0, 0, } },
+ { 83, "setitimer", 3, { 0, 0, 0, } },
+ { 90, "dup2", 2, { 0, 0, } },
+ { 92, "fcntl", 3, { 0, 0, 0, } },
+ { 93, "select", 5, { 0, 0, 0, 0, 0, } },
+ { 97, "socket", 3, { 0, 0, 0, } },
+ { 98, "connect", 3, { 0, 0, 0, } },
+ { 99, "accept", 3, { 0, 0, 0, } },
+ { 101, "send", 4, { 0, 0, 0, 0, } },
+ { 102, "recv", 4, { 0, 0, 0, 0, } },
+ { 104, "bind", 3, { 0, 0, 0, } },
+ { 105, "setsockopt", 5, { 0, 0, 0, 0, 0, } },
+ { 106, "listen", 2, { 0, 0, } },
+ { 120, "readv", 3, { 0, 0, 0, } },
+ { 121, "writev", 3, { 0, 0, 0, } },
+ { 123, "fchown", 3, { 0, 0, 0, } },
+ { 124, "fchmod", 2, { 0, 0, } },
+ { 128, "rename", 2, { 1, 1, } },
+ { 129, "truncate", 2, { 1, 0, } },
+ { 130, "ftruncate", 2, { 0, 0, } },
+ { 131, "flock", 2, { 0, 0, } },
+ { 136, "mkdir", 2, { 1, 0, } },
+ { 137, "rmdir", 1, { 1, } },
+ { 146, "killpg", 1, { 0, } },
+ { 157, "statfs", 2, { 1, 0, } },
+ { 158, "fstatfs", 2, { 0, 0, } },
+ { 159, "umount", 1, { 1, } },
+ { 167, "mount", 5, { 1, 1, 1, 0, 0, } },
+ { 174, "getdents", 3, { 0, 0, 0, } },
+ { 176, "fchdir", 2, { 0, 0, } },
+ { 198, "sigaction", 3, { 0, 0, 0, } },
+ { 201, "sigsuspend", 1, { 0, } },
+ { 206, "socketcall", 2, { 0, 0, } },
+ { 216, "sigreturn", 0, },
+ { 230, "newselect", 5, { 0, 0, 0, 0, 0, } },
+ { 236, "llseek", 5, { 0, 0, 0, 0, 0, } },
+ { 251, "sysctl", 1, { 0, } },
};
+#define NUM_SDESC_ENTRIES (sizeof(sdesc_entries) / sizeof(sdesc_entries[0]))
+#endif
-int trap_curbuf = 0;
-struct trap_trace_entry trapbuf[1024];
+#ifdef VERBOSE_SYSCALL_TRACING
+static char scall_strbuf[512];
+#endif
-void syscall_trace_entry(struct pt_regs *regs)
+void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
{
- printk("%s[%d]: ", current->comm, current->pid);
- printk("scall<%ld> (could be %ld)\n", (long) regs->u_regs[UREG_G1],
- (long) regs->u_regs[UREG_I0]);
-}
+#ifdef VERBOSE_SYSCALL_TRACING
+ struct sdesc *sdp;
+ int i;
+#endif
-void syscall_trace_exit(struct pt_regs *regs)
-{
- printk("Syscall return check, reg dump.\n");
- show_regs(regs);
+ printk("SYS[%s:%d]: <%d> ", current->comm, current->pid, (int)g1);
+#ifdef VERBOSE_SYSCALL_TRACING
+ sdp = NULL;
+ for(i = 0; i < NUM_SDESC_ENTRIES; i++)
+ if(sdesc_entries[i].scall_num == g1) {
+ sdp = &sdesc_entries[i];
+ break;
+ }
+ if(sdp) {
+ printk("%s(", sdp->name);
+ for(i = 0; i < sdp->num_args; i++) {
+ if(i)
+ printk(",");
+ if(!sdp->arg_is_string[i])
+ printk("%08x", (unsigned int)regs->u_regs[UREG_I0 + i]);
+ else {
+ strncpy_from_user(scall_strbuf,
+ (char *)regs->u_regs[UREG_I0 + i],
+ 512);
+ printk("%s", scall_strbuf);
+ }
+ }
+ printk(") ");
+ }
+#endif
}
-void sparc64_dtlb_fault_handler (void)
+unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
{
- printk ("sparc64_dtlb_fault_handler\n");
- while (1);
- /* Die for now... */
+ printk("ret[%08x]\n", (unsigned int) retval);
+ return retval;
}
+#endif /* SYSCALL_TRACING */
-void sparc64_dtlb_refbit_handler (struct pt_regs *regs)
+#if 0
+void user_rtrap_report(struct pt_regs *regs)
{
- printk ("sparc64_dtlb_refbit_handler[%016lx]\n", regs->tpc);
- while (1);
- /* Die for now... */
-}
+ static int hits = 0;
-void sparc64_itlb_refbit_handler (void)
-{
- printk ("sparc64_itlb_refbit_handler\n");
- while (1);
- /* Die for now... */
+ /* Bwahhhhrggg... */
+ if(regs->tpc == 0x1f294UL && ++hits == 2) {
+ register unsigned long ctx asm("o4");
+ register unsigned long paddr asm("o5");
+ unsigned long cwp, wstate;
+
+ printk("RT[%016lx:%016lx] ", regs->tpc, regs->u_regs[UREG_I6]);
+ __asm__ __volatile__("rdpr %%cwp, %0" : "=r" (cwp));
+ __asm__ __volatile__("rdpr %%wstate, %0" : "=r" (wstate));
+ printk("CWP[%d] WSTATE[%016lx]\n"
+ "TSS( ksp[%016lx] kpc[%016lx] wstate[%016lx] w_saved[%d] flgs[%x]"
+ " cur_ds[%d] )\n", cwp, wstate,
+ current->tss.ksp, current->tss.kpc, current->tss.wstate,
+ (int) current->tss.w_saved, current->tss.flags,
+ current->tss.current_ds);
+ __asm__ __volatile__("
+ rdpr %%pstate, %%o3
+ wrpr %%o3, %2, %%pstate
+ mov %%g7, %%o5
+ mov 0x10, %%o4
+ ldxa [%%o4] %3, %%o4
+ wrpr %%o3, 0x0, %%pstate
+ " : "=r" (ctx), "=r" (paddr)
+ : "i" (PSTATE_MG|PSTATE_IE), "i" (ASI_DMMU));
+
+ printk("MMU[ppgd(%016lx)sctx(%d)] ", paddr, ctx);
+ printk("mm->context(%016lx) mm->pgd(%p)\n",
+ current->mm->context, current->mm->pgd);
+ printk("TASK: signal[%016lx] blocked[%016lx]\n",
+ current->signal, current->blocked);
+ show_regs(regs);
+ while(1)
+ barrier();
+ }
}
+#endif
void bad_trap (struct pt_regs *regs, long lvl)
{
- printk ("Bad trap %d (tstate %016lx tpc %016lx tnpc %016lx)\n", lvl, regs->tstate, regs->tpc, regs->tnpc);
- while (1);
- /* Die for now... */
+ lock_kernel ();
+ if (lvl < 0x100) {
+ char buffer[24];
+
+ sprintf (buffer, "Bad hw trap %lx at tl0\n", lvl);
+ die_if_kernel (buffer, regs);
+ }
+ if (regs->tstate & TSTATE_PRIV)
+ die_if_kernel ("Kernel bad trap", regs);
+ current->tss.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
+ current->tss.sig_address = regs->tpc;
+ send_sig(SIGILL, current, 1);
+ unlock_kernel ();
}
void bad_trap_tl1 (struct pt_regs *regs, long lvl)
{
- printk ("Bad trap %d at tl1+ (tstate %016lx tpc %016lx tnpc %016lx)\n", lvl, regs->tstate, regs->tpc, regs->tnpc);
- while (1);
- /* Die for now... */
+ char buffer[24];
+
+ lock_kernel ();
+ sprintf (buffer, "Bad trap %lx at tl>0", lvl);
+ die_if_kernel (buffer, regs);
}
void data_access_exception (struct pt_regs *regs)
{
- printk ("Unhandled data access exception sfsr %016lx sfar %016lx\n", spitfire_get_dsfsr(), spitfire_get_sfar());
+ lock_kernel ();
+ printk ("Unhandled data access exception ");
+ printk("sfsr %016lx sfar %016lx\n", spitfire_get_dsfsr(), spitfire_get_sfar());
die_if_kernel("Data access exception", regs);
}
+void do_dae(struct pt_regs *regs)
+{
+ printk("DAE: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void instruction_access_exception (struct pt_regs *regs)
{
- printk ("Unhandled instruction access exception sfsr %016lx\n", spitfire_get_isfsr());
+ lock_kernel ();
+ printk ("Unhandled instruction access exception ");
+ printk("sfsr %016lx\n", spitfire_get_isfsr());
die_if_kernel("Instruction access exception", regs);
}
+void do_iae(struct pt_regs *regs)
+{
+ printk("IAE at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpdis(struct pt_regs *regs)
+{
+ printk("FPDIS: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpieee(struct pt_regs *regs)
+{
+ printk("FPIEEE: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_fpother(struct pt_regs *regs)
+{
+ printk("FPOTHER: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_tof(struct pt_regs *regs)
+{
+ printk("TOF: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_div0(struct pt_regs *regs)
+{
+ printk("DIV0: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void instruction_dump (unsigned int *pc)
{
int i;
@@ -116,11 +311,27 @@ void die_if_kernel(char *str, struct pt_regs *regs)
" \\__U_/\n");
printk("%s(%d): %s\n", current->comm, current->pid, str);
+ __asm__ __volatile__("flushw");
show_regs(regs);
+ {
+ struct reg_window *rw = (struct reg_window *)
+ (regs->u_regs[UREG_FP] + STACK_BIAS);
+
+ if(rw) {
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ rw = (struct reg_window *)
+ (rw->ins[6] + STACK_BIAS);
+ if(rw) {
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ rw = (struct reg_window *)
+ (rw->ins[6] + STACK_BIAS);
+ if(rw)
+ printk("Caller[%016lx]\n", rw->ins[7]);
+ }
+ }
+ }
printk("Instruction DUMP:");
instruction_dump ((unsigned int *) regs->tpc);
- while(1)
- barrier();
if(regs->tstate & TSTATE_PRIV)
do_exit(SIGKILL);
do_exit(SIGSEGV);
@@ -160,6 +371,20 @@ void do_mna(struct pt_regs *regs)
barrier();
}
+void do_privop(struct pt_regs *regs)
+{
+ printk("PRIVOP: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
+void do_privact(struct pt_regs *regs)
+{
+ printk("PRIVACT: at %016lx\n", regs->tpc);
+ while(1)
+ barrier();
+}
+
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long tstate)
{