linux/arch/m68k/mm/fault.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/m68k/mm/fault.c
   3 *
   4 *  Copyright (C) 1995  Hamish Macdonald
   5 */
   6
   7#include <linux/mman.h>
   8#include <linux/mm.h>
   9#include <linux/kernel.h>
  10#include <linux/ptrace.h>
  11#include <linux/interrupt.h>
  12#include <linux/module.h>
  13
  14#include <asm/setup.h>
  15#include <asm/traps.h>
  16#include <asm/system.h>
  17#include <asm/uaccess.h>
  18#include <asm/pgalloc.h>
  19
  20extern void die_if_kernel(char *, struct pt_regs *, long);
  21
  22int send_fault_sig(struct pt_regs *regs)
  23{
  24        siginfo_t siginfo = { 0, 0, 0, };
  25
  26        siginfo.si_signo = current->thread.signo;
  27        siginfo.si_code = current->thread.code;
  28        siginfo.si_addr = (void *)current->thread.faddr;
  29#ifdef DEBUG
  30        printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code);
  31#endif
  32
  33        if (user_mode(regs)) {
  34                force_sig_info(siginfo.si_signo,
  35                               &siginfo, current);
  36        } else {
  37                if (handle_kernel_fault(regs))
  38                        return -1;
  39
  40                //if (siginfo.si_signo == SIGBUS)
  41                //      force_sig_info(siginfo.si_signo,
  42                //                     &siginfo, current);
  43
  44                /*
  45                 * Oops. The kernel tried to access some bad page. We'll have to
  46                 * terminate things with extreme prejudice.
  47                 */
  48                if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
  49                        printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
  50                else
  51                        printk(KERN_ALERT "Unable to handle kernel access");
  52                printk(" at virtual address %p\n", siginfo.si_addr);
  53                die_if_kernel("Oops", regs, 0 /*error_code*/);
  54                do_exit(SIGKILL);
  55        }
  56
  57        return 1;
  58}
  59
  60/*
  61 * This routine handles page faults.  It determines the problem, and
  62 * then passes it off to one of the appropriate routines.
  63 *
  64 * error_code:
  65 *      bit 0 == 0 means no page found, 1 means protection fault
  66 *      bit 1 == 0 means read, 1 means write
  67 *
  68 * If this routine detects a bad access, it returns 1, otherwise it
  69 * returns 0.
  70 */
  71int do_page_fault(struct pt_regs *regs, unsigned long address,
  72                              unsigned long error_code)
  73{
  74        struct mm_struct *mm = current->mm;
  75        struct vm_area_struct * vma;
  76        int write, fault;
  77
  78#ifdef DEBUG
  79        printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
  80                regs->sr, regs->pc, address, error_code,
  81                current->mm->pgd);
  82#endif
  83
  84        /*
  85         * If we're in an interrupt or have no user
  86         * context, we must not take the fault..
  87         */
  88        if (in_atomic() || !mm)
  89                goto no_context;
  90
  91        down_read(&mm->mmap_sem);
  92
  93        vma = find_vma(mm, address);
  94        if (!vma)
  95                goto map_err;
  96        if (vma->vm_flags & VM_IO)
  97                goto acc_err;
  98        if (vma->vm_start <= address)
  99                goto good_area;
 100        if (!(vma->vm_flags & VM_GROWSDOWN))
 101                goto map_err;
 102        if (user_mode(regs)) {
 103                /* Accessing the stack below usp is always a bug.  The
 104                   "+ 256" is there due to some instructions doing
 105                   pre-decrement on the stack and that doesn't show up
 106                   until later.  */
 107                if (address + 256 < rdusp())
 108                        goto map_err;
 109        }
 110        if (expand_stack(vma, address))
 111                goto map_err;
 112
 113/*
 114 * Ok, we have a good vm_area for this memory access, so
 115 * we can handle it..
 116 */
 117good_area:
 118#ifdef DEBUG
 119        printk("do_page_fault: good_area\n");
 120#endif
 121        write = 0;
 122        switch (error_code & 3) {
 123                default:        /* 3: write, present */
 124                        /* fall through */
 125                case 2:         /* write, not present */
 126                        if (!(vma->vm_flags & VM_WRITE))
 127                                goto acc_err;
 128                        write++;
 129                        break;
 130                case 1:         /* read, present */
 131                        goto acc_err;
 132                case 0:         /* read, not present */
 133                        if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
 134                                goto acc_err;
 135        }
 136
 137        /*
 138         * If for any reason at all we couldn't handle the fault,
 139         * make sure we exit gracefully rather than endlessly redo
 140         * the fault.
 141         */
 142
 143        fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
 144#ifdef DEBUG
 145        printk("handle_mm_fault returns %d\n",fault);
 146#endif
 147        if (unlikely(fault & VM_FAULT_ERROR)) {
 148                if (fault & VM_FAULT_OOM)
 149                        goto out_of_memory;
 150                else if (fault & VM_FAULT_SIGBUS)
 151                        goto bus_err;
 152                BUG();
 153        }
 154        if (fault & VM_FAULT_MAJOR)
 155                current->maj_flt++;
 156        else
 157                current->min_flt++;
 158
 159        up_read(&mm->mmap_sem);
 160        return 0;
 161
 162/*
 163 * We ran out of memory, or some other thing happened to us that made
 164 * us unable to handle the page fault gracefully.
 165 */
 166out_of_memory:
 167        up_read(&mm->mmap_sem);
 168        if (!user_mode(regs))
 169                goto no_context;
 170        pagefault_out_of_memory();
 171        return 0;
 172
 173no_context:
 174        current->thread.signo = SIGBUS;
 175        current->thread.faddr = address;
 176        return send_fault_sig(regs);
 177
 178bus_err:
 179        current->thread.signo = SIGBUS;
 180        current->thread.code = BUS_ADRERR;
 181        current->thread.faddr = address;
 182        goto send_sig;
 183
 184map_err:
 185        current->thread.signo = SIGSEGV;
 186        current->thread.code = SEGV_MAPERR;
 187        current->thread.faddr = address;
 188        goto send_sig;
 189
 190acc_err:
 191        current->thread.signo = SIGSEGV;
 192        current->thread.code = SEGV_ACCERR;
 193        current->thread.faddr = address;
 194
 195send_sig:
 196        up_read(&mm->mmap_sem);
 197        return send_fault_sig(regs);
 198}
 199