patch-2.1.44 linux/arch/mips/mm/fault.c
Next file: linux/arch/mips/mm/init.c
Previous file: linux/arch/mips/mm/extable.c
Back to the patch index
Back to the overall index
- Lines: 124
- Date:
Thu Jun 26 12:33:38 1997
- Orig file:
v2.1.43/linux/arch/mips/mm/fault.c
- Orig date:
Wed Dec 13 02:39:44 1995
diff -u --recursive --new-file v2.1.43/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c
@@ -1,7 +1,7 @@
/*
* arch/mips/mm/fault.c
*
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*/
#include <linux/signal.h>
#include <linux/sched.h>
@@ -13,29 +13,43 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
-#include <asm/system.h>
-#include <asm/segment.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
extern void die_if_kernel(char *, struct pt_regs *, long);
+unsigned long asid_cache = ASID_FIRST_VERSION;
+
+/*
+ * Macro for exception fixup code to access integer registers.
+ */
+#define dpf_reg(r) (regs->regs[r])
+
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
* routines.
*/
-asmlinkage void
-do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address)
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+ unsigned long address)
{
struct vm_area_struct * vma;
+ struct task_struct *tsk = current;
+ struct mm_struct *mm = tsk->mm;
+ unsigned long fixup;
+ lock_kernel();
#if 0
- printk("do_page_fault() #1: %s %08lx (epc == %08lx, ra == %08lx)\n",
- writeaccess ? "writeaccess to" : "readaccess from",
- address, regs->cp0_epc, regs->reg31);
+ printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
+ address, writeaccess, regs->cp0_epc);
#endif
- vma = find_vma(current, address);
+ down(&mm->mmap_sem);
+ vma = find_vma(mm, address);
if (!vma)
goto bad_area;
if (vma->vm_start <= address)
@@ -56,29 +70,55 @@
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
- handle_mm_fault(vma, address, writeaccess);
- /* FIXME: This flushes the cache far to often */
- sys_cacheflush(address, PAGE_SIZE, BCACHE);
+ handle_mm_fault(tsk, vma, address, writeaccess);
+ up(&mm->mmap_sem);
- return;
+ goto out;
/*
* Something tried to access memory that isn't in our memory map..
* Fix it, but check if it's kernel or user first..
*/
bad_area:
+ up(&mm->mmap_sem);
+ /* Did we have an exception handler installed? */
+
+ fixup = search_exception_table(regs->cp0_epc);
+ if (fixup) {
+ long new_epc;
+ new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+ printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n",
+ regs->cp0_epc, new_epc);
+ regs->cp0_epc = new_epc;
+ goto out;
+ }
+
if (user_mode(regs)) {
+ tsk->tss.cp0_badvaddr = address;
+ tsk->tss.error_code = writeaccess;
+#if 1
+ printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
+ "%08lx (epc == %08lx, ra == %08lx)\n",
+ tsk->comm,
+ writeaccess ? "writeaccess to" : "readaccess from",
+ address,
+ (unsigned long) regs->cp0_epc,
+ (unsigned long) regs->regs[31]);
+#endif
+
current->tss.cp0_badvaddr = address;
current->tss.error_code = writeaccess;
- send_sig(SIGSEGV, current, 1);
- return;
+ force_sig(SIGSEGV, tsk);
+ goto out;
}
/*
* Oops. The kernel tried to access some bad page. We'll have to
* terminate things with extreme prejudice.
*/
printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
- "address %08lx\n", address);
+ "address %08lx, epc == %08lx\n", address, regs->cp0_epc);
die_if_kernel("Oops", regs, writeaccess);
do_exit(SIGKILL);
+out:
+ unlock_kernel();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov