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 
  19 #include <asm/system.h>
  20 #include <asm/segment.h>
  21 #include <asm/mipsconfig.h>
  22 
  23 extern void die_if_kernel(char *, struct pt_regs *, long);
  24 
  25 /*
  26  * This routine handles page faults.  It determines the address,
  27  * and the problem, and then passes it off to one of the appropriate
  28  * routines.
  29  */
  30 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32         struct vm_area_struct * vma;
  33         unsigned long address;
  34         unsigned long page;
  35 
  36         /* get the address */
  37         __asm__("dmfc0\t%0,$8"
  38                 : "=r" (address));
  39 
  40         vma = find_vma(current, address);
  41         if (!vma)
  42                 goto bad_area;
  43         if (vma->vm_start <= address)
  44                 goto good_area;
  45         if (!(vma->vm_flags & VM_GROWSDOWN))
  46                 goto bad_area;
  47         if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
  48                 goto bad_area;
  49         vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
  50         vma->vm_start = (address & PAGE_MASK);
  51 /*
  52  * Ok, we have a good vm_area for this memory access, so
  53  * we can handle it..
  54  */
  55 good_area:
  56 #if 0
  57         if (regs->eflags & VM_MASK) {
  58                 unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
  59                 if (bit < 32)
  60                         current->tss.screen_bitmap |= 1 << bit;
  61         }
  62 #endif
  63         if (!(vma->vm_page_prot & PAGE_USER))
  64                 goto bad_area;
  65         if (error_code & PAGE_PRESENT) {
  66                 if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW)))
  67                         goto bad_area;
  68                 do_wp_page(vma, address, error_code);
  69                 return;
  70         }
  71 printk("do_page_fault: do_no_page(%x, %x, %d)", vma, address, error_code);
  72         do_no_page(vma, address, error_code);
  73         return;
  74 
  75 /*
  76  * Something tried to access memory that isn't in our memory map..
  77  * Fix it, but check if it's kernel or user first..
  78  */
  79 bad_area:
  80 printk("Bad Area...\n");
  81         if (error_code & PAGE_USER) {
  82                 current->tss.cp0_badvaddr = address;
  83                 current->tss.error_code = error_code;
  84                 current->tss.trap_no = 14;
  85                 send_sig(SIGSEGV, current, 1);
  86                 return;
  87         }
  88 /*
  89  * Oops. The kernel tried to access some bad page. We'll have to
  90  * terminate things with extreme prejudice.
  91  */
  92         printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
  93         if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
  94                 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
  95                 pg0[0] = PAGE_SHARED;
  96         } else
  97                 printk(KERN_ALERT "Unable to handle kernel paging request");
  98         printk(" at virtual address %08lx\n",address);
  99         page = current->tss.pg_dir;
 100         printk(KERN_ALERT "current->tss.pg_dir = %08lx\n", page);
 101         page = ((unsigned long *) page)[address >> 22];
 102         printk(KERN_ALERT "*pde = %08lx\n", page);
 103         if (page & PAGE_PRESENT) {
 104                 page &= PAGE_MASK;
 105                 address &= 0x003ff000;
 106                 page = ((unsigned long *) page)[address >> PAGE_SHIFT];
 107                 printk(KERN_ALERT "*pte = %08lx\n", page);
 108         }
 109         die_if_kernel("Oops", regs, error_code);
 110         do_exit(SIGKILL);
 111 }

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