* better
[mascara-docs.git] / i386 / linux-2.3.21 / arch / arm / mm / fault-common.c
bloba536515af7e632d95269512a8017c041c53ebb7d
1 /*
2 * linux/arch/arm/mm/fault-common.c
4 * Copyright (C) 1995 Linus Torvalds
5 * Modifications for ARM processor (c) 1995-1999 Russell King
6 */
7 #include <linux/config.h>
9 extern void die(char *msg, struct pt_regs *regs, unsigned int err);
11 void __bad_pmd(pmd_t *pmd)
13 printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
14 #ifdef CONFIG_DEBUG_ERRORS
15 __backtrace();
16 #endif
17 set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
20 void __bad_pmd_kernel(pmd_t *pmd)
22 printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
23 #ifdef CONFIG_DEBUG_ERRORS
24 __backtrace();
25 #endif
26 set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
30 * This is useful to dump out the page tables associated with
31 * 'addr' in mm 'mm'.
33 void show_pte(struct mm_struct *mm, unsigned long addr)
35 pgd_t *pgd;
37 pgd = pgd_offset(mm, addr);
38 printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd));
40 do {
41 pmd_t *pmd;
42 pte_t *pte;
44 if (pgd_none(*pgd))
45 break;
47 if (pgd_bad(*pgd)) {
48 printk("(bad)\n");
49 break;
52 pmd = pmd_offset(pgd, addr);
53 printk(", *pmd = %08lx", pmd_val(*pmd));
55 if (pmd_none(*pmd))
56 break;
58 if (pmd_bad(*pmd)) {
59 printk("(bad)\n");
60 break;
63 pte = pte_offset(pmd, addr);
64 printk(", *pte = %08lx", pte_val(*pte));
65 printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
66 } while(0);
68 printk("\n");
72 * Oops. The kernel tried to access some bad page. We'll have to
73 * terminate things with extreme prejudice.
75 static void
76 kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs,
77 struct task_struct *tsk, struct mm_struct *mm)
79 char *reason;
81 if (addr < PAGE_SIZE)
82 reason = "NULL pointer dereference";
83 else
84 reason = "paging request";
86 printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n",
87 reason, addr);
88 if (!mm)
89 mm = &init_mm;
91 printk(KERN_ALERT "pgd = %p\n", mm->pgd);
92 show_pte(mm, addr);
93 die("Oops", regs, mode);
95 do_exit(SIGKILL);
98 static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
100 struct task_struct *tsk;
101 struct mm_struct *mm;
102 struct vm_area_struct *vma;
103 unsigned long fixup;
105 tsk = current;
106 mm = tsk->mm;
109 * If we're in an interrupt or have no user
110 * context, we must not take the fault..
112 if (in_interrupt() || !mm)
113 goto no_context;
115 down(&mm->mmap_sem);
116 vma = find_vma(mm, addr);
117 if (!vma)
118 goto bad_area;
119 if (vma->vm_start <= addr)
120 goto good_area;
121 if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, addr))
122 goto bad_area;
125 * Ok, we have a good vm_area for this memory access, so
126 * we can handle it..
128 good_area:
129 if (READ_FAULT(mode)) { /* read? */
130 if (!(vma->vm_flags & (VM_READ|VM_EXEC)))
131 goto bad_area;
132 } else {
133 if (!(vma->vm_flags & VM_WRITE))
134 goto bad_area;
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.
142 if (!handle_mm_fault(tsk, vma, addr & PAGE_MASK, DO_COW(mode)))
143 goto do_sigbus;
145 up(&mm->mmap_sem);
146 return;
149 * Something tried to access memory that isn't in our memory map..
150 * Fix it, but check if it's kernel or user first..
152 bad_area:
153 up(&mm->mmap_sem);
155 /* User mode accesses just cause a SIGSEGV */
156 if (mode & FAULT_CODE_USER) {
157 tsk->thread.error_code = mode;
158 tsk->thread.trap_no = 14;
159 #ifdef CONFIG_DEBUG_USER
160 printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
161 tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
162 #endif
163 force_sig(SIGSEGV, tsk);
164 return;
167 no_context:
168 /* Are we prepared to handle this kernel fault? */
169 if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
170 #ifdef DEBUG
171 printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
172 tsk->comm, regs->ARM_pc, addr, fixup);
173 #endif
174 regs->ARM_pc = fixup;
175 return;
178 kernel_page_fault(addr, mode, regs, tsk, mm);
179 return;
181 do_sigbus:
183 * We ran out of memory, or some other thing happened to us that made
184 * us unable to handle the page fault gracefully.
186 up(&mm->mmap_sem);
189 * Send a sigbus, regardless of whether we were in kernel
190 * or user mode.
192 tsk->thread.error_code = mode;
193 tsk->thread.trap_no = 14;
194 force_sig(SIGBUS, tsk);
196 /* Kernel mode? Handle exceptions or die */
197 if (!(mode & FAULT_CODE_USER))
198 goto no_context;