This source file includes following definitions.
- DataAccessException
- InstructionAccessException
- do_page_fault
- va_to_phys
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/config.h>
13 #include <linux/signal.h>
14 #include <linux/sched.h>
15 #include <linux/head.h>
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
19 #include <linux/types.h>
20 #include <linux/ptrace.h>
21 #include <linux/mman.h>
22 #include <linux/mm.h>
23
24 #include <asm/page.h>
25 #include <asm/pgtable.h>
26
27 extern void die_if_kernel(char *, struct pt_regs *, long);
28 extern void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
29
30 #if 0
31 #define SHOW_FAULTS
32 #endif
33
34 void
35 DataAccessException(struct pt_regs *regs)
36 {
37 pgd_t *dir;
38 pmd_t *pmd;
39 pte_t *pte;
40 int tries, mode = 0;
41 if (user_mode(regs)) mode |= 0x04;
42 if (regs->dsisr & 0x02000000) mode |= 0x02;
43 if (regs->dsisr & 0x08000000) mode |= 0x01;
44 #ifdef NOISY_DATAFAULT
45 printk("Data fault on %x\n",regs->dar);
46 #endif
47 if (mode & 0x01)
48 {
49 #if 0
50 printk("Write Protect Fault - Loc: %x, DSISR: %x, PC: %x\n", regs->dar, regs->dsisr, regs->nip);
51 #endif
52 #ifdef NOISY_DATAFAULT
53 printk("Write Protect fault\n ");
54 #endif
55 do_page_fault(regs, regs->dar, mode);
56 #ifdef NOISY_DATAFAULT
57 printk("Write Protect fault handled\n");
58 #endif
59 return;
60 }
61
62 for (tries = 0; tries < 1; tries++)
63 {
64 dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
65 if (dir)
66 {
67 pmd = pmd_offset(dir, regs->dar & PAGE_MASK);
68 if (pmd && pmd_present(*pmd))
69 {
70 pte = pte_offset(pmd, regs->dar & PAGE_MASK);
71 if (pte && pte_present(*pte))
72 {
73 #if 0
74 printk("Page mapped - PTE: %x[%x]\n", pte, *(long *)pte);
75 #endif
76 MMU_hash_page(¤t->tss, regs->dar & PAGE_MASK, pte);
77 return;
78 }
79 }
80 } else
81 {
82 printk("No PGD\n");
83 }
84 #ifdef NOISY_DATAFAULT
85 printk("fall through page fault addr=%x; ip=%x\n",
86 regs->dar,regs->nip);
87 printk("beforefault: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd));
88 #endif
89 do_page_fault(regs, regs->dar, mode);
90 #ifdef NOISY_DATAFAULT
91 printk("handled: pgd[0] = %x[%x]\n",current->mm->pgd,*(current->mm->pgd));
92 #endif
93 }
94 }
95
96 void
97 InstructionAccessException(struct pt_regs *regs)
98 {
99 pgd_t *dir;
100 pmd_t *pmd;
101 pte_t *pte;
102 int tries, mode = 0;
103
104 #if NOISY_INSTRFAULT
105 printk("Instr fault on %x\n",regs->dar);
106 #endif
107 if (user_mode(regs)) mode |= 0x04;
108 if (regs->dsisr & 0x02000000) mode |= 0x02;
109 if (regs->dsisr & 0x08000000) mode |= 0x01;
110
111 if (mode & 0x01)
112 {
113 do_page_fault(regs, regs->dar, mode);
114 return;
115 }
116 for (tries = 0; tries < 1; tries++)
117 {
118
119 dir = pgd_offset(current->mm, regs->dar & PAGE_MASK);
120 #ifdef NOISY_INSTRFAULT
121
122
123 #endif
124 if (dir)
125 {
126 pmd = pmd_offset(dir, regs->dar & PAGE_MASK);
127 if (pmd && pmd_present(*pmd))
128 {
129 pte = pte_offset(pmd, regs->dar & PAGE_MASK);
130
131 #ifdef NOISY_INSTRFAULT
132
133 #if 0
134 printk("pgd_offset mm=%x mm->pgd=%x dirshouldbe=%x\n",
135 current->mm, current->mm->pgd,
136 current->mm->pgd+((regs->dar&PAGE_MASK) >> PGDIR_SHIFT));
137 printk("dir is %x\n", dir);
138
139
140 if (pte) {
141 printk("pgd=%x; dir=%x->%x; pmd=%x->%x; pte=%x; \n",
142 current->mm->pgd,dir,*dir,pmd,*pmd,pte);
143 if (pte_present(*pte)) {
144 printk("pte present\n");
145 } else {
146 printk("pte not present\n");
147 }
148 } else {
149 printk("pte false\n");
150 }
151 #endif
152 #endif
153 if (pte && pte_present(*pte))
154 {
155
156 MMU_hash_page(¤t->tss, regs->dar & PAGE_MASK, pte);
157 return;
158 }
159 }
160 } else
161 {
162 #ifdef NOISY_INSTRFAULT
163 panic("No PGD Instruction Access Fault - Loc: %x, DSISR: %x, PC: %x current->mm\n",
164 regs->dar, regs->dsisr, regs->nip, current->mm);
165 #endif
166 }
167
168 do_page_fault(regs, regs->dar, mode);
169 }
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183 void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code)
184 {
185 struct vm_area_struct * vma;
186 unsigned long page;
187
188
189 #if 1
190 for (vma = current->mm->mmap ; ; vma = vma->vm_next)
191 {
192 if (!vma)
193 {
194 panic("!vma: ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",
195 regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
196 goto bad_area;
197 }
198 if (vma->vm_end > address)
199 break;
200 }
201 #else
202 vma = find_vma(current, address);
203 if (!vma)
204 {
205 }
206 goto bad_area;
207 #endif
208 if (vma->vm_start <= address){
209 goto good_area;
210 }
211 if (!(vma->vm_flags & VM_GROWSDOWN))
212 {
213 printk("stack: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
214 panic("stack\n");
215 goto bad_area;
216 }
217 if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
218 {
219 printk("stack2: vma->vm_end-address %x rlim %x\n", vma->vm_end - address,
220 current->rlim[RLIMIT_STACK].rlim_cur);
221 printk("stack2: vm_end %x address = %x\n", vma->vm_end,address);
222 printk("stack2: gpr[1]=%x ip = %x; current=%x[%d]; mm=%x; mmap=%x; address = %x error_code = %x\n",regs->gpr[1],regs->nip, current,current->pid,current->mm,current->mm->mmap, address, error_code);
223 panic("stack2\n");
224 goto bad_area;
225 }
226 vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
227 vma->vm_start = (address & PAGE_MASK);
228
229
230
231
232
233 good_area:
234
235
236
237 if (error_code & 2) {
238 if (!(vma->vm_flags & VM_WRITE))
239 {
240 panic("do_page_fault() write\n");
241 panic("do_page_fault() write! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
242 current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
243 goto bad_area;
244 }
245 } else {
246
247 if (error_code & 1)
248 {
249 panic("do_page_fault() error code thing\n");
250 goto bad_area;
251 }
252 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
253 {
254 #if 0
255 _printk("vma = %x\n", vma);
256 _printk("vma->vm_flags = %x\n", vma->vm_flags);
257 _printk("VM_READ = %x VM_EXEC = %x\n",VM_READ,VM_EXEC);
258 #endif
259 #if 0
260 printk("vma = %x VM_READ = %x VM_EXEC = %x\n",
261 vma, VM_READ,VM_EXEC);
262 printk("vma->vm_start = %x vma->vm_end = %d\n",
263 vma->vm_start, vma->vm_end);
264 printk("error_code = %x\n", error_code);
265 printk("regs = %x\n", regs);
266 printk("vma->vm_flags = %x\n", vma->vm_flags);
267 #endif
268
269 goto bad_area;
270 }
271 }
272
273 handle_mm_fault(vma, address, error_code & 2);
274
275
276 return;
277
278
279
280
281
282 bad_area:
283 if (user_mode(regs)) {
284 printk("Task: %x, PC: %x, bad area! - Addr: %x\n", current, regs->nip, address);
285 send_sig(SIGSEGV, current, 1);
286 return;
287 }
288 #if 0
289 panic("KERNEL! Task: %x, PC: %x, bad area! - Addr: %x, PGDIR: %x\n",
290 current, regs->nip, address, current->tss.pg_tables);
291 #else
292
293
294
295 printk("KERNEL mm! current: %x, address:%x, vm_flags: %x, mm: %x; vma(%x) %x to %x\n",
296 current,address,vma->vm_flags,current->mm,vma,vma->vm_start,vma->vm_end);
297 panic("Kernel access of bad area\n");
298
299 #endif
300
301 while (1) ;
302 }
303
304 va_to_phys(unsigned long address)
305 {
306 pgd_t *dir;
307 pmd_t *pmd;
308 pte_t *pte;
309 dir = pgd_offset(current->mm, address & PAGE_MASK);
310 if (dir)
311 {
312 pmd = pmd_offset(dir, address & PAGE_MASK);
313 if (pmd && pmd_present(*pmd))
314 {
315 pte = pte_offset(pmd, address & PAGE_MASK);
316 if (pte && pte_present(*pte))
317 {
318 return(pte_page(*pte) | (address & ~(PAGE_MASK-1)));
319 }
320 } else
321 {
322 return (0);
323 }
324 } else
325 {
326 return (0);
327 }
328 }
329
330
331
332
333
334
335
336
337
338
339
340
341