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