fault.c revision 1.20 1 /* $NetBSD: fault.c,v 1.20 2002/08/12 20:17:37 bjh21 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 <arm/cpuconf.h>
59
60 #include <machine/frame.h>
61 #include <arm/arm32/katelib.h>
62 #include <machine/cpu.h>
63 #include <machine/intr.h>
64 #ifdef DDB
65 #include <machine/db_machdep.h>
66 #endif
67
68 #include <arch/arm/arm/disassem.h>
69 #include <arm/arm32/machdep.h>
70
71 int cowfault __P((vaddr_t));
72 extern char fusubailout[];
73
74 static void report_abort __P((const char *, u_int, u_int, u_int));
75
76 /* Abort code */
77
78 /* Define text descriptions of the different aborts */
79
80 static const char *aborts[16] = {
81 "Write buffer fault",
82 "Alignment fault",
83 "Write buffer fault",
84 "Alignment fault",
85 "Bus error (LF section)",
86 "Translation fault (section)",
87 "Bus error (page)",
88 "Translation fault (page)",
89 "Bus error (section)",
90 "Domain error (section)",
91 "Bus error (page)",
92 "Domain error (page)",
93 "Bus error trans (L1)",
94 "Permission error (section)",
95 "Bus error trans (L2)",
96 "Permission error (page)"
97 };
98
99 static void
100 report_abort(prefix, fault_status, fault_address, fault_pc)
101 const char *prefix;
102 u_int fault_status;
103 u_int fault_address;
104 u_int fault_pc;
105 {
106 #ifndef DEBUG
107 if (prefix == NULL) {
108 #endif
109 if (prefix)
110 printf("%s ", prefix);
111 printf("Data abort: '%s' status=%03x address=%08x PC=%08x\n",
112 aborts[fault_status & FAULT_TYPE_MASK],
113 fault_status & 0xfff, fault_address, fault_pc);
114 #ifndef DEBUG
115 }
116 #endif
117 }
118
119 static __volatile int data_abort_expected;
120 static __volatile int data_abort_received;
121
122 int
123 badaddr_read(void *addr, size_t size, void *rptr)
124 {
125 u_long rcpt;
126 int rv;
127
128 /* Tell the Data Abort handler that we're expecting one. */
129 data_abort_received = 0;
130 data_abort_expected = 1;
131
132 cpu_drain_writebuf();
133
134 /* Read from the test address. */
135 switch (size) {
136 case sizeof(uint8_t):
137 __asm __volatile("ldrb %0, [%1]"
138 : "=r" (rcpt)
139 : "r" (addr));
140 break;
141
142 case sizeof(uint16_t):
143 __asm __volatile("ldrh %0, [%1]"
144 : "=r" (rcpt)
145 : "r" (addr));
146 break;
147
148 case sizeof(uint32_t):
149 __asm __volatile("ldr %0, [%1]"
150 : "=r" (rcpt)
151 : "r" (addr));
152 break;
153
154 default:
155 data_abort_expected = 0;
156 panic("badaddr: invalid size (%lu)\n", (u_long) size);
157 }
158
159 /* Disallow further Data Aborts. */
160 data_abort_expected = 0;
161
162 rv = data_abort_received;
163 data_abort_received = 0;
164
165 /* Copy the data back if no fault occurred. */
166 if (rptr != NULL && rv == 0) {
167 switch (size) {
168 case sizeof(uint8_t):
169 *(uint8_t *) rptr = rcpt;
170 break;
171
172 case sizeof(uint16_t):
173 *(uint16_t *) rptr = rcpt;
174 break;
175
176 case sizeof(uint32_t):
177 *(uint32_t *) rptr = rcpt;
178 break;
179 }
180 }
181
182 /* Return true if the address was invalid. */
183 return (rv);
184 }
185
186 /*
187 * void data_abort_handler(trapframe_t *frame)
188 *
189 * Abort handler called when read/write occurs at an address of
190 * a non existent or restricted (access permissions) memory page.
191 * We first need to identify the type of page fault.
192 */
193
194 #define TRAP_CODE ((fault_status & 0x0f) | (fault_address & 0xfffffff0))
195
196 void
197 data_abort_handler(frame)
198 trapframe_t *frame;
199 {
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 proc structure or proc0 if there is none */
250 if ((p = curproc) == NULL)
251 p = &proc0;
252
253 /*
254 * can't use curpcb, as it might be NULL; and we have p in
255 * a register anyway
256 */
257 pcb = &p->p_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 frame->tf_r0 = EFAULT;
266 copyfault:
267 #ifdef DEBUG
268 printf("Using pcb_onfault=%p addr=%08x st=%08x p=%p\n",
269 pcb->pcb_onfault, fault_address, fault_status, p);
270 #endif
271 frame->tf_pc = (u_int)pcb->pcb_onfault;
272 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
273 panic("Yikes pcb_onfault=%p during USR mode fault\n",
274 pcb->pcb_onfault);
275 return;
276 }
277
278 /* More debug stuff */
279
280 fault_instruction = ReadWord(fault_pc);
281
282 #ifdef PMAP_DEBUG
283 if (pmap_debug_level >= 0) {
284 report_abort(NULL, fault_status, fault_address, fault_pc);
285 printf("Instruction @V%08x = %08x\n",
286 fault_pc, fault_instruction);
287 }
288 #endif
289
290 /* Call the cpu specific abort fixup routine */
291 error = cpu_dataabt_fixup(frame);
292 if (error == ABORT_FIXUP_RETURN)
293 return;
294 if (error == ABORT_FIXUP_FAILED) {
295 printf("pc = 0x%08x, opcode 0x%08x, insn = ", fault_pc, *((u_int *)fault_pc));
296 disassemble(fault_pc);
297 printf("data abort handler: fixup failed for this instruction\n");
298 }
299
300 #ifdef PMAP_DEBUG
301 if (pmap_debug_level >= 0)
302 printf("fault in process %p\n", p);
303 #endif
304
305 #ifdef DEBUG
306 /* Is this needed ? */
307 if (pcb != curpcb) {
308 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n",
309 pcb, curpcb);
310 printf("data_abort: Alert ! proc(%p), curproc(%p)\n",
311 p, curproc);
312 }
313 #endif /* DEBUG */
314
315 /* Were we in user mode when the abort occurred ? */
316 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
317 /*
318 * Note that the fault was from USR mode.
319 */
320 user = 1;
321 p->p_addr->u_pcb.pcb_tf = frame;
322 } else
323 user = 0;
324
325 /* check if this was a failed fixup */
326 if (error == ABORT_FIXUP_FAILED) {
327 if (user) {
328 trapsignal(p, SIGSEGV, TRAP_CODE);
329 userret(p);
330 return;
331 };
332 panic("Data abort fixup failed in kernel - we're dead\n");
333 };
334
335 /* Now act on the fault type */
336 switch (fault_code) {
337 case FAULT_WRTBUF_0: /* Write Buffer Fault */
338 case FAULT_WRTBUF_1: /* Write Buffer Fault */
339 /* If this happens forget it no point in continuing */
340
341 /* FALLTHROUGH */
342
343 case FAULT_ALIGN_0: /* Alignment Fault */
344 case FAULT_ALIGN_1: /* Alignment Fault */
345 /*
346 * Really this should just kill the process.
347 * Alignment faults are turned off in the kernel
348 * in order to get better performance from shorts with
349 * GCC so an alignment fault means somebody has played
350 * with the control register in the CPU. Might as well
351 * panic as the kernel was not compiled for aligned accesses.
352 */
353
354 /* FALLTHROUGH */
355
356 case FAULT_BUSERR_0: /* Bus Error LF Section */
357 case FAULT_BUSERR_1: /* Bus Error Page */
358 case FAULT_BUSERR_2: /* Bus Error Section */
359 case FAULT_BUSERR_3: /* Bus Error Page */
360 /* What will accutally cause a bus error ? */
361 /* Real bus errors are not a process problem but hardware */
362
363 /* FALLTHROUGH */
364
365 case FAULT_DOMAIN_S: /* Section Domain Error Fault */
366 case FAULT_DOMAIN_P: /* Page Domain Error Fault*/
367 /*
368 * Right well we dont use domains, everything is
369 * always a client and thus subject to access permissions.
370 * If we get a domain error then we have corrupts PTE's
371 * so we might as well die !
372 * I suppose eventually this should just kill the process
373 * who owns the PTE's but if this happens it implies a
374 * kernel problem.
375 */
376
377 /* FALLTHROUGH */
378
379 case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */
380 case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */
381 /*
382 * These faults imply that the PTE is corrupt.
383 * Likely to be a kernel fault so we had better stop.
384 */
385
386 /* FALLTHROUGH */
387
388 default :
389 /* Are there any combinations I have missed ? */
390 report_abort(NULL, fault_status, fault_address, fault_pc);
391
392 we_re_toast:
393 /*
394 * Were are dead, try and provide some debug
395 * information before dying.
396 */
397 #ifdef DDB
398 printf("Unhandled trap (frame = %p)\n", frame);
399 report_abort(NULL, fault_status, fault_address, fault_pc);
400 kdb_trap(-1, frame);
401 return;
402 #else
403 panic("Unhandled trap (frame = %p)", frame);
404 #endif /* DDB */
405
406 case FAULT_TRANS_P: /* Page Translation Fault */
407 case FAULT_PERM_P: /* Page Permission Fault */
408 case FAULT_TRANS_S: /* Section Translation Fault */
409 case FAULT_PERM_S: /* Section Permission Fault */
410 /*
411 * Page/section translation/permission fault -- need to fault in
412 * the page and possibly the page table page.
413 */
414 {
415 register vaddr_t va;
416 register struct vmspace *vm = p->p_vmspace;
417 register struct vm_map *map;
418 int rv;
419 vm_prot_t ftype;
420 extern struct vm_map *kernel_map;
421
422 va = trunc_page((vaddr_t)fault_address);
423
424 #ifdef PMAP_DEBUG
425 if (pmap_debug_level >= 0)
426 printf("page fault: addr=V%08lx ", va);
427 #endif
428
429 /*
430 * It is only a kernel address space fault iff:
431 * 1. user == 0 and
432 * 2. pcb_onfault not set or
433 * 3. pcb_onfault set but supervisor space fault
434 * The last can occur during an exec() copyin where the
435 * argument space is lazy-allocated.
436 */
437 if (!user &&
438 (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) {
439 /* Was the fault due to the FPE/IPKDB ? */
440 if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
441 report_abort("UND32", fault_status,
442 fault_address, fault_pc);
443 trapsignal(p, SIGSEGV, TRAP_CODE);
444
445 /*
446 * Force exit via userret()
447 * This is necessary as the FPE is an extension
448 * to userland that actually runs in a
449 * priveledged mode but uses USR mode
450 * permissions for its accesses.
451 */
452 userret(p);
453 return;
454 }
455 map = kernel_map;
456 } else
457 map = &vm->vm_map;
458
459 #ifdef PMAP_DEBUG
460 if (pmap_debug_level >= 0)
461 printf("vmmap=%p ", map);
462 #endif
463
464 if (map == NULL)
465 panic("No map for fault address va = 0x%08lx", va);
466
467 /*
468 * We need to know whether the page should be mapped
469 * as R or R/W. The MMU does not give us the info as
470 * to whether the fault was caused by a read or a write.
471 * This means we need to disassemble the instruction
472 * responsible and determine if it was a read or write
473 * instruction.
474 */
475 /* STR instruction ? */
476 if ((fault_instruction & 0x0c100000) == 0x04000000)
477 ftype = VM_PROT_WRITE;
478 /* STM or CDT instruction ? */
479 else if ((fault_instruction & 0x0a100000) == 0x08000000)
480 ftype = VM_PROT_WRITE;
481 /* STRH, STRSH or STRSB instruction ? */
482 else if ((fault_instruction & 0x0e100090) == 0x00000090)
483 ftype = VM_PROT_WRITE;
484 /* SWP instruction ? */
485 else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
486 ftype = VM_PROT_READ | VM_PROT_WRITE;
487 else
488 ftype = VM_PROT_READ;
489
490 #ifdef PMAP_DEBUG
491 if (pmap_debug_level >= 0)
492 printf("fault protection = %d\n", ftype);
493 #endif
494
495 if ((ftype & VM_PROT_WRITE) ?
496 pmap_modified_emulation(map->pmap, va) :
497 pmap_handled_emulation(map->pmap, va))
498 goto out;
499
500 if (current_intr_depth > 0) {
501 #ifdef DDB
502 printf("Non-emulated page fault with intr_depth > 0\n");
503 report_abort(NULL, fault_status, fault_address, fault_pc);
504 kdb_trap(-1, frame);
505 return;
506 #else
507 panic("Fault with intr_depth > 0");
508 #endif /* DDB */
509 }
510
511 onfault = pcb->pcb_onfault;
512 pcb->pcb_onfault = NULL;
513 rv = uvm_fault(map, va, 0, ftype);
514 pcb->pcb_onfault = onfault;
515 if (rv == 0)
516 goto out;
517
518 if (user == 0) {
519 if (pcb->pcb_onfault) {
520 frame->tf_r0 = rv;
521 goto copyfault;
522 }
523 printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
524 map, va, ftype, rv);
525 goto we_re_toast;
526 }
527
528 report_abort("", fault_status, fault_address, fault_pc);
529 if (rv == ENOMEM) {
530 printf("UVM: pid %d (%s), uid %d killed: "
531 "out of swap\n", p->p_pid, p->p_comm,
532 p->p_cred && p->p_ucred ?
533 p->p_ucred->cr_uid : -1);
534 trapsignal(p, SIGKILL, TRAP_CODE);
535 } else
536 trapsignal(p, SIGSEGV, TRAP_CODE);
537 break;
538 }
539 }
540
541 out:
542 /* Call userret() if it was a USR mode fault */
543 if (user)
544 userret(p);
545 }
546
547
548 /*
549 * void prefetch_abort_handler(trapframe_t *frame)
550 *
551 * Abort handler called when instruction execution occurs at
552 * a non existent or restricted (access permissions) memory page.
553 * If the address is invalid and we were in SVC mode then panic as
554 * the kernel should never prefetch abort.
555 * If the address is invalid and the page is mapped then the user process
556 * does no have read permission so send it a signal.
557 * Otherwise fault the page in and try again.
558 */
559
560 extern int kernel_debug;
561
562 void
563 prefetch_abort_handler(frame)
564 trapframe_t *frame;
565 {
566 struct proc *p;
567 struct vm_map *map;
568 vaddr_t fault_pc, va;
569 int error;
570
571 /*
572 * Enable IRQ's (disabled by the abort) This always comes
573 * from user mode so we know interrupts were not disabled.
574 * But we check anyway.
575 */
576 if (!(frame->tf_spsr & I32_bit))
577 enable_interrupts(I32_bit);
578
579 #ifdef DEBUG
580 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
581 panic("prefetch_abort_handler: not in SVC32 mode");
582 #endif
583
584 /* Update vmmeter statistics */
585 uvmexp.traps++;
586
587 /* Call the cpu specific abort fixup routine */
588 error = cpu_prefetchabt_fixup(frame);
589 if (error == ABORT_FIXUP_RETURN)
590 return;
591 if (error == ABORT_FIXUP_FAILED)
592 panic("prefetch abort fixup failed\n");
593
594 /* Get the current proc structure or proc0 if there is none */
595 if ((p = curproc) == 0) {
596 p = &proc0;
597 #ifdef DEBUG
598 printf("Prefetch abort with curproc == 0\n");
599 #endif
600 }
601
602 #ifdef PMAP_DEBUG
603 if (pmap_debug_level >= 0)
604 printf("prefetch fault in process %p %s\n", p, p->p_comm);
605 #endif
606
607 /* Get fault address */
608 fault_pc = frame->tf_pc;
609 va = trunc_page(fault_pc);
610
611 /* Was the prefectch abort from USR32 mode ? */
612 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
613 p->p_addr->u_pcb.pcb_tf = frame;
614 } else {
615 /*
616 * All the kernel code pages are loaded at boot time
617 * and do not get paged
618 */
619 panic("Prefetch abort in non-USR mode (frame=%p PC=0x%08lx)\n",
620 frame, fault_pc);
621 }
622
623 map = &p->p_vmspace->vm_map;
624
625 #ifdef PMAP_DEBUG
626 if (pmap_debug_level >= 0)
627 printf("prefetch_abort: PC = %08lx\n", fault_pc);
628 #endif
629 /* Ok validate the address, can only execute in USER space */
630 if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
631 #ifdef DEBUG
632 printf("prefetch: pc (%08lx) not in user process space\n",
633 fault_pc);
634 #endif
635 trapsignal(p, SIGSEGV, fault_pc);
636 userret(p);
637 return;
638 }
639
640 #ifdef CPU_SA110
641 /*
642 * There are bugs in the rev K SA110. This is a check for one
643 * of them.
644 */
645 if (curcpu()->ci_cputype == CPU_ID_SA110 && curcpu()->ci_cpurev < 3) {
646 /* Always current pmap */
647 pt_entry_t *pte = vtopte((vaddr_t) fault_pc);
648 struct pmap *pmap = p->p_vmspace->vm_map.pmap;
649
650 if (pmap_pde_v(pmap_pde(pmap, (vaddr_t) fault_pc)) &&
651 pmap_pte_v(pte)) {
652 if (kernel_debug & 1) {
653 printf("prefetch_abort: page is already "
654 "mapped - pte=%p *pte=%08x\n", pte, *pte);
655 printf("prefetch_abort: pc=%08lx proc=%p "
656 "process=%s\n", fault_pc, p, p->p_comm);
657 printf("prefetch_abort: far=%08x fs=%x\n",
658 cpu_faultaddress(), cpu_faultstatus());
659 printf("prefetch_abort: trapframe=%08x\n",
660 (u_int)frame);
661 }
662 #ifdef DDB
663 if (kernel_debug & 2)
664 Debugger();
665 #endif
666 }
667 }
668 #endif /* CPU_SA110 */
669
670 if (pmap_handled_emulation(map->pmap, va))
671 goto out;
672
673 if (current_intr_depth > 0) {
674 #ifdef DDB
675 printf("Non-emulated prefetch abort with intr_depth > 0\n");
676 kdb_trap(-1, frame);
677 return;
678 #else
679 panic("Prefetch Abort with intr_depth > 0");
680 #endif
681 }
682
683 error = uvm_fault(map, va, 0, VM_PROT_READ);
684 if (error == 0)
685 goto out;
686
687 if (error == ENOMEM) {
688 printf("UVM: pid %d (%s), uid %d killed: "
689 "out of swap\n", p->p_pid, p->p_comm,
690 p->p_cred && p->p_ucred ?
691 p->p_ucred->cr_uid : -1);
692 trapsignal(p, SIGKILL, fault_pc);
693 } else
694 trapsignal(p, SIGSEGV, fault_pc);
695 out:
696 userret(p);
697 }
698
699 int
700 cowfault(va)
701 vaddr_t va;
702 {
703 struct vmspace *vm;
704 int error;
705
706 if (va >= VM_MAXUSER_ADDRESS)
707 return (EFAULT);
708
709 /* uvm_fault can't be called from within an interrupt */
710 KASSERT(current_intr_depth == 0);
711
712 vm = curproc->p_vmspace;
713 error = uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE);
714 return error;
715 }
716