fault.c revision 1.4.2.5 1 /* $NetBSD: fault.c,v 1.4.2.5 2002/02/28 04:07:22 nathanw Exp $ */
2
3 /*
4 * Copyright (c) 1994-1997 Mark Brinicombe.
5 * Copyright (c) 1994 Brini.
6 * All rights reserved.
7 *
8 * This code is derived from software written for Brini by Mark Brinicombe
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Brini.
21 * 4. The name of the company nor the name of the author may be used to
22 * endorse or promote products derived from this software without specific
23 * prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * RiscBSD kernel project
38 *
39 * fault.c
40 *
41 * Fault handlers
42 *
43 * Created : 28/11/94
44 */
45
46 #include "opt_ddb.h"
47 #include "opt_pmap_debug.h"
48
49 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/proc.h>
53 #include <sys/user.h>
54 #include <sys/kernel.h>
55
56 #include <uvm/uvm_extern.h>
57
58 #include <machine/frame.h>
59 #include <arm/arm32/katelib.h>
60 #include <machine/cpu.h>
61 #include <machine/intr.h>
62 #ifdef DDB
63 #include <machine/db_machdep.h>
64 #endif
65
66 #include <arch/arm/arm/disassem.h>
67 #include <arm/arm32/machdep.h>
68
69 int cowfault __P((vaddr_t));
70 int fetchuserword __P((u_int address, u_int *location));
71 extern char fusubailout[];
72
73 static void report_abort __P((const char *, u_int, u_int, u_int));
74
75 /* Abort code */
76
77 /* Define text descriptions of the different aborts */
78
79 static const char *aborts[16] = {
80 "Write buffer fault",
81 "Alignment fault",
82 "Write buffer fault",
83 "Alignment fault",
84 "Bus error (LF section)",
85 "Translation fault (section)",
86 "Bus error (page)",
87 "Translation fault (page)",
88 "Bus error (section)",
89 "Domain error (section)",
90 "Bus error (page)",
91 "Domain error (page)",
92 "Bus error trans (L1)",
93 "Permission error (section)",
94 "Bus error trans (L2)",
95 "Permission error (page)"
96 };
97
98 static void
99 report_abort(prefix, fault_status, fault_address, fault_pc)
100 const char *prefix;
101 u_int fault_status;
102 u_int fault_address;
103 u_int fault_pc;
104 {
105 #ifndef DEBUG
106 if (prefix == NULL) {
107 #endif
108 if (prefix)
109 printf("%s ", prefix);
110 printf("Data abort: '%s' status=%03x address=%08x PC=%08x\n",
111 aborts[fault_status & FAULT_TYPE_MASK],
112 fault_status & 0xfff, fault_address, fault_pc);
113 #ifndef DEBUG
114 }
115 #endif
116 }
117
118 static __volatile int data_abort_expected;
119 static __volatile int data_abort_received;
120
121 int
122 badaddr_read(void *addr, size_t size, void *rptr)
123 {
124 u_long rcpt;
125 int rv;
126
127 /* Tell the Data Abort handler that we're expecting one. */
128 data_abort_received = 0;
129 data_abort_expected = 1;
130
131 cpu_drain_writebuf();
132
133 /* Read from the test address. */
134 switch (size) {
135 case sizeof(uint8_t):
136 __asm __volatile("ldrb %0, [%1]"
137 : "=r" (rcpt)
138 : "r" (addr));
139 break;
140
141 case sizeof(uint16_t):
142 __asm __volatile("ldrh %0, [%1]"
143 : "=r" (rcpt)
144 : "r" (addr));
145 break;
146
147 case sizeof(uint32_t):
148 __asm __volatile("ldr %0, [%1]"
149 : "=r" (rcpt)
150 : "r" (addr));
151 break;
152
153 default:
154 data_abort_expected = 0;
155 panic("badaddr: invalid size (%lu)\n", (u_long) size);
156 }
157
158 /* Disallow further Data Aborts. */
159 data_abort_expected = 0;
160
161 rv = data_abort_received;
162 data_abort_received = 0;
163
164 /* Copy the data back if no fault occurred. */
165 if (rptr != NULL && rv == 0) {
166 switch (size) {
167 case sizeof(uint8_t):
168 *(uint8_t *) rptr = rcpt;
169 break;
170
171 case sizeof(uint16_t):
172 *(uint16_t *) rptr = rcpt;
173 break;
174
175 case sizeof(uint32_t):
176 *(uint32_t *) rptr = rcpt;
177 break;
178 }
179 }
180
181 /* Return true if the address was invalid. */
182 return (rv);
183 }
184
185 /*
186 * void data_abort_handler(trapframe_t *frame)
187 *
188 * Abort handler called when read/write occurs at an address of
189 * a non existent or restricted (access permissions) memory page.
190 * We first need to identify the type of page fault.
191 */
192
193 #define TRAP_CODE ((fault_status & 0x0f) | (fault_address & 0xfffffff0))
194
195 void
196 data_abort_handler(frame)
197 trapframe_t *frame;
198 {
199 struct lwp *l;
200 struct proc *p;
201 struct pcb *pcb;
202 u_int fault_address;
203 u_int fault_status;
204 u_int fault_pc;
205 u_int fault_instruction;
206 int fault_code;
207 int user;
208 int error;
209 void *onfault;
210
211 /*
212 * If we were expecting a Data Abort, signal that we got
213 * one, adjust the PC to skip the faulting insn, and
214 * return.
215 */
216 if (data_abort_expected) {
217 data_abort_received = 1;
218 frame->tf_pc += INSN_SIZE;
219 return;
220 }
221
222 /*
223 * Must get fault address and status from the CPU before
224 * re-enabling interrupts. (Interrupt handlers may take
225 * R/M emulation faults.)
226 */
227 fault_address = cpu_faultaddress();
228 fault_status = cpu_faultstatus();
229 fault_pc = frame->tf_pc;
230
231 /*
232 * Enable IRQ's (disabled by CPU on abort) if trapframe
233 * shows they were enabled.
234 */
235 if (!(frame->tf_spsr & I32_bit))
236 enable_interrupts(I32_bit);
237
238 #ifdef DEBUG
239 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
240 panic("data_abort_handler: not in SVC32 mode");
241 #endif
242
243 /* Update vmmeter statistics */
244 uvmexp.traps++;
245
246 /* Extract the fault code from the fault status */
247 fault_code = fault_status & FAULT_TYPE_MASK;
248
249 /* Get the current lwp structure or lwp0 if there is none */
250 l = curproc == NULL ? &lwp0 : curproc;
251 p = l->l_proc;
252
253 /*
254 * can't use curpcb, as it might be NULL; and we have p in
255 * a register anyway
256 */
257 pcb = &l->l_addr->u_pcb;
258
259 /* fusubailout is used by [fs]uswintr to avoid page faulting */
260 if (pcb->pcb_onfault
261 && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P &&
262 fault_code != FAULT_PERM_S && fault_code != FAULT_PERM_P)
263 || pcb->pcb_onfault == fusubailout)) {
264
265 copyfault:
266 #ifdef DEBUG
267 printf("Using pcb_onfault=%p addr=%08x st=%08x l=%p\n",
268 pcb->pcb_onfault, fault_address, fault_status, l);
269 #endif
270 frame->tf_pc = (u_int)pcb->pcb_onfault;
271 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
272 panic("Yikes pcb_onfault=%p during USR mode fault\n",
273 pcb->pcb_onfault);
274 return;
275 }
276
277 /* More debug stuff */
278
279 fault_instruction = ReadWord(fault_pc);
280
281 #ifdef PMAP_DEBUG
282 if (pmap_debug_level >= 0) {
283 report_abort(NULL, fault_status, fault_address, fault_pc);
284 printf("Instruction @V%08x = %08x\n",
285 fault_pc, fault_instruction);
286 }
287 #endif
288
289 /* Call the cpu specific abort fixup routine */
290 error = cpu_dataabt_fixup(frame);
291 if (error == ABORT_FIXUP_RETURN)
292 return;
293 if (error == ABORT_FIXUP_FAILED) {
294 printf("pc = 0x%08x, insn = ", fault_pc);
295 disassemble(fault_pc);
296 panic("data abort fixup failed\n");
297 }
298
299 #ifdef PMAP_DEBUG
300 if (pmap_debug_level >= 0)
301 printf("fault in process %p\n", p);
302 #endif
303
304 #ifdef DEBUG
305 /* Is this needed ? */
306 if (pcb != curpcb) {
307 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n",
308 pcb, curpcb);
309 printf("data_abort: Alert ! proc(%p), curproc(%p)\n",
310 p, curproc);
311 }
312 #endif /* DEBUG */
313
314 /* Were we in user mode when the abort occurred ? */
315 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
316 /*
317 * Note that the fault was from USR mode.
318 */
319 user = 1;
320 l->l_addr->u_pcb.pcb_tf = frame;
321 } else
322 user = 0;
323
324 /* Now act on the fault type */
325 switch (fault_code) {
326 case FAULT_WRTBUF_0: /* Write Buffer Fault */
327 case FAULT_WRTBUF_1: /* Write Buffer Fault */
328 /* If this happens forget it no point in continuing */
329
330 /* FALLTHROUGH */
331
332 case FAULT_ALIGN_0: /* Alignment Fault */
333 case FAULT_ALIGN_1: /* Alignment Fault */
334 /*
335 * Really this should just kill the process.
336 * Alignment faults are turned off in the kernel
337 * in order to get better performance from shorts with
338 * GCC so an alignment fault means somebody has played
339 * with the control register in the CPU. Might as well
340 * panic as the kernel was not compiled for aligned accesses.
341 */
342
343 /* FALLTHROUGH */
344
345 case FAULT_BUSERR_0: /* Bus Error LF Section */
346 case FAULT_BUSERR_1: /* Bus Error Page */
347 case FAULT_BUSERR_2: /* Bus Error Section */
348 case FAULT_BUSERR_3: /* Bus Error Page */
349 /* What will accutally cause a bus error ? */
350 /* Real bus errors are not a process problem but hardware */
351
352 /* FALLTHROUGH */
353
354 case FAULT_DOMAIN_S: /* Section Domain Error Fault */
355 case FAULT_DOMAIN_P: /* Page Domain Error Fault*/
356 /*
357 * Right well we dont use domains, everything is
358 * always a client and thus subject to access permissions.
359 * If we get a domain error then we have corrupts PTE's
360 * so we might as well die !
361 * I suppose eventually this should just kill the process
362 * who owns the PTE's but if this happens it implies a
363 * kernel problem.
364 */
365
366 /* FALLTHROUGH */
367
368 case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */
369 case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */
370 /*
371 * These faults imply that the PTE is corrupt.
372 * Likely to be a kernel fault so we had better stop.
373 */
374
375 /* FALLTHROUGH */
376
377 default :
378 /* Are there any combinations I have missed ? */
379 report_abort(NULL, fault_status, fault_address, fault_pc);
380
381 we_re_toast:
382 /*
383 * Were are dead, try and provide some debug
384 * information before dying.
385 */
386 #ifdef DDB
387 printf("Unhandled trap (frame = %p)\n", frame);
388 report_abort(NULL, fault_status, fault_address, fault_pc);
389 kdb_trap(-1, frame);
390 return;
391 #else
392 panic("Unhandled trap (frame = %p)", frame);
393 #endif /* DDB */
394
395 case FAULT_TRANS_P: /* Page Translation Fault */
396 case FAULT_PERM_P: /* Page Permission Fault */
397 case FAULT_TRANS_S: /* Section Translation Fault */
398 case FAULT_PERM_S: /* Section Permission Fault */
399 /*
400 * Page/section translation/permission fault -- need to fault in
401 * the page and possibly the page table page.
402 */
403 {
404 register vaddr_t va;
405 register struct vmspace *vm = p->p_vmspace;
406 register struct vm_map *map;
407 int rv;
408 vm_prot_t ftype;
409 extern struct vm_map *kernel_map;
410
411 va = trunc_page((vaddr_t)fault_address);
412
413 #ifdef PMAP_DEBUG
414 if (pmap_debug_level >= 0)
415 printf("page fault: addr=V%08lx ", va);
416 #endif
417
418 /*
419 * It is only a kernel address space fault iff:
420 * 1. user == 0 and
421 * 2. pcb_onfault not set or
422 * 3. pcb_onfault set but supervisor space fault
423 * The last can occur during an exec() copyin where the
424 * argument space is lazy-allocated.
425 */
426 if (!user &&
427 (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) {
428 /* Was the fault due to the FPE/IPKDB ? */
429 if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
430 report_abort("UND32", fault_status,
431 fault_address, fault_pc);
432 trapsignal(l, SIGSEGV, TRAP_CODE);
433
434 /*
435 * Force exit via userret()
436 * This is necessary as the FPE is an extension
437 * to userland that actually runs in a
438 * priveledged mode but uses USR mode
439 * permissions for its accesses.
440 */
441 userret(l);
442 return;
443 }
444 map = kernel_map;
445 } else
446 map = &vm->vm_map;
447
448 #ifdef PMAP_DEBUG
449 if (pmap_debug_level >= 0)
450 printf("vmmap=%p ", map);
451 #endif
452
453 if (map == NULL)
454 panic("No map for fault address va = 0x%08lx", va);
455
456 /*
457 * We need to know whether the page should be mapped
458 * as R or R/W. The MMU does not give us the info as
459 * to whether the fault was caused by a read or a write.
460 * This means we need to disassemble the instruction
461 * responsible and determine if it was a read or write
462 * instruction.
463 */
464 /* STR instruction ? */
465 if ((fault_instruction & 0x0c100000) == 0x04000000)
466 ftype = VM_PROT_WRITE;
467 /* STM or CDT instruction ? */
468 else if ((fault_instruction & 0x0a100000) == 0x08000000)
469 ftype = VM_PROT_WRITE;
470 /* STRH, STRSH or STRSB instruction ? */
471 else if ((fault_instruction & 0x0e100090) == 0x00000090)
472 ftype = VM_PROT_WRITE;
473 /* SWP instruction ? */
474 else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
475 ftype = VM_PROT_READ | VM_PROT_WRITE;
476 else
477 ftype = VM_PROT_READ;
478
479 #ifdef PMAP_DEBUG
480 if (pmap_debug_level >= 0)
481 printf("fault protection = %d\n", ftype);
482 #endif
483
484 if ((ftype & VM_PROT_WRITE) ?
485 pmap_modified_emulation(map->pmap, va) :
486 pmap_handled_emulation(map->pmap, va))
487 goto out;
488
489 if (current_intr_depth > 0) {
490 #ifdef DDB
491 printf("Non-emulated page fault with intr_depth > 0\n");
492 report_abort(NULL, fault_status, fault_address, fault_pc);
493 kdb_trap(-1, frame);
494 return;
495 #else
496 panic("Fault with intr_depth > 0");
497 #endif /* DDB */
498 }
499
500 onfault = pcb->pcb_onfault;
501 pcb->pcb_onfault = NULL;
502 rv = uvm_fault(map, va, 0, ftype);
503 pcb->pcb_onfault = onfault;
504 if (rv == 0)
505 goto out;
506
507 if (user == 0) {
508 if (pcb->pcb_onfault)
509 goto copyfault;
510 printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
511 map, va, ftype, rv);
512 goto we_re_toast;
513 }
514
515 report_abort("", fault_status, fault_address, fault_pc);
516 if (rv == ENOMEM) {
517 printf("UVM: pid %d (%s), uid %d killed: "
518 "out of swap\n", p->p_pid, p->p_comm,
519 p->p_cred && p->p_ucred ?
520 p->p_ucred->cr_uid : -1);
521 trapsignal(l, SIGKILL, TRAP_CODE);
522 } else
523 trapsignal(l, SIGSEGV, TRAP_CODE);
524 break;
525 }
526 }
527
528 out:
529 /* Call userret() if it was a USR mode fault */
530 if (user)
531 userret(l);
532 }
533
534
535 /*
536 * void prefetch_abort_handler(trapframe_t *frame)
537 *
538 * Abort handler called when instruction execution occurs at
539 * a non existent or restricted (access permissions) memory page.
540 * If the address is invalid and we were in SVC mode then panic as
541 * the kernel should never prefetch abort.
542 * If the address is invalid and the page is mapped then the user process
543 * does no have read permission so send it a signal.
544 * Otherwise fault the page in and try again.
545 */
546
547 extern int kernel_debug;
548
549 void
550 prefetch_abort_handler(frame)
551 trapframe_t *frame;
552 {
553 u_int fault_pc;
554 struct lwp *l;
555 struct proc *p;
556 struct pcb *pcb;
557 u_int fault_instruction;
558 pt_entry_t *pte;
559 int error;
560
561 /*
562 * Enable IRQ's (disabled by the abort) This always comes
563 * from user mode so we know interrupts were not disabled.
564 * But we check anyway.
565 */
566 if (!(frame->tf_spsr & I32_bit))
567 enable_interrupts(I32_bit);
568
569 #ifdef DEBUG
570 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
571 panic("prefetch_abort_handler: not in SVC32 mode");
572 #endif
573
574 /* Update vmmeter statistics */
575 uvmexp.traps++;
576
577 /* Call the cpu specific abort fixup routine */
578 error = cpu_prefetchabt_fixup(frame);
579 if (error == ABORT_FIXUP_RETURN)
580 return;
581 if (error == ABORT_FIXUP_FAILED)
582 panic("prefetch abort fixup failed\n");
583
584 /* Get the current proc structure or proc0 if there is none */
585 if ((l = curproc) == NULL) {
586 l = &lwp0;
587 #ifdef DEBUG
588 printf("Prefetch abort with curproc == 0\n");
589 #endif
590 }
591 p = l->l_proc;
592
593 #ifdef PMAP_DEBUG
594 if (pmap_debug_level >= 0)
595 printf("prefetch fault in process %p %s\n", p, p->p_comm);
596 #endif
597 /*
598 * can't use curpcb, as it might be NULL; and we have p in a
599 * register anyway
600 */
601 pcb = &l->l_addr->u_pcb;
602 if (pcb == 0)
603 panic("prefetch_abort_handler: no pcb ... we're toast !\n");
604
605 #ifdef DEBUG
606 if (pcb != curpcb) {
607 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n",
608 pcb, curpcb);
609 printf("data_abort: Alert ! proc(%p), curproc(%p)\n",
610 p, curproc);
611 }
612 #endif /* DEBUG */
613
614 /* Get fault address */
615 fault_pc = frame->tf_pc;
616
617 /* Was the prefectch abort from USR32 mode ? */
618 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
619 l->l_addr->u_pcb.pcb_tf = frame;
620 } else {
621 /*
622 * All the kernel code pages are loaded at boot time
623 * and do not get paged
624 */
625 panic("Prefetch abort in non-USR mode (frame=%p PC=0x%08x)\n",
626 frame, fault_pc);
627 }
628
629 #ifdef PMAP_DEBUG
630 if (pmap_debug_level >= 0)
631 printf("prefetch_abort: PC = %08x\n", fault_pc);
632 #endif
633 /* Ok validate the address, can only execute in USER space */
634 if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
635 #ifdef DEBUG
636 printf("prefetch: pc (%08x) not in user process space\n",
637 fault_pc);
638 #endif
639 trapsignal(l, SIGSEGV, fault_pc);
640 userret(l);
641 return;
642 }
643
644 /* Is the page already mapped ? */
645 /* This is debugging for rev K SA110 silicon */
646 pte = pmap_pte(p->p_vmspace->vm_map.pmap, (vaddr_t)fault_pc);
647 if (pte && *pte != 0) {
648 if (kernel_debug & 1) {
649 printf("prefetch_abort: page is already mapped - pte=%p *pte=%08x\n",
650 pte, *pte);
651 printf("prefetch_abort: pc=%08x proc=%p process=%s\n", fault_pc, p, p->p_comm);
652 printf("prefetch_abort: far=%08x fs=%x\n", cpu_faultaddress(), cpu_faultstatus());
653 printf("prefetch_abort: trapframe=%08x\n", (u_int)frame);
654 }
655 #ifdef DDB
656 if (kernel_debug & 2)
657 Debugger();
658 #endif
659 }
660
661 /* Ok read the fault address. This will fault the page in for us */
662 if (fetchuserword(fault_pc, &fault_instruction) != 0) {
663 #ifdef DEBUG
664 printf("prefetch: faultin failed for address %08x\n",
665 fault_pc);
666 #endif
667 trapsignal(l, SIGSEGV, fault_pc);
668 } else {
669
670 #ifdef DIAGNOSTIC
671 /* More debug stuff */
672
673 #ifdef PMAP_DEBUG
674 if (pmap_debug_level >= 0) {
675 printf("Instruction @V%08x = %08x\n", fault_pc,
676 fault_instruction);
677 disassemble(fault_pc);
678 printf("return addr=%08x", frame->tf_pc);
679 pte = pmap_pte(p->p_vmspace->vm_map.pmap,
680 (vaddr_t)fault_pc);
681 if (pte)
682 printf(" pte=%p *pte=%08x\n", pte, *pte);
683 else
684 printf("\n");
685
686 }
687 #endif /* PMAP_DEBUG */
688 #endif /* DIAGNOSTIC */
689 }
690
691 userret(l);
692 }
693
694 int
695 cowfault(va)
696 vaddr_t va;
697 {
698 struct vmspace *vm;
699 int error;
700
701 if (va >= VM_MAXUSER_ADDRESS)
702 return (EFAULT);
703
704 /* uvm_fault can't be called from within an interrupt */
705 KASSERT(current_intr_depth == 0);
706
707 vm = curproc->l_proc->p_vmspace;
708 error = uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE);
709 return error;
710 }
711
712 /* End of fault.c */
713