patch-2.1.51 linux/arch/ppc/kernel/traps.c

Next file: linux/arch/ppc/ld.script
Previous file: linux/arch/ppc/kernel/time.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.50/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
@@ -1,9 +1,15 @@
 /*
  *  linux/arch/ppc/kernel/traps.c
  *
- *  Copyright (C) 1995  Gary Thomas
- *  Adapted for PowerPC by Gary Thomas
+ *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
  *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  and Paul Mackerras (paulus@cs.anu.edu.au)
  */
 
 /*
@@ -24,9 +30,21 @@
 #include <linux/config.h>
 
 #include <asm/pgtable.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/processor.h>
+
+extern int fix_alignment(struct pt_regs *);
+extern void bad_page_fault(struct pt_regs *, unsigned long);
+
+#ifdef CONFIG_XMON
+extern int xmon_bpt(struct pt_regs *regs);
+extern int xmon_sstep(struct pt_regs *regs);
+extern void xmon(struct pt_regs *regs);
+extern int xmon_iabr_match(struct pt_regs *regs);
+extern void (*xmon_fault_handler)(struct pt_regs *regs);
+#endif
 
 /*
  * Trap & Exception support
@@ -43,40 +61,53 @@
 	if (!user_mode(regs))
 	{
 		show_regs(regs);
-		print_backtrace(regs->gpr[1]);
-		panic("Exception in kernel pc %x signal %d",regs->nip,signr);
+		print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_XMON
+		xmon(regs);
+#endif
+		panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
 	}
 	force_sig(signr, current);
 }
 
+void
 MachineCheckException(struct pt_regs *regs)
 {
 	if ( !user_mode(regs) )
 	{
+#ifdef CONFIG_XMON
+		if (xmon_fault_handler) {
+			xmon_fault_handler(regs);
+			return;
+		}
+#endif
 		printk("Machine check in kernel mode.\n");
 		printk("Caused by (from msr): ");
-		printk("regs %08x ",regs);
+		printk("regs %p ",regs);
 		switch( regs->msr & 0x0000F000)
 		{
 		case (1<<12) :
 			printk("Machine check signal - probably due to mm fault\n"
 				"with mmu off\n");
-		break;
+			break;
 		case (1<<13) :
 			printk("Transfer error ack signal\n");
-		break;
+			break;
 		case (1<<14) :
 			printk("Data parity signal\n");
-		break;
+			break;
 		case (1<<15) :
 			printk("Address parity signal\n");
-		break;
+			break;
 		default:
 			printk("Unknown values in msr\n");
 		}
 		show_regs(regs);
-		print_backtrace(regs->gpr[1]);
-		panic("");
+		print_backtrace((unsigned long *)regs->gpr[1]);
+#ifdef CONFIG_XMON
+		xmon(regs);
+#endif
+		panic("machine check");
 	}
 	_exception(SIGSEGV, regs);	
 }
@@ -105,33 +136,71 @@
 	_exception(SIGTRAP, regs);	
 }
 
+void
 ProgramCheckException(struct pt_regs *regs)
 {
-	if (current->flags & PF_PTRACED)
+	if (regs->msr & 0x100000) {
+		/* IEEE FP exception */
+		_exception(SIGFPE, regs);
+	} else if (regs->msr & 0x20000) {
+		/* trap exception */
+#ifdef CONFIG_XMON
+		if (xmon_bpt(regs))
+			return;
+#endif
 		_exception(SIGTRAP, regs);
-	else
+	} else {
 		_exception(SIGILL, regs);
+	}
 }
 
+void
 SingleStepException(struct pt_regs *regs)
 {
 	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
+#ifdef CONFIG_XMON
+	if (xmon_sstep(regs))
+		return;
+#endif
 	_exception(SIGTRAP, regs);	
 }
 
+void
 AlignmentException(struct pt_regs *regs)
 {
+	int fixed;
+
+	if (last_task_used_math == current)
+		giveup_fpu();
+	fixed = fix_alignment(regs);
+	if (fixed == 1) {
+		regs->nip += 4;	/* skip over emulated instruction */
+		return;
+	}
+	if (fixed == -EFAULT) {
+		/* fixed == -EFAULT means the operand address was bad */
+		bad_page_fault(regs, regs->dar);
+		return;
+	}
 	_exception(SIGBUS, regs);	
 }
 
+void
+PromException(struct pt_regs *regs, int trap)
+{
+	regs->trap = trap;
+#ifdef CONFIG_XMON
+	xmon(regs);
+#endif
+	printk("Exception %lx in prom at PC: %lx, SR: %lx\n",
+	       regs->trap, regs->nip, regs->msr);
+	/* probably should turn up the toes here */
+}
+
+void
 trace_syscall(struct pt_regs *regs)
 {
-	static int count;
-	printk("Task: %08X(%d), PC: %08X/%08X, Syscall: %3d, Result: %s%d\n",
+	printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
 	       current, current->pid, regs->nip, regs->link, regs->gpr[0],
 	       regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
-	if (++count == 20)
-	{
-		count = 0;
-	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov