OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [mm/] [fault-armo.c] - Blame information for rev 1765

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 *  linux/arch/arm/mm/fault.c
3
 *
4
 *  Copyright (C) 1995  Linus Torvalds
5
 *  Modifications for ARM processor (c) 1995, 1996 Russell King
6
 */
7
 
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
#include <linux/mm.h>
18
 
19
#include <asm/system.h>
20
#include <asm/segment.h>
21
#include <asm/pgtable.h>
22
 
23
#define FAULT_CODE_FORCECOW     0x80
24
#define FAULT_CODE_PREFETCH     0x04
25
#define FAULT_CODE_WRITE        0x02
26
#define FAULT_CODE_USER         0x01
27
 
28
extern void die_if_kernel(char *, struct pt_regs *, long, int, int);
29
 
30
static void
31
handle_dataabort (unsigned long addr, int mode, struct pt_regs *regs)
32
{
33
    struct task_struct *tsk = current;
34
    struct mm_struct *mm = tsk->mm;
35
    struct vm_area_struct *vma;
36
 
37
    down(&mm->mmap_sem);
38
    vma = find_vma (mm, addr);
39
    if (!vma)
40
        goto bad_area;
41
    if (addr >= vma->vm_start)
42
        goto good_area;
43
    if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr))
44
        goto bad_area;
45
 
46
    /*
47
     * Ok, we have a good vm_area for this memory access, so
48
     * we can handle it..
49
     */
50
good_area:
51
    if (mode & FAULT_CODE_WRITE) { /* write? */
52
        if (!(vma->vm_flags & VM_WRITE))
53
            goto bad_area;
54
    } else {
55
        if (!(vma->vm_flags & (VM_READ|VM_EXEC)))
56
            goto bad_area;
57
    }
58
    /*
59
     * Dirty hack for now...  Should solve the problem with ldm though!
60
     */
61
    handle_mm_fault (vma, addr, mode & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW));
62
    up(&mm->mmap_sem);
63
    return;
64
 
65
    /*
66
     * Something tried to access memory that isn't in our memory map..
67
     * Fix it, but check if it's kernel or user first..
68
     */
69
bad_area:
70
    up(&mm->mmap_sem);
71
    if (mode & FAULT_CODE_USER) {
72
        tsk->tss.error_code = mode;
73
        tsk->tss.trap_no = 14;
74
        printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
75
                tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
76
        force_sig(SIGSEGV, tsk);
77
        return;
78
    } else {
79
        /*
80
         * Oops. The kernel tried to access some bad page. We'll have to
81
         * terminate things with extreme prejudice.
82
         */
83
        pgd_t *pgd;
84
        pmd_t *pmd;
85
        if (addr < PAGE_SIZE)
86
            printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
87
        else
88
            printk (KERN_ALERT "Unable to handle kernel paging request");
89
        printk (" at virtual address %08lx\n", addr);
90
        printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap);
91
        pgd = pgd_offset (vma->vm_mm, addr);
92
        printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd));
93
        if (!pgd_none (*pgd)) {
94
            pmd = pmd_offset (pgd, addr);
95
            printk (", *pmd = %08lx", pmd_val (*pmd));
96
            if (!pmd_none (*pmd))
97
                printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
98
        }
99
        printk ("\n");
100
        die_if_kernel ("Oops", regs, mode, 0, SIGKILL);
101
        do_exit (SIGKILL);
102
    }
103
}
104
 
105
/*
106
 * Handle a data abort.  Note that we have to handle a range of addresses
107
 * on ARM2/3 for ldm.  If both pages are zero-mapped, then we have to force
108
 * a copy-on-write
109
 */
110
asmlinkage void
111
do_DataAbort (unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs)
112
{
113
    handle_dataabort (min_addr, mode, regs);
114
 
115
    if ((min_addr ^ max_addr) >> PAGE_SHIFT)
116
        handle_dataabort (max_addr, mode | FAULT_CODE_FORCECOW, regs);
117
}
118
 
119
asmlinkage int
120
do_PrefetchAbort (unsigned long addr, int mode, struct pt_regs *regs)
121
{
122
#if 0
123
    if (the memc mapping for this page exists - can check now...) {
124
        printk ("Page in, but got abort (undefined instruction?)\n");
125
        return 0;
126
    }
127
#endif
128
    handle_dataabort (addr, mode, regs);
129
    return 1;
130
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.