fault.c revision 1.7 1 /* $NetBSD: fault.c,v 1.7 2002/01/05 22:41:47 chris 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 proc *p;
200 struct pcb *pcb;
201 u_int fault_address;
202 u_int fault_status;
203 u_int fault_pc;
204 u_int fault_instruction;
205 int fault_code;
206 int user;
207 int error;
208 void *onfault;
209
210 /*
211 * If we were expecting a Data Abort, signal that we got
212 * one, adjust the PC to skip the faulting insn, and
213 * return.
214 */
215 if (data_abort_expected) {
216 data_abort_received = 1;
217 frame->tf_pc += INSN_SIZE;
218 return;
219 }
220
221 /*
222 * Must get fault address and status from the CPU before
223 * re-enabling interrupts. (Interrupt handlers may take
224 * R/M emulation faults.)
225 */
226 fault_address = cpu_faultaddress();
227 fault_status = cpu_faultstatus();
228 fault_pc = frame->tf_pc;
229
230 /*
231 * Enable IRQ's (disabled by CPU on abort) if trapframe
232 * shows they were enabled.
233 */
234 if (!(frame->tf_spsr & I32_bit))
235 enable_interrupts(I32_bit);
236
237 #ifdef DEBUG
238 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
239 panic("data_abort_handler: not in SVC32 mode");
240 #endif
241
242 /* Update vmmeter statistics */
243 uvmexp.traps++;
244
245 /* Extract the fault code from the fault status */
246 fault_code = fault_status & FAULT_TYPE_MASK;
247
248 /* Get the current proc structure or proc0 if there is none */
249 if ((p = curproc) == NULL)
250 p = &proc0;
251
252 /*
253 * can't use curpcb, as it might be NULL; and we have p in
254 * a register anyway
255 */
256 pcb = &p->p_addr->u_pcb;
257
258 /* fusubailout is used by [fs]uswintr to avoid page faulting */
259 if (pcb->pcb_onfault
260 && ((fault_code != FAULT_TRANS_S && fault_code != FAULT_TRANS_P &&
261 fault_code != FAULT_PERM_S && fault_code != FAULT_PERM_P)
262 || pcb->pcb_onfault == fusubailout)) {
263
264 copyfault:
265 #ifdef DEBUG
266 printf("Using pcb_onfault=%p addr=%08x st=%08x p=%p\n",
267 pcb->pcb_onfault, fault_address, fault_status, p);
268 #endif
269 frame->tf_pc = (u_int)pcb->pcb_onfault;
270 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
271 panic("Yikes pcb_onfault=%p during USR mode fault\n",
272 pcb->pcb_onfault);
273 return;
274 }
275
276 /* More debug stuff */
277
278 fault_instruction = ReadWord(fault_pc);
279
280 #ifdef PMAP_DEBUG
281 if (pmap_debug_level >= 0) {
282 report_abort(NULL, fault_status, fault_address, fault_pc);
283 printf("Instruction @V%08x = %08x\n",
284 fault_pc, fault_instruction);
285 }
286 #endif
287
288 /* Call the cpu specific abort fixup routine */
289 error = cpu_dataabt_fixup(frame);
290 if (error == ABORT_FIXUP_RETURN)
291 return;
292 if (error == ABORT_FIXUP_FAILED) {
293 printf("pc = 0x%08x, insn = ", fault_pc);
294 disassemble(fault_pc);
295 panic("data abort fixup failed\n");
296 }
297
298 #ifdef PMAP_DEBUG
299 if (pmap_debug_level >= 0)
300 printf("fault in process %p\n", p);
301 #endif
302
303 #ifdef DEBUG
304 /* Is this needed ? */
305 if (pcb != curpcb) {
306 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n",
307 pcb, curpcb);
308 printf("data_abort: Alert ! proc(%p), curproc(%p)\n",
309 p, curproc);
310 }
311 #endif /* DEBUG */
312
313 /* Were we in user mode when the abort occurred ? */
314 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
315 /*
316 * Note that the fault was from USR mode.
317 */
318 user = 1;
319 p->p_addr->u_pcb.pcb_tf = frame;
320 } else
321 user = 0;
322
323 /* Now act on the fault type */
324 switch (fault_code) {
325 case FAULT_WRTBUF_0: /* Write Buffer Fault */
326 case FAULT_WRTBUF_1: /* Write Buffer Fault */
327 /* If this happens forget it no point in continuing */
328
329 /* FALLTHROUGH */
330
331 case FAULT_ALIGN_0: /* Alignment Fault */
332 case FAULT_ALIGN_1: /* Alignment Fault */
333 /*
334 * Really this should just kill the process.
335 * Alignment faults are turned off in the kernel
336 * in order to get better performance from shorts with
337 * GCC so an alignment fault means somebody has played
338 * with the control register in the CPU. Might as well
339 * panic as the kernel was not compiled for aligned accesses.
340 */
341
342 /* FALLTHROUGH */
343
344 case FAULT_BUSERR_0: /* Bus Error LF Section */
345 case FAULT_BUSERR_1: /* Bus Error Page */
346 case FAULT_BUSERR_2: /* Bus Error Section */
347 case FAULT_BUSERR_3: /* Bus Error Page */
348 /* What will accutally cause a bus error ? */
349 /* Real bus errors are not a process problem but hardware */
350
351 /* FALLTHROUGH */
352
353 case FAULT_DOMAIN_S: /* Section Domain Error Fault */
354 case FAULT_DOMAIN_P: /* Page Domain Error Fault*/
355 /*
356 * Right well we dont use domains, everything is
357 * always a client and thus subject to access permissions.
358 * If we get a domain error then we have corrupts PTE's
359 * so we might as well die !
360 * I suppose eventually this should just kill the process
361 * who owns the PTE's but if this happens it implies a
362 * kernel problem.
363 */
364
365 /* FALLTHROUGH */
366
367 case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */
368 case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */
369 /*
370 * These faults imply that the PTE is corrupt.
371 * Likely to be a kernel fault so we had better stop.
372 */
373
374 /* FALLTHROUGH */
375
376 default :
377 /* Are there any combinations I have missed ? */
378 report_abort(NULL, fault_status, fault_address, fault_pc);
379
380 we_re_toast:
381 /*
382 * Were are dead, try and provide some debug
383 * information before dying.
384 */
385 #ifdef DDB
386 printf("Unhandled trap (frame = %p)\n", frame);
387 report_abort(NULL, fault_status, fault_address, fault_pc);
388 kdb_trap(-1, frame);
389 return;
390 #else
391 panic("Unhandled trap (frame = %p)", frame);
392 #endif /* DDB */
393
394 case FAULT_TRANS_P: /* Page Translation Fault */
395 case FAULT_PERM_P: /* Page Permission Fault */
396 case FAULT_TRANS_S: /* Section Translation Fault */
397 case FAULT_PERM_S: /* Section Permission Fault */
398 /*
399 * Page/section translation/permission fault -- need to fault in
400 * the page and possibly the page table page.
401 */
402 {
403 register vaddr_t va;
404 register struct vmspace *vm = p->p_vmspace;
405 register struct vm_map *map;
406 int rv;
407 vm_prot_t ftype;
408 extern struct vm_map *kernel_map;
409
410 va = trunc_page((vaddr_t)fault_address);
411
412 #ifdef PMAP_DEBUG
413 if (pmap_debug_level >= 0)
414 printf("page fault: addr=V%08lx ", va);
415 #endif
416
417 /*
418 * It is only a kernel address space fault iff:
419 * 1. user == 0 and
420 * 2. pcb_onfault not set or
421 * 3. pcb_onfault set but supervisor space fault
422 * The last can occur during an exec() copyin where the
423 * argument space is lazy-allocated.
424 */
425 if (!user &&
426 (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) {
427 /* Was the fault due to the FPE/IPKDB ? */
428 if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
429 report_abort("UND32", fault_status,
430 fault_address, fault_pc);
431 trapsignal(p, SIGSEGV, TRAP_CODE);
432
433 /*
434 * Force exit via userret()
435 * This is necessary as the FPE is an extension
436 * to userland that actually runs in a
437 * priveledged mode but uses USR mode
438 * permissions for its accesses.
439 */
440 userret(p);
441 return;
442 }
443 map = kernel_map;
444 } else
445 map = &vm->vm_map;
446
447 #ifdef PMAP_DEBUG
448 if (pmap_debug_level >= 0)
449 printf("vmmap=%p ", map);
450 #endif
451
452 if (map == NULL)
453 panic("No map for fault address\n");
454
455 /*
456 * We need to know whether the page should be mapped
457 * as R or R/W. The MMU does not give us the info as
458 * to whether the fault was caused by a read or a write.
459 * This means we need to disassemble the instruction
460 * responsible and determine if it was a read or write
461 * instruction.
462 */
463 /* STR instruction ? */
464 if ((fault_instruction & 0x0c100000) == 0x04000000)
465 ftype = VM_PROT_READ | VM_PROT_WRITE;
466 /* STM or CDT instruction ? */
467 else if ((fault_instruction & 0x0a100000) == 0x08000000)
468 ftype = VM_PROT_READ | VM_PROT_WRITE;
469 /* STRH, STRSH or STRSB instruction ? */
470 else if ((fault_instruction & 0x0e100090) == 0x00000090)
471 ftype = VM_PROT_READ | VM_PROT_WRITE;
472 /* SWP instruction ? */
473 else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
474 ftype = VM_PROT_READ | VM_PROT_WRITE;
475 else
476 ftype = VM_PROT_READ;
477
478 #ifdef PMAP_DEBUG
479 if (pmap_debug_level >= 0)
480 printf("fault protection = %d\n", ftype);
481 #endif
482
483 if ((ftype & VM_PROT_WRITE) ?
484 pmap_modified_emulation(map->pmap, va) :
485 pmap_handled_emulation(map->pmap, va))
486 goto out;
487
488 if (current_intr_depth > 0) {
489 #ifdef DDB
490 printf("Non-emulated page fault with intr_depth > 0\n");
491 report_abort(NULL, fault_status, fault_address, fault_pc);
492 kdb_trap(-1, frame);
493 return;
494 #else
495 panic("Fault with intr_depth > 0");
496 #endif /* DDB */
497 }
498
499 onfault = pcb->pcb_onfault;
500 pcb->pcb_onfault = NULL;
501 rv = uvm_fault(map, va, 0, ftype);
502 pcb->pcb_onfault = onfault;
503 if (rv == 0)
504 goto out;
505
506 if (user == 0) {
507 if (pcb->pcb_onfault)
508 goto copyfault;
509 printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
510 map, va, ftype, rv);
511 goto we_re_toast;
512 }
513
514 report_abort("", fault_status, fault_address, fault_pc);
515 if (rv == ENOMEM) {
516 printf("UVM: pid %d (%s), uid %d killed: "
517 "out of swap\n", p->p_pid, p->p_comm,
518 p->p_cred && p->p_ucred ?
519 p->p_ucred->cr_uid : -1);
520 trapsignal(p, SIGKILL, TRAP_CODE);
521 } else
522 trapsignal(p, SIGSEGV, TRAP_CODE);
523 break;
524 }
525 }
526
527 out:
528 /* Call userret() if it was a USR mode fault */
529 if (user)
530 userret(p);
531 }
532
533
534 /*
535 * void prefetch_abort_handler(trapframe_t *frame)
536 *
537 * Abort handler called when instruction execution occurs at
538 * a non existent or restricted (access permissions) memory page.
539 * If the address is invalid and we were in SVC mode then panic as
540 * the kernel should never prefetch abort.
541 * If the address is invalid and the page is mapped then the user process
542 * does no have read permission so send it a signal.
543 * Otherwise fault the page in and try again.
544 */
545
546 extern int kernel_debug;
547
548 void
549 prefetch_abort_handler(frame)
550 trapframe_t *frame;
551 {
552 register u_int fault_pc;
553 register struct proc *p;
554 register struct pcb *pcb;
555 u_int fault_instruction;
556 pt_entry_t *pte;
557 int error;
558
559 /*
560 * Enable IRQ's (disabled by the abort) This always comes
561 * from user mode so we know interrupts were not disabled.
562 * But we check anyway.
563 */
564 if (!(frame->tf_spsr & I32_bit))
565 enable_interrupts(I32_bit);
566
567 #ifdef DEBUG
568 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
569 panic("prefetch_abort_handler: not in SVC32 mode");
570 #endif
571
572 /* Update vmmeter statistics */
573 uvmexp.traps++;
574
575 /* Call the cpu specific abort fixup routine */
576 error = cpu_prefetchabt_fixup(frame);
577 if (error == ABORT_FIXUP_RETURN)
578 return;
579 if (error == ABORT_FIXUP_FAILED)
580 panic("prefetch abort fixup failed\n");
581
582 /* Get the current proc structure or proc0 if there is none */
583 if ((p = curproc) == 0) {
584 p = &proc0;
585 #ifdef DEBUG
586 printf("Prefetch abort with curproc == 0\n");
587 #endif
588 }
589
590 #ifdef PMAP_DEBUG
591 if (pmap_debug_level >= 0)
592 printf("prefetch fault in process %p %s\n", p, p->p_comm);
593 #endif
594 /*
595 * can't use curpcb, as it might be NULL; and we have p in a
596 * register anyway
597 */
598 pcb = &p->p_addr->u_pcb;
599 if (pcb == 0)
600 panic("prefetch_abort_handler: no pcb ... we're toast !\n");
601
602 #ifdef DEBUG
603 if (pcb != curpcb) {
604 printf("data_abort: Alert ! pcb(%p) != curpcb(%p)\n",
605 pcb, curpcb);
606 printf("data_abort: Alert ! proc(%p), curproc(%p)\n",
607 p, curproc);
608 }
609 #endif /* DEBUG */
610
611 /* Get fault address */
612 fault_pc = frame->tf_pc;
613
614 /* Was the prefectch abort from USR32 mode ? */
615 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
616 p->p_addr->u_pcb.pcb_tf = frame;
617 } else {
618 /*
619 * All the kernel code pages are loaded at boot time
620 * and do not get paged
621 */
622 panic("Prefetch abort in non-USR mode (frame=%p PC=0x%08x)\n",
623 frame, fault_pc);
624 }
625
626 #ifdef PMAP_DEBUG
627 if (pmap_debug_level >= 0)
628 printf("prefetch_abort: PC = %08x\n", fault_pc);
629 #endif
630 /* Ok validate the address, can only execute in USER space */
631 if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
632 #ifdef DEBUG
633 printf("prefetch: pc (%08x) not in user process space\n",
634 fault_pc);
635 #endif
636 trapsignal(p, SIGSEGV, fault_pc);
637 userret(p);
638 return;
639 }
640
641 /* Is the page already mapped ? */
642 /* This is debugging for rev K SA110 silicon */
643 pte = pmap_pte(p->p_vmspace->vm_map.pmap, (vaddr_t)fault_pc);
644 if (pte && *pte != 0) {
645 if (kernel_debug & 1) {
646 printf("prefetch_abort: page is already mapped - pte=%p *pte=%08x\n",
647 pte, *pte);
648 printf("prefetch_abort: pc=%08x proc=%p process=%s\n", fault_pc, p, p->p_comm);
649 printf("prefetch_abort: far=%08x fs=%x\n", cpu_faultaddress(), cpu_faultstatus());
650 printf("prefetch_abort: trapframe=%08x\n", (u_int)frame);
651 }
652 #ifdef DDB
653 if (kernel_debug & 2)
654 Debugger();
655 #endif
656 }
657
658 /* Ok read the fault address. This will fault the page in for us */
659 if (fetchuserword(fault_pc, &fault_instruction) != 0) {
660 #ifdef DEBUG
661 printf("prefetch: faultin failed for address %08x\n",
662 fault_pc);
663 #endif
664 trapsignal(p, SIGSEGV, fault_pc);
665 } else {
666
667 #ifdef DIAGNOSTIC
668 /* More debug stuff */
669
670 #ifdef PMAP_DEBUG
671 if (pmap_debug_level >= 0) {
672 printf("Instruction @V%08x = %08x\n", fault_pc,
673 fault_instruction);
674 disassemble(fault_pc);
675 printf("return addr=%08x", frame->tf_pc);
676 pte = pmap_pte(p->p_vmspace->vm_map.pmap,
677 (vaddr_t)fault_pc);
678 if (pte)
679 printf(" pte=%p *pte=%08x\n", pte, *pte);
680 else
681 printf("\n");
682
683 }
684 #endif /* PMAP_DEBUG */
685 #endif /* DIAGNOSTIC */
686 }
687
688 userret(p);
689 }
690
691 int
692 cowfault(va)
693 vaddr_t va;
694 {
695 struct vmspace *vm;
696 int error;
697
698 if (va >= VM_MAXUSER_ADDRESS)
699 return (EFAULT);
700
701 /* uvm_fault can't be called from within an interrupt */
702 KASSERT(current_intr_depth == 0);
703
704 vm = curproc->p_vmspace;
705 error = uvm_fault(&vm->vm_map, va, 0, VM_PROT_READ | VM_PROT_WRITE);
706 return error;
707 }
708
709 /* End of fault.c */
710