root/arch/mips/mm/fault.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_page_fault

   1 /*
   2  *  arch/mips/mm/fault.c
   3  *
   4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
   5  *  Ported to MIPS by Ralf Baechle
   6  */
   7 
   8 #include <linux/config.h>
   9 #include <linux/signal.h>
  10 #include <linux/sched.h>
  11 #include <linux/head.h>
  12 #include <linux/kernel.h>
  13 #include <linux/errno.h>
  14 #include <linux/string.h>
  15 #include <linux/types.h>
  16 #include <linux/ptrace.h>
  17 #include <linux/mman.h>
  18 #include <linux/mm.h>
  19 
  20 #include <asm/system.h>
  21 #include <asm/segment.h>
  22 #include <asm/mipsconfig.h>
  23 
  24 extern void die_if_kernel(char *, struct pt_regs *, long);
  25 
  26 /*
  27  * This routine handles page faults.  It determines the address,
  28  * and the problem, and then passes it off to one of the appropriate
  29  * routines.
  30  *
  31  * The error_code parameter just the same as in the i386 version:
  32  *
  33  *      bit 0 == 0 means no page found, 1 means protection fault
  34  *      bit 1 == 0 means read, 1 means write
  35  *      bit 2 == 0 means kernel, 1 means user-mode
  36  */
  37 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  38 {
  39         struct vm_area_struct * vma;
  40         unsigned long address;
  41         unsigned long page;
  42 
  43         /* get the address */
  44         __asm__("dmfc0\t%0,$8"
  45                 : "=r" (address));
  46 
  47         for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
  48                 if (!vma)
  49                         goto bad_area;
  50                 if (vma->vm_end > address)
  51                         break;
  52         }
  53         if (vma->vm_start <= address)
  54                 goto good_area;
  55         if (!(vma->vm_flags & VM_GROWSDOWN))
  56                 goto bad_area;
  57         if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
  58                 goto bad_area;
  59         vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
  60         vma->vm_start = (address & PAGE_MASK);
  61 /*
  62  * Ok, we have a good vm_area for this memory access, so
  63  * we can handle it..
  64  */
  65 good_area:
  66         /*
  67          * was it a write?
  68          */
  69         if (error_code & 2) {
  70                 if (!(vma->vm_flags & VM_WRITE))
  71                         goto bad_area;
  72         } else {
  73                 /* read with protection fault? */
  74                 if (error_code & 1)
  75                         goto bad_area;
  76                 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
  77                         goto bad_area;
  78         }
  79         if (error_code & 1) {
  80                 do_wp_page(vma, address, error_code & 2);
  81                 return;
  82         }
  83         do_no_page(vma, address, error_code & 2);
  84         return;
  85 
  86 /*
  87  * Something tried to access memory that isn't in our memory map..
  88  * Fix it, but check if it's kernel or user first..
  89  */
  90 bad_area:
  91         if (user_mode(regs)) {
  92                 current->tss.cp0_badvaddr = address;
  93                 current->tss.error_code = error_code;
  94 #if 0
  95                 current->tss.trap_no = 14;
  96 #endif
  97                 send_sig(SIGSEGV, current, 1);
  98                 return;
  99         }
 100         /*
 101          * Oops. The kernel tried to access some bad page. We'll have to
 102          * terminate things with extreme prejudice.
 103          */
 104         if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
 105                 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 106                 pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
 107         } else
 108                 printk(KERN_ALERT "Unable to handle kernel paging request");
 109         printk(" at virtual address %08lx\n",address);
 110         page = current->tss.pg_dir;
 111         printk(KERN_ALERT "current->tss.pg_dir = %08lx\n", page);
 112         page = ((unsigned long *) page)[address >> PGDIR_SHIFT];
 113         printk(KERN_ALERT "*pde = %08lx\n", page);
 114         if (page & 1) {
 115                 page &= PAGE_MASK;
 116                 address &= 0x003ff000;
 117                 page = ((unsigned long *) page)[address >> PAGE_SHIFT];
 118                 printk(KERN_ALERT "*pte = %08lx\n", page);
 119         }
 120         die_if_kernel("Oops", regs, error_code);
 121         do_exit(SIGKILL);
 122 }

/* [previous][next][first][last][top][bottom][index][help] */