This source file includes following definitions.
- prom_probe_memory
- probe_memory
- sparc_txtmem_error
- sparc_text_access_fault
- sparc_datamem_error
- sparc_data_access_fault
- dump_srmmu_fsr
- really_bad_srmmu_fault
- srmmu_text_access_fault
- srmmu_data_access_fault
1
2
3
4
5
6 #include <linux/string.h>
7 #include <linux/types.h>
8 #include <linux/ptrace.h>
9 #include <linux/mman.h>
10 #include <linux/signal.h>
11 #include <linux/mm.h>
12
13 #include <asm/system.h>
14 #include <asm/segment.h>
15 #include <asm/openprom.h>
16 #include <asm/idprom.h>
17 #include <asm/page.h>
18 #include <asm/pgtable.h>
19 #include <asm/memreg.h>
20 #include <asm/openprom.h>
21 #include <asm/oplib.h>
22 #include <asm/kdebug.h>
23
24 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
25
26 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
27 extern int prom_node_root;
28
29 extern void die_if_kernel(char *,struct pt_regs *,long);
30
31 struct linux_romvec *romvec;
32
33
34
35 int tbase_needs_unmapping;
36
37
38
39
40
41 int num_segmaps, num_contexts;
42 int invalid_segment;
43
44
45
46 int vac_size, vac_linesize, vac_do_hw_vac_flushes;
47 int vac_entries_per_context, vac_entries_per_segment;
48 int vac_entries_per_page;
49
50
51
52
53
54
55 #undef CONFIG_TEST_VERIFY_AREA
56
57
58 int prom_probe_memory (void)
59 {
60 register struct linux_mlist_v0 *mlist;
61 register unsigned long bytes, base_paddr, tally;
62 register int i;
63
64 i = 0;
65 mlist= *prom_meminfo()->v0_available;
66 bytes = tally = mlist->num_bytes;
67 base_paddr = (unsigned long) mlist->start_adr;
68
69 sp_banks[0].base_addr = base_paddr;
70 sp_banks[0].num_bytes = bytes;
71
72 while (mlist->theres_more != (void *) 0){
73 i++;
74 mlist = mlist->theres_more;
75 bytes = mlist->num_bytes;
76 tally += bytes;
77 if (i >= SPARC_PHYS_BANKS-1) {
78 printk ("The machine has more banks that this kernel can support\n"
79 "Increase the SPARC_PHYS_BANKS setting (currently %d)\n",
80 SPARC_PHYS_BANKS);
81 i = SPARC_PHYS_BANKS-1;
82 break;
83 }
84
85 sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
86 sp_banks[i].num_bytes = mlist->num_bytes;
87 }
88
89 i++;
90 sp_banks[i].base_addr = 0xdeadbeef;
91 sp_banks[i].num_bytes = 0;
92
93 return tally;
94 }
95
96
97
98
99 unsigned long
100 probe_memory(void)
101 {
102 int total;
103
104 total = prom_probe_memory();
105
106
107 return total;
108 }
109
110 asmlinkage void sparc_txtmem_error(int type, unsigned long sync_err_reg,
111 unsigned long sync_vaddr,
112 unsigned long async_err_reg,
113 unsigned long async_vaddr)
114 {
115 printk("Aieee, sparc text page access error, halting\n");
116 printk("type = %d sync_err_reg = 0x%x sync_vaddr = 0x%x\n",
117 type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
118 printk("async_err_reg = 0x%x async_vaddr = 0x%x\n",
119 (unsigned int) async_err_reg, (unsigned int) async_vaddr);
120 halt();
121 }
122
123
124
125 asmlinkage void sparc_text_access_fault(int type, unsigned long sync_err_reg,
126 unsigned long sync_vaddr,
127 unsigned long pc, unsigned long psr,
128 struct pt_regs *regs)
129 {
130 struct vm_area_struct *vma;
131 unsigned long address;
132
133 address = sync_vaddr;
134 #ifdef DEBUG_SPARC_TEXT_ACCESS_FAULT
135 printk("Text FAULT: address = %08lx code = %08lx\n",
136 (unsigned long) address, (unsigned long) sync_err_reg);
137 printk("PC = %08lx\n", (unsigned long) regs->pc);
138 SP_ENTER_DEBUGGER;
139 halt();
140 #endif
141 vma = find_vma(current, address);
142 if(!vma) {
143 goto bad_area;
144 }
145 if(vma->vm_start <= address)
146 goto good_area;
147 goto bad_area;
148
149
150
151
152
153 good_area:
154 handle_mm_fault(vma, address, 0);
155 return;
156
157
158
159
160
161 bad_area:
162 if((unsigned long) address < PAGE_SIZE) {
163 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
164 } else
165 printk(KERN_ALERT "Unable to handle kernel paging request");
166 printk(" at virtual address %08lx\n",address);
167 printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
168 (unsigned long) current->tss.pgd_ptr);
169 halt();
170 }
171
172 asmlinkage void sparc_datamem_error(int type, unsigned long sync_err_reg,
173 unsigned long sync_vaddr,
174 unsigned long async_err_reg,
175 unsigned long async_vaddr)
176 {
177 printk("Aieee, sparc data page access error, halting\n");
178 printk("type = %d sync_err_reg = 0x%x sync_vaddr = 0x%x\n",
179 type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
180 printk("async_err_reg = 0x%x async_vaddr = 0x%x\n",
181 (unsigned int) async_err_reg, (unsigned int) async_vaddr);
182 printk("SYNC PAGE has MMU entry %08lx\n",
183 (unsigned long) get_pte(sync_vaddr));
184 halt();
185 }
186
187
188
189 asmlinkage void sparc_data_access_fault(int type, unsigned long sync_err_reg,
190 unsigned long sync_vaddr,
191 unsigned long pc, unsigned long psr,
192 struct pt_regs *regs)
193 {
194 struct vm_area_struct *vma;
195 unsigned long address;
196 int error_code;
197
198 address = sync_vaddr;
199 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
200 printk("Data FAULT: address = %08lx code = %08lx\n",
201 (unsigned long) address, (unsigned long) sync_err_reg);
202 printk("PC = %08lx\n", (unsigned long) regs->pc);
203 printk("PTE = %08lx\n", (unsigned long) get_pte(address));
204 #endif
205 vma = find_vma(current, address);
206 if(!vma) {
207 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
208 printk("NULL VMA\n");
209 #endif
210 goto bad_area;
211 }
212 if(vma->vm_start <= address)
213 goto good_area;
214
215 if(!(vma->vm_flags & VM_GROWSDOWN)) {
216 goto bad_area;
217 }
218 if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
219 goto bad_area;
220 }
221
222 vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
223 vma->vm_start = (address & PAGE_MASK);
224
225
226
227
228
229 good_area:
230 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
231 printk("Found good_area\n");
232 #endif
233 if((sync_err_reg & SUN4C_SYNC_BADWRITE) &&
234 (sync_err_reg & SUN4C_SYNC_NPRESENT)) {
235 if(!(vma->vm_flags & VM_WRITE)) {
236 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
237 printk("oops, vma not writable\n");
238 #endif
239 goto bad_area;
240 }
241 } else {
242 if(sync_err_reg & SUN4C_SYNC_PROT) {
243 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
244 printk("PROT violation\n");
245 #endif
246 goto bad_area;
247 }
248 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
249 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
250 printk("vma not readable nor executable\n");
251 #endif
252 goto bad_area;
253 }
254 }
255
256 if(sync_err_reg & SUN4C_SYNC_BADWRITE)
257 error_code = 0x2;
258 else
259 error_code = 0x0;
260
261 #ifdef DEBUG_SPARC_DATA_ACCESS_FAULT
262 printk("calling handle_mm_fault vma=%08lx addr=%08lx code=%d\n",
263 (unsigned long) vma, (unsigned long) address,
264 (int) error_code);
265 #endif
266 handle_mm_fault(vma, address, error_code);
267 return;
268
269
270
271
272
273 bad_area:
274 if (wp_works_ok < 0 && address == 0x0) {
275 wp_works_ok = 1;
276 pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_SHARED));
277 put_pte((unsigned long) 0x0, pg0[0]);
278 printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
279 return;
280 }
281
282 if((unsigned long) address < PAGE_SIZE) {
283 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
284 } else
285 printk(KERN_ALERT "Unable to handle kernel paging request");
286 printk(" at virtual address %08lx\n",address);
287 printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
288 (unsigned long) current->tss.pgd_ptr);
289 halt();
290 }
291
292
293 void
294 dump_srmmu_fsr(unsigned long fsr)
295 {
296 unsigned long ebe, l, at, ft, fav, ow;
297
298 ebe = (fsr&SRMMU_FSR_EBE_MASK)>>10;
299 l = (fsr&SRMMU_FSR_L_MASK)>>8;
300 at = (fsr&SRMMU_FSR_AT_MASK)>>5;
301 ft = (fsr&SRMMU_FSR_FT_MASK)>>2;
302 fav = (fsr&SRMMU_FSR_FAV_MASK)>>1;
303 ow = (fsr&SRMMU_FSR_OW_MASK);
304
305 printk("FSR %08lx: ", fsr);
306
307
308 printk("EBE<%s> ", (ebe == 0 ? "none" : (ebe == 1 ? "bus err" :
309 (ebe == 2 ? "bus timeout" :
310 (ebe == 4 ? "uncorrectable err" :
311 (ebe == 8 ? "undefined err" :
312 (ebe == 16 ? "parity err" :
313 (ebe == 24 ? "tsunami parity err" :
314 (ebe == 32 ? "store buf err" :
315 (ebe == 64 ? "control space err" :
316 "VIKING emergency response team"))))))))));
317 printk("L<%s> ", (l == 0 ? "context table" : (l == 1 ? "level1" :
318 (l == 2 ? "level2" :
319 "level3"))));
320 printk("AT<%s> ", (at == 0 ? "user load" :
321 (at == 1 ? "priv load" :
322 (at == 2 ? "user rd/exec" :
323 (at == 3 ? "priv rd/exec" :
324 (at == 4 ? "user store data" :
325 (at == 5 ? "priv store data" :
326 (at == 6 ? "user store inst" :
327 "priv store inst"))))))));
328
329 printk("FT<%s> ", (ft == 0 ? "none" :
330 (ft == 1 ? "invalid address" :
331 (ft == 2 ? "prot violation" :
332 (ft == 3 ? "priv violation" :
333 (ft == 4 ? "translation error" :
334 (ft == 5 ? "bus acc error" :
335 (ft == 6 ? "internal error" :
336 "reserved"))))))));
337
338 printk("FAV<%s> ", (fav == 0 ? "faddr invalid" : "faddr valid"));
339 printk("OW<%s>\n", (ow == 0 ? "fsr not overwritten" : "fsr overwritten"));
340
341 return;
342 }
343
344
345
346 void
347 really_bad_srmmu_fault(int type, unsigned long fstatus, unsigned long faddr)
348 {
349
350 printk("REALLY BAD SRMMU FAULT DETECTED\n");
351 printk("Bailing out...\n");
352 dump_srmmu_fsr(fstatus);
353 prom_halt();
354 return;
355 }
356
357 asmlinkage void srmmu_text_access_fault(int type, unsigned long fstatus,
358 unsigned long faddr,
359 unsigned long pc, unsigned long psr,
360 struct pt_regs *regs)
361 {
362 struct vm_area_struct *vma;
363 unsigned long address;
364
365
366 if(fstatus&SRMMU_FSR_EBE_MASK)
367 printk("External Bus Error detected during a text fault.\n");
368
369
370 if(fstatus&SRMMU_FSR_OW_MASK && (fstatus&SRMMU_FSR_FT_TRANS)) {
371 printk("Multiple faults detected in text fault handler\n");
372 printk("Fault number one: Text fault at addr %08lx", faddr);
373 printk("Fault number two: Translation Error\n");
374 printk("Giving up...\n");
375 prom_halt();
376 }
377
378 if(fstatus&(SRMMU_FSR_EBE_BERR | SRMMU_FSR_EBE_BTIMEO | SRMMU_FSR_EBE_UNCOR))
379 really_bad_srmmu_fault(type, fstatus, faddr);
380
381
382
383 address = faddr;
384 #ifdef DEBUG_SRMMU_TEXT_ACCESS_FAULT
385 printk("Text FAULT: address = %08lx code = %08lx\n",
386 (unsigned long) address, (unsigned long) fstatus);
387 printk("PC = %08lx\n", (unsigned long) regs->pc);
388 dump_srmmu_fsr(fstatus);
389 halt();
390 #endif
391
392
393 if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
394 printk("Fault address register is INVALID! Since this is a text\n");
395 printk("fault I'll use the value of the trapped PC instead...\n");
396 address = regs->pc;
397 }
398
399
400
401 vma = find_vma(current, address);
402 if(!vma) {
403 goto bad_area;
404 }
405 if(vma->vm_start <= address)
406 goto good_area;
407 goto bad_area;
408
409
410
411
412
413 good_area:
414 do_no_page(vma, address, 0);
415 return;
416
417
418
419
420
421 bad_area:
422 if((unsigned long) address < PAGE_SIZE) {
423 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
424 } else
425 printk(KERN_ALERT "Unable to handle kernel paging request");
426 printk(" at virtual address %08lx\n",address);
427 printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
428 (unsigned long) current->tss.pgd_ptr);
429 halt();
430 }
431
432
433
434 asmlinkage void srmmu_data_access_fault(int type, unsigned long fstatus,
435 unsigned long faddr,
436 unsigned long afstatus,
437 unsigned long afaddr,
438 struct pt_regs *regs)
439 {
440 struct vm_area_struct *vma;
441 unsigned long address, pc, psr;
442 int error_code;
443
444 pc = regs->pc;
445 psr= regs->psr;
446 address = faddr;
447 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
448 printk("Data FAULT: address = %08lx code = %08lx\n",
449 (unsigned long) address, (unsigned long) fstatus);
450 printk("PC = %08lx\n", (unsigned long) pc);
451 printk("afsr = %08lx afaddr = %08lx\n", afstatus, afaddr);
452 dump_srmmu_fsr(fstatus);
453 #endif
454
455
456
457
458 if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
459 dump_srmmu_fsr(fstatus);
460 panic("hat_pteload: Fault address is invalid on a data fault, I'm confused...\n");
461 }
462
463 #if 0
464 if(fstatus&SRMMU_FSR_OW_MASK) {
465 dump_srmmu_fsr(fstatus);
466 panic("hat_pteload: Multiple faults at once, giving up...\n");
467 }
468 #endif
469
470 vma = find_vma(current, address);
471 if(!vma) {
472 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
473 printk("NULL VMA\n");
474 #endif
475 goto bad_area;
476 }
477 if(vma->vm_start <= address)
478 goto good_area;
479
480 if(!(vma->vm_flags & VM_GROWSDOWN)) {
481 goto bad_area;
482 }
483 if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
484 goto bad_area;
485 }
486
487 vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
488 vma->vm_start = (address & PAGE_MASK);
489
490
491
492
493
494 good_area:
495 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
496 printk("Found good_area\n");
497 #endif
498 if((fstatus & SUN4C_SYNC_BADWRITE) &&
499 (fstatus & SUN4C_SYNC_NPRESENT)) {
500 if(!(vma->vm_flags & VM_WRITE)) {
501 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
502 printk("oops, vma not writable\n");
503 #endif
504 goto bad_area;
505 }
506 } else {
507 if(fstatus & SUN4C_SYNC_PROT) {
508 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
509 printk("PROT violation\n");
510 #endif
511 goto bad_area;
512 }
513 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
514 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
515 printk("vma not readable nor executable\n");
516 #endif
517 goto bad_area;
518 }
519 }
520
521 if(fstatus & SUN4C_SYNC_BADWRITE)
522 error_code = 0x2;
523 else
524 error_code = 0x0;
525
526 #ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT
527 printk("calling do_no_page vma=%08lx addr=%08lx code=%d\n",
528 (unsigned long) vma, (unsigned long) address,
529 (int) error_code);
530 #endif
531 do_no_page(vma, address, error_code);
532 return;
533
534
535
536
537
538 bad_area:
539 if (wp_works_ok < 0 && address == 0x0) {
540 wp_works_ok = 1;
541
542 regs->pc = regs->npc;
543 regs->npc += 4;
544 printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
545 return;
546 }
547
548 if((unsigned long) address < PAGE_SIZE) {
549 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
550 } else
551 printk(KERN_ALERT "Unable to handle kernel paging request");
552 printk(" at virtual address %08lx\n",address);
553 printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
554 (unsigned long) current->tss.pgd_ptr);
555 halt();
556 }