linux-old/arch/arm/mm/fault-common.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/arm/mm/fault-common.c
   3 *
   4 *  Copyright (C) 1995  Linus Torvalds
   5 *  Modifications for ARM processor (c) 1995-2001 Russell King
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11#include <linux/config.h>
  12#include <linux/signal.h>
  13#include <linux/sched.h>
  14#include <linux/kernel.h>
  15#include <linux/errno.h>
  16#include <linux/string.h>
  17#include <linux/types.h>
  18#include <linux/ptrace.h>
  19#include <linux/mman.h>
  20#include <linux/mm.h>
  21#include <linux/interrupt.h>
  22#include <linux/proc_fs.h>
  23#include <linux/init.h>
  24
  25#include <asm/system.h>
  26#include <asm/uaccess.h>
  27#include <asm/pgtable.h>
  28#include <asm/unaligned.h>
  29
  30#ifdef CONFIG_CPU_26
  31#define FAULT_CODE_WRITE        0x02
  32#define FAULT_CODE_FORCECOW     0x01
  33#define DO_COW(m)               ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
  34#define READ_FAULT(m)           (!((m) & FAULT_CODE_WRITE))
  35#else
  36/*
  37 * On 32-bit processors, we define "mode" to be zero when reading,
  38 * non-zero when writing.  This now ties up nicely with the polarity
  39 * of the 26-bit machines, and also means that we avoid the horrible
  40 * gcc code for "int val = !other_val;".
  41 */
  42#define DO_COW(m)               (m)
  43#define READ_FAULT(m)           (!(m))
  44#endif
  45
  46NORET_TYPE void die(const char *msg, struct pt_regs *regs, int err) ATTRIB_NORET;
  47
  48/*
  49 * This is useful to dump out the page tables associated with
  50 * 'addr' in mm 'mm'.
  51 */
  52void show_pte(struct mm_struct *mm, unsigned long addr)
  53{
  54        pgd_t *pgd;
  55
  56        if (!mm)
  57                mm = &init_mm;
  58
  59        printk(KERN_ALERT "pgd = %p\n", mm->pgd);
  60        pgd = pgd_offset(mm, addr);
  61        printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd));
  62
  63        do {
  64                pmd_t *pmd;
  65                pte_t *pte;
  66
  67                if (pgd_none(*pgd))
  68                        break;
  69
  70                if (pgd_bad(*pgd)) {
  71                        printk("(bad)");
  72                        break;
  73                }
  74
  75                pmd = pmd_offset(pgd, addr);
  76                printk(", *pmd = %08lx", pmd_val(*pmd));
  77
  78                if (pmd_none(*pmd))
  79                        break;
  80
  81                if (pmd_bad(*pmd)) {
  82                        printk("(bad)");
  83                        break;
  84                }
  85
  86                pte = pte_offset(pmd, addr);
  87                printk(", *pte = %08lx", pte_val(*pte));
  88#ifdef CONFIG_CPU_32
  89                printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
  90#endif
  91        } while(0);
  92
  93        printk("\n");
  94}
  95
  96/*
  97 * Oops.  The kernel tried to access some page that wasn't present.
  98 */
  99static void
 100__do_kernel_fault(struct mm_struct *mm, unsigned long addr, int error_code,
 101                  struct pt_regs *regs)
 102{
 103        unsigned long fixup;
 104
 105        /*
 106         * Are we prepared to handle this kernel fault?
 107         */
 108        if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
 109#ifdef DEBUG
 110                printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
 111                        current->comm, regs->ARM_pc, addr, fixup);
 112#endif
 113                regs->ARM_pc = fixup;
 114                return;
 115        }
 116
 117        /*
 118         * No handler, we'll have to terminate things with extreme prejudice.
 119         */
 120        printk(KERN_ALERT
 121                "Unable to handle kernel %s at virtual address %08lx\n",
 122                (addr < PAGE_SIZE) ? "NULL pointer dereference" :
 123                "paging request", addr);
 124
 125        show_pte(mm, addr);
 126        die("Oops", regs, error_code);
 127        do_exit(SIGKILL);
 128}
 129
 130/*
 131 * Something tried to access memory that isn't in our memory map..
 132 * User mode accesses just cause a SIGSEGV
 133 */
 134static void
 135__do_user_fault(struct task_struct *tsk, unsigned long addr, int error_code,
 136                int code, struct pt_regs *regs)
 137{
 138        struct siginfo si;
 139
 140#ifdef CONFIG_DEBUG_USER
 141        printk(KERN_DEBUG "%s: unhandled page fault at pc=0x%08lx, "
 142               "lr=0x%08lx (bad address=0x%08lx, code %d)\n",
 143               tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, error_code);
 144#endif
 145
 146        tsk->thread.address = addr;
 147        tsk->thread.error_code = error_code;
 148        tsk->thread.trap_no = 14;
 149        si.si_signo = SIGSEGV;
 150        si.si_errno = 0;
 151        si.si_code = code;
 152        si.si_addr = (void *)addr;
 153        force_sig_info(SIGSEGV, &si, tsk);
 154}
 155
 156void
 157do_bad_area(struct task_struct *tsk, struct mm_struct *mm, unsigned long addr,
 158            int error_code, struct pt_regs *regs)
 159{
 160        /*
 161         * If we are in kernel mode at this point, we
 162         * have no context to handle this fault with.
 163         */
 164        if (user_mode(regs))
 165                __do_user_fault(tsk, addr, error_code, SEGV_MAPERR, regs);
 166        else
 167                __do_kernel_fault(mm, addr, error_code, regs);
 168}
 169
 170static int
 171__do_page_fault(struct mm_struct *mm, unsigned long addr, int error_code,
 172                struct task_struct *tsk)
 173{
 174        struct vm_area_struct *vma;
 175        int fault, mask;
 176
 177        vma = find_vma(mm, addr);
 178        fault = -2; /* bad map area */
 179        if (!vma)
 180                goto out;
 181        if (vma->vm_start > addr)
 182                goto check_stack;
 183
 184        /*
 185         * Ok, we have a good vm_area for this
 186         * memory access, so we can handle it.
 187         */
 188good_area:
 189        if (READ_FAULT(error_code)) /* read? */
 190                mask = VM_READ|VM_EXEC;
 191        else
 192                mask = VM_WRITE;
 193
 194        fault = -1; /* bad access type */
 195        if (!(vma->vm_flags & mask))
 196                goto out;
 197
 198        /*
 199         * If for any reason at all we couldn't handle
 200         * the fault, make sure we exit gracefully rather
 201         * than endlessly redo the fault.
 202         */
 203survive:
 204        fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(error_code));
 205
 206        /*
 207         * Handle the "normal" cases first - successful and sigbus
 208         */
 209        switch (fault) {
 210        case 2:
 211                tsk->maj_flt++;
 212                return fault;
 213        case 1:
 214                tsk->min_flt++;
 215        case 0:
 216                return fault;
 217        }
 218
 219        fault = -3; /* out of memory */
 220        if (tsk->pid != 1)
 221                goto out;
 222
 223        /*
 224         * If we are out of memory for pid1,
 225         * sleep for a while and retry
 226         */
 227        tsk->policy |= SCHED_YIELD;
 228        schedule();
 229        goto survive;
 230
 231check_stack:
 232        if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
 233                goto good_area;
 234out:
 235        return fault;
 236}
 237
 238int do_page_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 239{
 240        struct task_struct *tsk;
 241        struct mm_struct *mm;
 242        int fault;
 243
 244        tsk = current;
 245        mm  = tsk->mm;
 246
 247        /*
 248         * If we're in an interrupt or have no user
 249         * context, we must not take the fault..
 250         */
 251        if (in_interrupt() || !mm)
 252                goto no_context;
 253
 254        down_read(&mm->mmap_sem);
 255        fault = __do_page_fault(mm, addr, error_code, tsk);
 256        up_read(&mm->mmap_sem);
 257
 258        /*
 259         * Handle the "normal" case first
 260         */
 261        if (fault > 0)
 262                return 0;
 263
 264        /*
 265         * We had some memory, but were unable to
 266         * successfully fix up this page fault.
 267         */
 268        if (fault == 0)
 269                goto do_sigbus;
 270
 271        /*
 272         * If we are in kernel mode at this point, we
 273         * have no context to handle this fault with.
 274         */
 275        if (!user_mode(regs))
 276                goto no_context;
 277
 278        if (fault == -3) {
 279                /*
 280                 * We ran out of memory, or some other thing happened to
 281                 * us that made us unable to handle the page fault gracefully.
 282                 */
 283                printk("VM: killing process %s\n", tsk->comm);
 284                do_exit(SIGKILL);
 285        } else
 286                __do_user_fault(tsk, addr, error_code, fault == -1 ?
 287                                SEGV_ACCERR : SEGV_MAPERR, regs);
 288        return 0;
 289
 290
 291/*
 292 * We ran out of memory, or some other thing happened to us that made
 293 * us unable to handle the page fault gracefully.
 294 */
 295do_sigbus:
 296        /*
 297         * Send a sigbus, regardless of whether we were in kernel
 298         * or user mode.
 299         */
 300        tsk->thread.address = addr;
 301        tsk->thread.error_code = error_code;
 302        tsk->thread.trap_no = 14;
 303        force_sig(SIGBUS, tsk);
 304#ifdef CONFIG_DEBUG_USER
 305        printk(KERN_DEBUG "%s: sigbus at 0x%08lx, pc=0x%08lx\n",
 306                current->comm, addr, instruction_pointer(regs));
 307#endif
 308
 309        /* Kernel mode? Handle exceptions or die */
 310        if (user_mode(regs))
 311                return 0;
 312
 313no_context:
 314        __do_kernel_fault(mm, addr, error_code, regs);
 315        return 0;
 316}
 317
 318/*
 319 * First Level Translation Fault Handler
 320 *
 321 * We enter here because the first level page table doesn't contain
 322 * a valid entry for the address.
 323 *
 324 * If the address is in kernel space (>= TASK_SIZE), then we are
 325 * probably faulting in the vmalloc() area.
 326 *
 327 * If the init_task's first level page tables contains the relevant
 328 * entry, we copy the it to this task.  If not, we send the process
 329 * a signal, fixup the exception, or oops the kernel.
 330 *
 331 * NOTE! We MUST NOT take any locks for this case. We may be in an
 332 * interrupt or a critical region, and should only copy the information
 333 * from the master page table, nothing more.
 334 */
 335int do_translation_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 336{
 337        struct task_struct *tsk;
 338        struct mm_struct *mm;
 339        int offset;
 340        pgd_t *pgd, *pgd_k;
 341        pmd_t *pmd, *pmd_k;
 342
 343        if (addr < TASK_SIZE)
 344                return do_page_fault(addr, error_code, regs);
 345
 346        offset = __pgd_offset(addr);
 347
 348        pgd = cpu_get_pgd() + offset;
 349        pgd_k = init_mm.pgd + offset;
 350
 351        if (pgd_none(*pgd_k))
 352                goto bad_area;
 353
 354#if 0   /* note that we are two-level */
 355        if (!pgd_present(*pgd))
 356                set_pgd(pgd, *pgd_k);
 357#endif
 358
 359        pmd_k = pmd_offset(pgd_k, addr);
 360        pmd   = pmd_offset(pgd, addr);
 361
 362        if (pmd_none(*pmd_k))
 363                goto bad_area;
 364
 365        set_pmd(pmd, *pmd_k);
 366        return 0;
 367
 368bad_area:
 369        tsk = current;
 370        mm  = tsk->active_mm;
 371
 372        do_bad_area(tsk, mm, addr, error_code, regs);
 373        return 0;
 374}
 375
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.