root/arch/i386/mm/fault.c

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

DEFINITIONS

This source file includes following definitions.
  1. do_page_fault

   1 /*
   2  *  linux/arch/i386/mm/fault.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   6 
   7 #include <linux/config.h>
   8 #include <linux/signal.h>
   9 #include <linux/sched.h>
  10 #include <linux/head.h>
  11 #include <linux/kernel.h>
  12 #include <linux/errno.h>
  13 #include <linux/string.h>
  14 #include <linux/types.h>
  15 #include <linux/ptrace.h>
  16 #include <linux/mman.h>
  17 
  18 #include <asm/system.h>
  19 #include <asm/segment.h>
  20 
  21 extern void die_if_kernel(char *,struct pt_regs *,long);
  22 
  23 /*
  24  * This routine handles page faults.  It determines the address,
  25  * and the problem, and then passes it off to one of the appropriate
  26  * routines.
  27  */
  28 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
     /* [previous][next][first][last][top][bottom][index][help] */
  29 {
  30         struct vm_area_struct * vma;
  31         unsigned long address;
  32         unsigned long page;
  33 
  34         /* get the address */
  35         __asm__("movl %%cr2,%0":"=r" (address));
  36         for (vma = current->mm->mmap ; ; vma = vma->vm_next) {
  37                 if (!vma)
  38                         goto bad_area;
  39                 if (vma->vm_end > address)
  40                         break;
  41         }
  42         if (vma->vm_start <= address)
  43                 goto good_area;
  44         if (!(vma->vm_flags & VM_GROWSDOWN))
  45                 goto bad_area;
  46         if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
  47                 goto bad_area;
  48         vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
  49         vma->vm_start = (address & PAGE_MASK);
  50 /*
  51  * Ok, we have a good vm_area for this memory access, so
  52  * we can handle it..
  53  */
  54 good_area:
  55         if (regs->eflags & VM_MASK) {
  56                 unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
  57                 if (bit < 32)
  58                         current->tss.screen_bitmap |= 1 << bit;
  59         }
  60         if (!(vma->vm_page_prot & PAGE_USER))
  61                 goto bad_area;
  62         if (error_code & PAGE_PRESENT) {
  63                 if (!(vma->vm_page_prot & (PAGE_RW | PAGE_COW)))
  64                         goto bad_area;
  65 #ifdef CONFIG_TEST_VERIFY_AREA
  66                 if (regs->cs == KERNEL_CS)
  67                         printk("WP fault at %08x\n", regs->eip);
  68 #endif
  69                 do_wp_page(vma, address, error_code & PAGE_RW);
  70                 return;
  71         }
  72         do_no_page(vma, address, error_code & PAGE_RW);
  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         if (error_code & PAGE_USER) {
  81                 current->tss.cr2 = address;
  82                 current->tss.error_code = error_code;
  83                 current->tss.trap_no = 14;
  84                 send_sig(SIGSEGV, current, 1);
  85                 return;
  86         }
  87 /*
  88  * Oops. The kernel tried to access some bad page. We'll have to
  89  * terminate things with extreme prejudice.
  90  */
  91         if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & PAGE_PRESENT)) {
  92                 wp_works_ok = 1;
  93                 pg0[0] = PAGE_SHARED;
  94                 invalidate();
  95                 printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
  96                 return;
  97         }
  98         if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
  99                 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 100                 pg0[0] = PAGE_SHARED;
 101         } else
 102                 printk(KERN_ALERT "Unable to handle kernel paging request");
 103         printk(" at virtual address %08lx\n",address);
 104         __asm__("movl %%cr3,%0" : "=r" (page));
 105         printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n",
 106                 current->tss.cr3, page);
 107         page = ((unsigned long *) page)[address >> 22];
 108         printk(KERN_ALERT "*pde = %08lx\n", page);
 109         if (page & PAGE_PRESENT) {
 110                 page &= PAGE_MASK;
 111                 address &= 0x003ff000;
 112                 page = ((unsigned long *) page)[address >> PAGE_SHIFT];
 113                 printk(KERN_ALERT "*pte = %08lx\n", page);
 114         }
 115         die_if_kernel("Oops", regs, error_code);
 116         do_exit(SIGKILL);
 117 }

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