patch-2.4.0-test3 linux/arch/mips64/mm/fault.c

Next file: linux/arch/mips64/mm/init.c
Previous file: linux/arch/mips64/mm/andes.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c
@@ -1,11 +1,10 @@
-/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj 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 (C) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 by Silicon Graphics
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
  */
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -41,7 +40,8 @@
 asmlinkage void
 dodebug(abi64_no_regargs, struct pt_regs regs)
 {
-	printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
+	printk("Got syscall %ld, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2],
+	       smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
 }
 
 asmlinkage void
@@ -68,9 +68,10 @@
 	struct vm_area_struct * vma;
 	struct task_struct *tsk = current;
 	struct mm_struct *mm = tsk->mm;
-	int si_code = SEGV_MAPERR;
 	unsigned long fixup;
+	siginfo_t info;
 
+	info.si_code = SEGV_MAPERR;
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
@@ -96,7 +97,7 @@
  * we can handle it..
  */
 good_area:
-	si_code = SEGV_ACCERR;
+	info.si_code = SEGV_ACCERR;
 
 	if (write) {
 		if (!(vma->vm_flags & VM_WRITE))
@@ -134,8 +135,14 @@
 bad_area:
 	up(&mm->mmap_sem);
 
+	/*
+	 * Quickly check for vmalloc range faults.
+	 */
+	if ((!vma) && (address >= VMALLOC_START) && (address < VMALLOC_END)) {
+		printk("Fix vmalloc invalidate fault\n");
+		while(1);
+	}
 	if (user_mode(regs)) {
-		struct siginfo si;
 		tsk->thread.cp0_badvaddr = address;
 		tsk->thread.error_code = write;
 #if 0
@@ -147,10 +154,11 @@
 		       (unsigned long) regs->cp0_epc,
 		       (unsigned long) regs->regs[31]);
 #endif
-		si.si_signo = SIGSEGV;
-		si.si_code = si_code;
-		si.si_addr = (void *) address;
-		force_sig_info(SIGSEGV, &si, tsk);
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, tsk);
 		return;
 	}
 
@@ -174,8 +182,9 @@
 	 * terminate things with extreme prejudice.
 	 */
 	printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at "
-	       "address %08lx, epc == %08lx, ra == %08lx\n",
-	       smp_processor_id(), address, regs->cp0_epc, regs->regs[31]);
+	       "address %08lx, epc == %08x, ra == %08x\n",
+	       smp_processor_id(), address, (unsigned int) regs->cp0_epc,
+               (unsigned int) regs->regs[31]);
 	die("Oops", regs, write);
 	do_exit(SIGKILL);
 
@@ -198,7 +207,11 @@
 	 * or user mode.
 	 */
 	tsk->thread.cp0_badvaddr = address;
-	force_sig(SIGBUS, tsk);
+	info.si_code = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *) address;
+	force_sig_info(SIGBUS, &info, tsk);
 
 	/* Kernel mode? Handle exceptions or die */
 	if (!user_mode(regs))

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)