patch-2.1.44 linux/arch/sparc64/kernel/traps.c
Next file: linux/arch/sparc64/kernel/ttable.S
Previous file: linux/arch/sparc64/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 527
- Date:
Mon Jul 7 08:18:54 1997
- Orig file:
v2.1.43/linux/arch/sparc64/kernel/traps.c
- Orig date:
Mon Jun 16 16:35:54 1997
diff -u --recursive --new-file v2.1.43/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
@@ -1,14 +1,15 @@
-/* $Id: traps.c,v 1.19 1997/06/05 06:22:49 davem Exp $
- * arch/sparc/kernel/traps.c
+/* $Id: traps.c,v 1.29 1997/07/05 09:52:38 davem Exp $
+ * arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
/*
- * I hate traps on the sparc, grrr...
+ * I like traps on v9, :))))
*/
+#include <linux/config.h>
#include <linux/sched.h> /* for jiffies */
#include <linux/kernel.h>
#include <linux/signal.h>
@@ -123,6 +124,8 @@
int i;
#endif
+ if(strcmp(current->comm, "bash.sunos"))
+ return;
printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
current->comm, current->pid, regs->tpc, (int)g1);
#ifdef VERBOSE_SYSCALL_TRACING
@@ -153,53 +156,12 @@
unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
{
- printk("ret[%016lx]\n", retval);
+ if(!strcmp(current->comm, "bash.sunos"))
+ printk("ret[%016lx]\n", retval);
return retval;
}
#endif /* SYSCALL_TRACING */
-#if 0
-void user_rtrap_report(struct pt_regs *regs)
-{
- static int hits = 0;
-
- /* 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)
{
lock_kernel ();
@@ -221,168 +183,44 @@
{
char buffer[24];
- lock_kernel ();
+ lock_kernel();
sprintf (buffer, "Bad trap %lx at tl>0", lvl);
die_if_kernel (buffer, regs);
+ unlock_kernel();
}
void data_access_exception (struct pt_regs *regs)
{
- 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);
+ send_sig(SIGSEGV, current, 1);
}
void do_dae(struct pt_regs *regs)
{
- printk("DAE: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ send_sig(SIGSEGV, current, 1);
}
void instruction_access_exception (struct pt_regs *regs)
{
- lock_kernel ();
- printk ("Unhandled instruction access exception ");
- printk("sfsr %016lx\n", spitfire_get_isfsr());
- die_if_kernel("Instruction access exception", regs);
+ send_sig(SIGSEGV, current, 1);
}
void do_iae(struct pt_regs *regs)
{
- printk("IAE at %016lx\n", regs->tpc);
- while(1)
- barrier();
-}
-
-static unsigned long init_fsr = 0x0UL;
-static unsigned int init_fregs[64] __attribute__ ((aligned (64))) =
- { ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
- ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U };
-
-void do_fpdis(struct pt_regs *regs)
-{
- lock_kernel();
-
- regs->tstate |= TSTATE_PEF;
- fprs_write(FPRS_FEF);
-
- /* This is allowed now because the V9 ABI varargs passes floating
- * point args in floating point registers, so vsprintf() and sprintf()
- * cause problems. Luckily we never actually pass floating point values
- * to those routines in the kernel and the code generated just does
- * stores of them to the stack. Therefore, for the moment this fix
- * is sufficient. -DaveM
- */
- if(regs->tstate & TSTATE_PRIV)
- goto out;
-
-#ifndef __SMP__
- if(last_task_used_math == current)
- goto out;
- if(last_task_used_math) {
- struct task_struct *fptask = last_task_used_math;
-
- if(fptask->tss.flags & SPARC_FLAG_32BIT)
- fpsave32((unsigned long *)&fptask->tss.float_regs[0],
- &fptask->tss.fsr);
- else
- fpsave((unsigned long *)&fptask->tss.float_regs[0],
- &fptask->tss.fsr);
- }
- last_task_used_math = current;
- if(current->used_math) {
- if(current->tss.flags & SPARC_FLAG_32BIT)
- fpload32(¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- else
- fpload(¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- } else {
- /* Set inital sane state. */
- fpload(&init_fregs[0], &init_fsr);
- current->used_math = 1;
- }
-#else
- if(!current->used_math) {
- fpload(&init_fregs[0], &init_fsr);
- current->used_math = 1;
- } else {
- if(current->tss.flags & SPARC_FLAG_32BIT)
- fpload32(¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- else
- fpload(¤t->tss.float_regs[0],
- ¤t->tss.fsr);
- }
- current->flags |= PF_USEDFPU;
-#endif
-#ifndef __SMP__
-out:
-#endif
- unlock_kernel();
+ send_sig(SIGSEGV, current, 1);
}
-static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
-static unsigned long fake_fsr;
-
void do_fpe_common(struct pt_regs *regs)
{
- static int calls = 0;
-#ifndef __SMP__
- struct task_struct *fpt = last_task_used_math;
-#else
- struct task_struct *fpt = current;
-#endif
-
- lock_kernel();
- fprs_write(FPRS_FEF);
-
-#ifndef __SMP__
- if(!fpt) {
-#else
- if(!(fpt->flags & PF_USEDFPU)) {
-#endif
- fpsave(&fake_regs[0], &fake_fsr);
- regs->tstate &= ~(TSTATE_PEF);
- goto out;
- }
- if(fpt->tss.flags & SPARC_FLAG_32BIT)
- fpsave32((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
- else
- fpsave((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
- fpt->tss.sig_address = regs->tpc;
- fpt->tss.sig_desc = SUBSIG_FPERROR;
-#ifdef __SMP__
- fpt->flags &= ~PF_USEDFPU;
-#endif
if(regs->tstate & TSTATE_PRIV) {
- printk("WARNING: FPU exception from kernel mode. at pc=%016lx\n",
- regs->tpc);
regs->tpc = regs->tnpc;
regs->tnpc += 4;
- calls++;
- if(calls > 2)
- die_if_kernel("Too many Penguin-FPU traps from kernel mode",
- regs);
- goto out;
+ } else {
+ lock_kernel();
+ current->tss.sig_address = regs->tpc;
+ current->tss.sig_desc = SUBSIG_FPERROR;
+ send_sig(SIGFPE, current, 1);
+ unlock_kernel();
}
- send_sig(SIGFPE, fpt, 1);
-#ifndef __SMP__
- last_task_used_math = NULL;
-#endif
- regs->tstate &= ~TSTATE_PEF;
- if(calls > 0)
- calls = 0;
-out:
- unlock_kernel();
}
void do_fpieee(struct pt_regs *regs)
@@ -397,16 +235,16 @@
void do_tof(struct pt_regs *regs)
{
- printk("TOF: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ if(regs->tstate & TSTATE_PRIV)
+ die_if_kernel("Penguin overflow trap from kernel mode", regs);
+ current->tss.sig_address = regs->tpc;
+ current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
+ send_sig(SIGEMT, current, 1);
}
void do_div0(struct pt_regs *regs)
{
- printk("DIV0: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ send_sig(SIGILL, current, 1);
}
void instruction_dump (unsigned int *pc)
@@ -426,7 +264,7 @@
/* Amuse the user. */
printk(
" \\|/ ____ \\|/\n"
-" \"@'/ .` \\`@\"\n"
+" \"@'/ .. \\`@\"\n"
" /_| \\__/ |_\\\n"
" \\__U_/\n");
@@ -437,17 +275,15 @@
struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS);
- if(rw) {
+ /* Stop the back trace when we hit userland or we
+ * find some badly aligned kernel stack.
+ */
+ while(rw &&
+ (((unsigned long) rw) >= PAGE_OFFSET) &&
+ !(((unsigned long) rw) & 0x7)) {
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:");
@@ -465,16 +301,6 @@
lock_kernel();
if(tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
-#if 1
- {
- unsigned int insn;
-
- printk("Ill instr. at pc=%016lx ", pc);
- get_user(insn, ((unsigned int *)pc));
- printk("insn=[%08x]\n", insn);
- show_regs(regs);
- }
-#endif
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_ILLINST;
send_sig(SIGILL, current, 1);
@@ -483,13 +309,11 @@
void mem_address_unaligned(struct pt_regs *regs)
{
- printk("AIEEE: do_mna at %016lx\n", regs->tpc);
- show_regs(regs);
if(regs->tstate & TSTATE_PRIV) {
- printk("MNA from kernel, spinning\n");
- sti();
- while(1)
- barrier();
+ extern void kernel_unaligned_trap(struct pt_regs *regs,
+ unsigned int insn);
+
+ return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc));
} else {
current->tss.sig_address = regs->tpc;
current->tss.sig_desc = SUBSIG_PRIVINST;
@@ -499,16 +323,17 @@
void do_privop(struct pt_regs *regs)
{
- printk("PRIVOP: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ current->tss.sig_address = regs->tpc;
+ current->tss.sig_desc = SUBSIG_PRIVINST;
+ send_sig(SIGILL, current, 1);
}
void do_privact(struct pt_regs *regs)
{
- printk("PRIVACT: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ current->tss.sig_address = regs->tpc;
+ current->tss.sig_desc = SUBSIG_PRIVINST;
+ send_sig(SIGILL, current, 1);
+ unlock_kernel();
}
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -537,11 +362,6 @@
}
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_PRIVINST;
-#if 0
- show_regs (regs);
- instruction_dump ((unsigned long *) regs->tpc);
- printk ("do_MNA!\n");
-#endif
send_sig(SIGBUS, current, 1);
unlock_kernel();
}
@@ -553,6 +373,134 @@
send_sig(SIGILL, current, 1);
unlock_kernel();
}
+
+/* Trap level 1 stuff or other traps we should never see... */
+void do_cee(struct pt_regs *regs)
+{
+ die_if_kernel("TL0: Cache Error Exception", regs);
+}
+
+void do_cee_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Cache Error Exception", regs);
+}
+
+void do_dae_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Data Access Exception", regs);
+}
+
+void do_iae_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Instruction Access Exception", regs);
+}
+
+void do_div0_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: DIV0 Exception", regs);
+}
+
+void do_fpdis_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: FPU Disabled", regs);
+}
+
+void do_fpieee_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: FPU IEEE Exception", regs);
+}
+
+void do_fpother_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: FPU Other Exception", regs);
+}
+
+void do_ill_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Illegal Instruction Exception", regs);
+}
+
+void do_irq_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: IRQ Exception", regs);
+}
+
+void do_lddfmna(struct pt_regs *regs)
+{
+ die_if_kernel("TL0: LDDF Exception", regs);
+}
+
+void do_lddfmna_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: LDDF Exception", regs);
+}
+
+void do_stdfmna(struct pt_regs *regs)
+{
+ die_if_kernel("TL0: STDF Exception", regs);
+}
+
+void do_stdfmna_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: STDF Exception", regs);
+}
+
+void do_paw(struct pt_regs *regs)
+{
+ die_if_kernel("TL0: Phys Watchpoint Exception", regs);
+}
+
+void do_paw_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Phys Watchpoint Exception", regs);
+}
+
+void do_vaw(struct pt_regs *regs)
+{
+ die_if_kernel("TL0: Virt Watchpoint Exception", regs);
+}
+
+void do_vaw_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Virt Watchpoint Exception", regs);
+}
+
+void do_tof_tl1(struct pt_regs *regs)
+{
+ die_if_kernel("TL1: Tag Overflow Exception", regs);
+}
+
+#ifdef CONFIG_EC_FLUSH_TRAP
+void cache_flush_trap(struct pt_regs *regs)
+{
+#ifndef __SMP__
+ unsigned node = linux_cpus[get_cpuid()].prom_node;
+#else
+#error SMP not supported on sparc64 yet
+#endif
+ int size = prom_getintdefault(node, "ecache-size", 512*1024);
+ int i, j;
+ unsigned long addr, page_nr;
+
+ regs->tpc = regs->tnpc;
+ regs->tnpc = regs->tnpc + 4;
+ if (!suser()) return;
+ size >>= PAGE_SHIFT;
+ addr = PAGE_OFFSET - PAGE_SIZE;
+ for (i = 0; i < size; i++) {
+ do {
+ addr += PAGE_SIZE;
+ page_nr = MAP_NR(addr);
+ if (page_nr >= max_mapnr) {
+ return;
+ }
+ } while (!PageReserved (mem_map + page_nr));
+ /* E-Cache line size is 64B. Let us pollute it :)) */
+ for (j = 0; j < PAGE_SIZE; j += 64)
+ __asm__ __volatile__ ("ldx [%0 + %1], %%g1" : : "r" (j), "r" (addr) : "g1");
+ }
+}
+#endif
void trap_init(void)
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov