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