diff options
-rw-r--r-- | arch/cris/mm/fault.c | 169 |
1 files changed, 28 insertions, 141 deletions
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index 3034f3ff950c..c4c76db90f9c 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c | |||
@@ -1,130 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/cris/mm/fault.c | 2 | * linux/arch/cris/mm/fault.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000, 2001 Axis Communications AB | 4 | * Copyright (C) 2000-2006 Axis Communications AB |
5 | * | ||
6 | * Authors: Bjorn Wesen | ||
7 | * | ||
8 | * $Log: fault.c,v $ | ||
9 | * Revision 1.20 2005/03/04 08:16:18 starvik | ||
10 | * Merge of Linux 2.6.11. | ||
11 | * | ||
12 | * Revision 1.19 2005/01/14 10:07:59 starvik | ||
13 | * Fixed warning. | ||
14 | * | ||
15 | * Revision 1.18 2005/01/12 08:10:14 starvik | ||
16 | * Re-added the change of frametype when handling kernel page fault fixup | ||
17 | * for v10. This is necessary to avoid that the CPU remakes the faulting | ||
18 | * access. | ||
19 | * | ||
20 | * Revision 1.17 2005/01/11 13:53:05 starvik | ||
21 | * Use raw_printk. | ||
22 | * | ||
23 | * Revision 1.16 2004/12/17 11:39:41 starvik | ||
24 | * SMP support. | ||
25 | * | ||
26 | * Revision 1.15 2004/11/23 18:36:18 starvik | ||
27 | * Stack is now non-executable. | ||
28 | * Signal handler trampolines are placed in a reserved page mapped into all | ||
29 | * processes. | ||
30 | * | ||
31 | * Revision 1.14 2004/11/23 07:10:21 starvik | ||
32 | * Moved find_fixup_code to generic code. | ||
33 | * | ||
34 | * Revision 1.13 2004/11/23 07:00:54 starvik | ||
35 | * Actually use the execute permission bit in the MMU. This makes it possible | ||
36 | * to prevent e.g. attacks where executable code is put on the stack. | ||
37 | * | ||
38 | * Revision 1.12 2004/09/29 06:16:04 starvik | ||
39 | * Use instruction_pointer | ||
40 | * | ||
41 | * Revision 1.11 2004/05/14 07:58:05 starvik | ||
42 | * Merge of changes from 2.4 | ||
43 | * | ||
44 | * Revision 1.10 2003/10/27 14:51:24 starvik | ||
45 | * Removed debugcode | ||
46 | * | ||
47 | * Revision 1.9 2003/10/27 14:50:42 starvik | ||
48 | * Changed do_page_fault signature | ||
49 | * | ||
50 | * Revision 1.8 2003/07/04 13:02:48 tobiasa | ||
51 | * Moved code snippet from arch/cris/mm/fault.c that searches for fixup code | ||
52 | * to separate function in arch-specific files. | ||
53 | * | ||
54 | * Revision 1.7 2003/01/22 06:48:38 starvik | ||
55 | * Fixed warnings issued by GCC 3.2.1 | ||
56 | * | ||
57 | * Revision 1.6 2003/01/09 14:42:52 starvik | ||
58 | * Merge of Linux 2.5.55 | ||
59 | * | ||
60 | * Revision 1.5 2002/12/11 14:44:48 starvik | ||
61 | * Extracted v10 (ETRAX 100LX) specific stuff to arch/cris/arch-v10/mm | ||
62 | * | ||
63 | * Revision 1.4 2002/11/13 15:10:28 starvik | ||
64 | * pte_offset has been renamed to pte_offset_kernel | ||
65 | * | ||
66 | * Revision 1.3 2002/11/05 06:45:13 starvik | ||
67 | * Merge of Linux 2.5.45 | ||
68 | * | ||
69 | * Revision 1.2 2001/12/18 13:35:22 bjornw | ||
70 | * Applied the 2.4.13->2.4.16 CRIS patch to 2.5.1 (is a copy of 2.4.15). | ||
71 | * | ||
72 | * Revision 1.20 2001/11/22 13:34:06 bjornw | ||
73 | * * Bug workaround (LX TR89): force a rerun of the whole of an interrupted | ||
74 | * unaligned write, because the second half of the write will be corrupted | ||
75 | * otherwise. Affected unaligned writes spanning not-yet mapped pages. | ||
76 | * * Optimization: use the wr_rd bit in R_MMU_CAUSE to know whether a miss | ||
77 | * was due to a read or a write (before we didn't know this until the next | ||
78 | * restart of the interrupted instruction, thus wasting one fault-irq) | ||
79 | * | ||
80 | * Revision 1.19 2001/11/12 19:02:10 pkj | ||
81 | * Fixed compiler warnings. | ||
82 | * | ||
83 | * Revision 1.18 2001/07/18 22:14:32 bjornw | ||
84 | * Enable interrupts in the bulk of do_page_fault | ||
85 | * | ||
86 | * Revision 1.17 2001/07/18 13:07:23 bjornw | ||
87 | * * Detect non-existant PTE's in vmalloc pmd synchronization | ||
88 | * * Remove comment about fast-paths for VMALLOC_START etc, because all that | ||
89 | * was totally bogus anyway it turned out :) | ||
90 | * * Fix detection of vmalloc-area synchronization | ||
91 | * * Add some comments | ||
92 | * | ||
93 | * Revision 1.16 2001/06/13 00:06:08 bjornw | ||
94 | * current_pgd should be volatile | ||
95 | * | ||
96 | * Revision 1.15 2001/06/13 00:02:23 bjornw | ||
97 | * Use a separate variable to store the current pgd to avoid races in schedule | ||
98 | * | ||
99 | * Revision 1.14 2001/05/16 17:41:07 hp | ||
100 | * Last comment tweak further tweaked. | ||
101 | * | ||
102 | * Revision 1.13 2001/05/15 00:58:44 hp | ||
103 | * Expand a bit on the comment why we compare address >= TASK_SIZE rather | ||
104 | * than >= VMALLOC_START. | ||
105 | * | ||
106 | * Revision 1.12 2001/04/04 10:51:14 bjornw | ||
107 | * mmap_sem is grabbed for reading | ||
108 | * | ||
109 | * Revision 1.11 2001/03/23 07:36:07 starvik | ||
110 | * Corrected according to review remarks | ||
111 | * | ||
112 | * Revision 1.10 2001/03/21 16:10:11 bjornw | ||
113 | * CRIS_FRAME_FIXUP not needed anymore, use FRAME_NORMAL | ||
114 | * | ||
115 | * Revision 1.9 2001/03/05 13:22:20 bjornw | ||
116 | * Spell-fix and fix in vmalloc_fault handling | ||
117 | * | ||
118 | * Revision 1.8 2000/11/22 14:45:31 bjornw | ||
119 | * * 2.4.0-test10 removed the set_pgdir instantaneous kernel global mapping | ||
120 | * into all processes. Instead we fill in the missing PTE entries on demand. | ||
121 | * | ||
122 | * Revision 1.7 2000/11/21 16:39:09 bjornw | ||
123 | * fixup switches frametype | ||
124 | * | ||
125 | * Revision 1.6 2000/11/17 16:54:08 bjornw | ||
126 | * More detailed siginfo reporting | ||
127 | * | 5 | * |
6 | * Authors: Bjorn Wesen | ||
128 | * | 7 | * |
129 | */ | 8 | */ |
130 | 9 | ||
@@ -135,7 +14,6 @@ | |||
135 | 14 | ||
136 | extern int find_fixup_code(struct pt_regs *); | 15 | extern int find_fixup_code(struct pt_regs *); |
137 | extern void die_if_kernel(const char *, struct pt_regs *, long); | 16 | extern void die_if_kernel(const char *, struct pt_regs *, long); |
138 | extern int raw_printk(const char *fmt, ...); | ||
139 | 17 | ||
140 | /* debug of low-level TLB reload */ | 18 | /* debug of low-level TLB reload */ |
141 | #undef DEBUG | 19 | #undef DEBUG |
@@ -164,8 +42,8 @@ unsigned long cris_signal_return_page; | |||
164 | * address. | 42 | * address. |
165 | * | 43 | * |
166 | * error_code: | 44 | * error_code: |
167 | * bit 0 == 0 means no page found, 1 means protection fault | 45 | * bit 0 == 0 means no page found, 1 means protection fault |
168 | * bit 1 == 0 means read, 1 means write | 46 | * bit 1 == 0 means read, 1 means write |
169 | * | 47 | * |
170 | * If this routine detects a bad access, it returns 1, otherwise it | 48 | * If this routine detects a bad access, it returns 1, otherwise it |
171 | * returns 0. | 49 | * returns 0. |
@@ -181,9 +59,10 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
181 | siginfo_t info; | 59 | siginfo_t info; |
182 | int fault; | 60 | int fault; |
183 | 61 | ||
184 | D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n", | 62 | D(printk(KERN_DEBUG |
185 | address, smp_processor_id(), instruction_pointer(regs), | 63 | "Page fault for %lX on %X at %lX, prot %d write %d\n", |
186 | protection, writeaccess)); | 64 | address, smp_processor_id(), instruction_pointer(regs), |
65 | protection, writeaccess)); | ||
187 | 66 | ||
188 | tsk = current; | 67 | tsk = current; |
189 | 68 | ||
@@ -233,7 +112,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
233 | * context, we must not take the fault.. | 112 | * context, we must not take the fault.. |
234 | */ | 113 | */ |
235 | 114 | ||
236 | if (in_atomic() || !mm) | 115 | if (in_interrupt() || !mm) |
237 | goto no_context; | 116 | goto no_context; |
238 | 117 | ||
239 | down_read(&mm->mmap_sem); | 118 | down_read(&mm->mmap_sem); |
@@ -319,6 +198,9 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
319 | /* info.si_code has been set above */ | 198 | /* info.si_code has been set above */ |
320 | info.si_addr = (void *)address; | 199 | info.si_addr = (void *)address; |
321 | force_sig_info(SIGSEGV, &info, tsk); | 200 | force_sig_info(SIGSEGV, &info, tsk); |
201 | printk(KERN_NOTICE "%s (pid %d) segfaults for page " | ||
202 | "address %08lx at pc %08lx\n", | ||
203 | tsk->comm, tsk->pid, address, instruction_pointer(regs)); | ||
322 | return; | 204 | return; |
323 | } | 205 | } |
324 | 206 | ||
@@ -326,7 +208,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
326 | 208 | ||
327 | /* Are we prepared to handle this kernel fault? | 209 | /* Are we prepared to handle this kernel fault? |
328 | * | 210 | * |
329 | * (The kernel has valid exception-points in the source | 211 | * (The kernel has valid exception-points in the source |
330 | * when it acesses user-memory. When it fails in one | 212 | * when it acesses user-memory. When it fails in one |
331 | * of those points, we find it in a table and do a jump | 213 | * of those points, we find it in a table and do a jump |
332 | * to some fixup code that loads an appropriate error | 214 | * to some fixup code that loads an appropriate error |
@@ -341,13 +223,18 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
341 | * terminate things with extreme prejudice. | 223 | * terminate things with extreme prejudice. |
342 | */ | 224 | */ |
343 | 225 | ||
344 | if ((unsigned long) (address) < PAGE_SIZE) | 226 | if (!oops_in_progress) { |
345 | raw_printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); | 227 | oops_in_progress = 1; |
346 | else | 228 | if ((unsigned long) (address) < PAGE_SIZE) |
347 | raw_printk(KERN_ALERT "Unable to handle kernel access"); | 229 | printk(KERN_ALERT "Unable to handle kernel NULL " |
348 | raw_printk(" at virtual address %08lx\n",address); | 230 | "pointer dereference"); |
349 | 231 | else | |
350 | die_if_kernel("Oops", regs, (writeaccess << 1) | protection); | 232 | printk(KERN_ALERT "Unable to handle kernel access" |
233 | " at virtual address %08lx\n", address); | ||
234 | |||
235 | die_if_kernel("Oops", regs, (writeaccess << 1) | protection); | ||
236 | oops_in_progress = 0; | ||
237 | } | ||
351 | 238 | ||
352 | do_exit(SIGKILL); | 239 | do_exit(SIGKILL); |
353 | 240 | ||
@@ -360,7 +247,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
360 | up_read(&mm->mmap_sem); | 247 | up_read(&mm->mmap_sem); |
361 | printk("VM: killing process %s\n", tsk->comm); | 248 | printk("VM: killing process %s\n", tsk->comm); |
362 | if (user_mode(regs)) | 249 | if (user_mode(regs)) |
363 | do_group_exit(SIGKILL); | 250 | do_exit(SIGKILL); |
364 | goto no_context; | 251 | goto no_context; |
365 | 252 | ||
366 | do_sigbus: | 253 | do_sigbus: |
@@ -406,8 +293,8 @@ vmalloc_fault: | |||
406 | /* Since we're two-level, we don't need to do both | 293 | /* Since we're two-level, we don't need to do both |
407 | * set_pgd and set_pmd (they do the same thing). If | 294 | * set_pgd and set_pmd (they do the same thing). If |
408 | * we go three-level at some point, do the right thing | 295 | * we go three-level at some point, do the right thing |
409 | * with pgd_present and set_pgd here. | 296 | * with pgd_present and set_pgd here. |
410 | * | 297 | * |
411 | * Also, since the vmalloc area is global, we don't | 298 | * Also, since the vmalloc area is global, we don't |
412 | * need to copy individual PTE's, it is enough to | 299 | * need to copy individual PTE's, it is enough to |
413 | * copy the pgd pointer into the pte page of the | 300 | * copy the pgd pointer into the pte page of the |