patch-2.1.126 linux/arch/mips/kernel/traps.c
Next file: linux/arch/mips/kernel/unaligned.c
Previous file: linux/arch/mips/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 348
- Date:
Tue Oct 20 13:52:54 1998
- Orig file:
v2.1.125/linux/arch/mips/kernel/traps.c
- Orig date:
Fri May 8 23:14:43 1998
diff -u --recursive --new-file v2.1.125/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
@@ -1,14 +1,11 @@
-/*
- * arch/mips/kernel/traps.c
+/* $Id: traps.c,v 1.20 1998/10/14 20:26:26 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright 1994, 1995, 1996, 1997 by Ralf Baechle
+ * Copyright 1994, 1995, 1996, 1997, 1998 by Ralf Baechle
* Modified for R3000 by Paul M. Antoine, 1995, 1996
- *
- * $Id: traps.c,v 1.10 1998/05/04 09:17:57 ralf Exp $
*/
#include <linux/config.h>
#include <linux/init.h>
@@ -20,7 +17,6 @@
#include <asm/branch.h>
#include <asm/cachectl.h>
#include <asm/jazz.h>
-#include <asm/vector.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/bootinfo.h>
@@ -28,8 +24,6 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#undef CONF_DEBUG_EXCEPTIONS
-
static inline void console_verbose(void)
{
extern int console_loglevel;
@@ -61,9 +55,7 @@
extern asmlinkage void handle_cpu(void);
extern asmlinkage void handle_ov(void);
extern asmlinkage void handle_tr(void);
-extern asmlinkage void handle_vcei(void);
extern asmlinkage void handle_fpe(void);
-extern asmlinkage void handle_vced(void);
extern asmlinkage void handle_watch(void);
extern asmlinkage void handle_reserved(void);
@@ -71,6 +63,7 @@
char watch_available = 0;
char dedicated_iv_available = 0;
+char vce_available = 0;
void (*ibe_board_handler)(struct pt_regs *regs);
void (*dbe_board_handler)(struct pt_regs *regs);
@@ -159,10 +152,9 @@
}
else
printk("(Bad address in epc)\n");
- do_exit(SIGSEGV);
}
-void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+void die(const char * str, struct pt_regs * regs, unsigned long err)
{
if (user_mode(regs)) /* Just return if in user mode. */
return;
@@ -173,6 +165,12 @@
do_exit(SIGSEGV);
}
+void die_if_kernel(const char * str, struct pt_regs * regs, unsigned long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
+}
+
static void default_be_board_handler(struct pt_regs *regs)
{
/*
@@ -183,31 +181,21 @@
void do_ibe(struct pt_regs *regs)
{
- lock_kernel();
show_regs(regs); while(1);
ibe_board_handler(regs);
- unlock_kernel();
}
void do_dbe(struct pt_regs *regs)
{
- lock_kernel();
show_regs(regs); while(1);
dbe_board_handler(regs);
- unlock_kernel();
}
void do_ov(struct pt_regs *regs)
{
- lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
if (compute_return_epc(regs))
- goto out;
+ return;
force_sig(SIGFPE, current);
-out:
- unlock_kernel();
}
#ifdef CONFIG_MIPS_FPE_MODULE
@@ -235,6 +223,9 @@
*/
void do_fpe(struct pt_regs *regs, unsigned long fcr31)
{
+ unsigned long pc;
+ unsigned int insn;
+
#ifdef CONFIG_MIPS_FPE_MODULE
if (fpe_handler != NULL) {
fpe_handler(regs, fcr31);
@@ -242,9 +233,6 @@
}
#endif
lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
if (fcr31 & 0x20000) {
/* Retry instruction with flush to zero ... */
if (!(fcr31 & (1<<24))) {
@@ -258,13 +246,22 @@
: "r" (fcr31));
goto out;
}
- printk("Unimplemented exception at 0x%08lx in %s.\n",
- regs->cp0_epc, current->comm);
+ pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
+ if (get_user(insn, (unsigned int *)pc)) {
+ /* XXX Can this happen? */
+ force_sig(SIGSEGV, current);
+ }
+
+ printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
+ insn, regs->cp0_epc, current->comm);
+ simfp(insn);
}
if (compute_return_epc(regs))
goto out;
- force_sig(SIGFPE, current);
+ //force_sig(SIGFPE, current);
+ printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
+
out:
unlock_kernel();
}
@@ -286,72 +283,53 @@
return 0;
}
-static inline void
-do_bp_and_tr(struct pt_regs *regs, char *exc, unsigned int trapcode)
-{
- /*
- * (A short test says that IRIX 5.3 sends SIGTRAP for all break
- * insns, even for break codes that indicate arithmetic failures.
- * Wiered ...)
- */
- force_sig(SIGTRAP, current);
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
-}
void do_bp(struct pt_regs *regs)
{
unsigned int opcode, bcode;
- lock_kernel();
/*
* There is the ancient bug in the MIPS assemblers that the break
* code starts left to bit 16 instead to bit 6 in the opcode.
* Gas is bug-compatible ...
*/
-#ifdef CONF_DEBUG_EXCEPTIONS
- printk("BREAKPOINT at %08lx\n", regs->cp0_epc);
-#endif
if (get_insn_opcode(regs, &opcode))
- goto out;
+ return;
bcode = ((opcode >> 16) & ((1 << 20) - 1));
- do_bp_and_tr(regs, "bp", bcode);
-
- if (compute_return_epc(regs))
- goto out;
-out:
- unlock_kernel();
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Wiered ...)
+ */
+ force_sig(SIGTRAP, current);
}
void do_tr(struct pt_regs *regs)
{
unsigned int opcode, bcode;
- lock_kernel();
if (get_insn_opcode(regs, &opcode))
- goto out;
+ return;
bcode = ((opcode >> 6) & ((1 << 20) - 1));
- do_bp_and_tr(regs, "tr", bcode);
-out:
- unlock_kernel();
+ /*
+ * (A short test says that IRIX 5.3 sends SIGTRAP for all break
+ * insns, even for break codes that indicate arithmetic failures.
+ * Wiered ...)
+ */
+ force_sig(SIGTRAP, current);
}
void do_ri(struct pt_regs *regs)
{
lock_kernel();
-#ifdef CONF_DEBUG_EXCEPTIONS
- show_regs(regs);
-#endif
printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+ unlock_kernel();
if (compute_return_epc(regs))
- goto out;
+ return;
force_sig(SIGILL, current);
-out:
- unlock_kernel();
}
void do_cpu(struct pt_regs *regs)
@@ -364,7 +342,7 @@
regs->cp0_status |= ST0_CU1;
if (last_task_used_math == current)
- goto out;
+ return;
if (current->used_math) { /* Using the FPU again. */
r4xx0_lazy_fpu_switch(last_task_used_math);
@@ -377,56 +355,27 @@
return;
bad_cid:
- lock_kernel();
force_sig(SIGILL, current);
- unlock_kernel();
-out:
-}
-
-void do_vcei(struct pt_regs *regs)
-{
- lock_kernel();
- /*
- * Only possible on R4[04]00[SM]C. No handler because I don't have
- * such a cpu. Theory says this exception doesn't happen.
- */
- panic("Caught VCEI exception - should not happen");
- unlock_kernel();
-}
-
-void do_vced(struct pt_regs *regs)
-{
- lock_kernel();
- /*
- * Only possible on R4[04]00[SM]C. No handler because I don't have
- * such a cpu. Theory says this exception doesn't happen.
- */
- panic("Caught VCE exception - should not happen");
- unlock_kernel();
}
void do_watch(struct pt_regs *regs)
{
- lock_kernel();
/*
* We use the watch exception where available to detect stack
* overflows.
*/
show_regs(regs);
panic("Caught WATCH exception - probably caused by stack overflow.");
- unlock_kernel();
}
void do_reserved(struct pt_regs *regs)
{
- lock_kernel();
/*
* Game over - no way to handle this if it ever occurs.
* Most probably caused by a new unknown cpu type or
* after another deadly hard/software error.
*/
panic("Caught reserved exception - should not happen.");
- unlock_kernel();
}
static inline void watch_init(unsigned long cputype)
@@ -545,11 +494,8 @@
case CPU_R4400MC:
case CPU_R4000SC:
case CPU_R4400SC:
- /* XXX The following won't work because we _cannot_
- * XXX perform any load/store before the VCE handler.
- */
- set_except_vector(14, handle_vcei);
- set_except_vector(31, handle_vced);
+ vce_available = 1;
+ /* Fall through ... */
case CPU_R4000PC:
case CPU_R4400PC:
case CPU_R4200:
@@ -565,13 +511,16 @@
else
memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
- /*
- * The idea is that this special r4000 general exception
- * vector will check for VCE exceptions before calling
- * out of the exception array. XXX TODO
- */
+ /* Cache error vector */
memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
- memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+
+ if (vce_available) {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
+ 0x180);
+ } else {
+ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+ 0x100);
+ }
save_fp_context = r4k_save_fp_context;
restore_fp_context = r4k_restore_fp_context;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov