fault.c revision 1.17 1 /* $NetBSD: fault.c,v 1.17 2002/04/04 12:39:55 skrll 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_cputypes.h"
47 #include "opt_ddb.h"
48 #include "opt_pmap_debug.h"
49
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/proc.h>
54 #include <sys/user.h>
55 #include <sys/kernel.h>
56
57 #include <uvm/uvm_extern.h>
58
59 #include <machine/frame.h>
60 #include <arm/arm32/katelib.h>
61 #include <machine/cpu.h>
62 #include <machine/intr.h>
63 #ifdef DDB
64 #include <machine/db_machdep.h>
65 #endif
66
67 #include <arch/arm/arm/disassem.h>
68 #include <arm/arm32/machdep.h>
69
70 int cowfault __P((vaddr_t));
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, opcode 0x%08x, insn = ", fault_pc, *((u_int *)fault_pc));
294 disassemble(fault_pc);
295 printf("data abort handler: fixup failed for this instruction\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 /* check if this was a failed fixup */
324 if (error == ABORT_FIXUP_FAILED) {
325 if (user) {
326 trapsignal(p, SIGSEGV, TRAP_CODE);
327 userret(p);
328 return;
329 };
330 panic("Data abort fixup failed in kernel - we're dead\n");
331 };
332
333 /* Now act on the fault type */
334 switch (fault_code) {
335 case FAULT_WRTBUF_0: /* Write Buffer Fault */
336 case FAULT_WRTBUF_1: /* Write Buffer Fault */
337 /* If this happens forget it no point in continuing */
338
339 /* FALLTHROUGH */
340
341 case FAULT_ALIGN_0: /* Alignment Fault */
342 case FAULT_ALIGN_1: /* Alignment Fault */
343 /*
344 * Really this should just kill the process.
345 * Alignment faults are turned off in the kernel
346 * in order to get better performance from shorts with
347 * GCC so an alignment fault means somebody has played
348 * with the control register in the CPU. Might as well
349 * panic as the kernel was not compiled for aligned accesses.
350 */
351
352 /* FALLTHROUGH */
353
354 case FAULT_BUSERR_0: /* Bus Error LF Section */
355 case FAULT_BUSERR_1: /* Bus Error Page */
356 case FAULT_BUSERR_2: /* Bus Error Section */
357 case FAULT_BUSERR_3: /* Bus Error Page */
358 /* What will accutally cause a bus error ? */
359 /* Real bus errors are not a process problem but hardware */
360
361 /* FALLTHROUGH */
362
363 case FAULT_DOMAIN_S: /* Section Domain Error Fault */
364 case FAULT_DOMAIN_P: /* Page Domain Error Fault*/
365 /*
366 * Right well we dont use domains, everything is
367 * always a client and thus subject to access permissions.
368 * If we get a domain error then we have corrupts PTE's
369 * so we might as well die !
370 * I suppose eventually this should just kill the process
371 * who owns the PTE's but if this happens it implies a
372 * kernel problem.
373 */
374
375 /* FALLTHROUGH */
376
377 case FAULT_BUSTRNL1: /* Bus Error Trans L1 Fault */
378 case FAULT_BUSTRNL2: /* Bus Error Trans L2 Fault */
379 /*
380 * These faults imply that the PTE is corrupt.
381 * Likely to be a kernel fault so we had better stop.
382 */
383
384 /* FALLTHROUGH */
385
386 default :
387 /* Are there any combinations I have missed ? */
388 report_abort(NULL, fault_status, fault_address, fault_pc);
389
390 we_re_toast:
391 /*
392 * Were are dead, try and provide some debug
393 * information before dying.
394 */
395 #ifdef DDB
396 printf("Unhandled trap (frame = %p)\n", frame);
397 report_abort(NULL, fault_status, fault_address, fault_pc);
398 kdb_trap(-1, frame);
399 return;
400 #else
401 panic("Unhandled trap (frame = %p)", frame);
402 #endif /* DDB */
403
404 case FAULT_TRANS_P: /* Page Translation Fault */
405 case FAULT_PERM_P: /* Page Permission Fault */
406 case FAULT_TRANS_S: /* Section Translation Fault */
407 case FAULT_PERM_S: /* Section Permission Fault */
408 /*
409 * Page/section translation/permission fault -- need to fault in
410 * the page and possibly the page table page.
411 */
412 {
413 register vaddr_t va;
414 register struct vmspace *vm = p->p_vmspace;
415 register struct vm_map *map;
416 int rv;
417 vm_prot_t ftype;
418 extern struct vm_map *kernel_map;
419
420 va = trunc_page((vaddr_t)fault_address);
421
422 #ifdef PMAP_DEBUG
423 if (pmap_debug_level >= 0)
424 printf("page fault: addr=V%08lx ", va);
425 #endif
426
427 /*
428 * It is only a kernel address space fault iff:
429 * 1. user == 0 and
430 * 2. pcb_onfault not set or
431 * 3. pcb_onfault set but supervisor space fault
432 * The last can occur during an exec() copyin where the
433 * argument space is lazy-allocated.
434 */
435 if (!user &&
436 (va >= VM_MIN_KERNEL_ADDRESS || va < VM_MIN_ADDRESS)) {
437 /* Was the fault due to the FPE/IPKDB ? */
438 if ((frame->tf_spsr & PSR_MODE) == PSR_UND32_MODE) {
439 report_abort("UND32", fault_status,
440 fault_address, fault_pc);
441 trapsignal(p, SIGSEGV, TRAP_CODE);
442
443 /*
444 * Force exit via userret()
445 * This is necessary as the FPE is an extension
446 * to userland that actually runs in a
447 * priveledged mode but uses USR mode
448 * permissions for its accesses.
449 */
450 userret(p);
451 return;
452 }
453 map = kernel_map;
454 } else
455 map = &vm->vm_map;
456
457 #ifdef PMAP_DEBUG
458 if (pmap_debug_level >= 0)
459 printf("vmmap=%p ", map);
460 #endif
461
462 if (map == NULL)
463 panic("No map for fault address va = 0x%08lx", va);
464
465 /*
466 * We need to know whether the page should be mapped
467 * as R or R/W. The MMU does not give us the info as
468 * to whether the fault was caused by a read or a write.
469 * This means we need to disassemble the instruction
470 * responsible and determine if it was a read or write
471 * instruction.
472 */
473 /* STR instruction ? */
474 if ((fault_instruction & 0x0c100000) == 0x04000000)
475 ftype = VM_PROT_WRITE;
476 /* STM or CDT instruction ? */
477 else if ((fault_instruction & 0x0a100000) == 0x08000000)
478 ftype = VM_PROT_WRITE;
479 /* STRH, STRSH or STRSB instruction ? */
480 else if ((fault_instruction & 0x0e100090) == 0x00000090)
481 ftype = VM_PROT_WRITE;
482 /* SWP instruction ? */
483 else if ((fault_instruction & 0x0fb00ff0) == 0x01000090)
484 ftype = VM_PROT_READ | VM_PROT_WRITE;
485 else
486 ftype = VM_PROT_READ;
487
488 #ifdef PMAP_DEBUG
489 if (pmap_debug_level >= 0)
490 printf("fault protection = %d\n", ftype);
491 #endif
492
493 if ((ftype & VM_PROT_WRITE) ?
494 pmap_modified_emulation(map->pmap, va) :
495 pmap_handled_emulation(map->pmap, va))
496 goto out;
497
498 if (current_intr_depth > 0) {
499 #ifdef DDB
500 printf("Non-emulated page fault with intr_depth > 0\n");
501 report_abort(NULL, fault_status, fault_address, fault_pc);
502 kdb_trap(-1, frame);
503 return;
504 #else
505 panic("Fault with intr_depth > 0");
506 #endif /* DDB */
507 }
508
509 onfault = pcb->pcb_onfault;
510 pcb->pcb_onfault = NULL;
511 rv = uvm_fault(map, va, 0, ftype);
512 pcb->pcb_onfault = onfault;
513 if (rv == 0)
514 goto out;
515
516 if (user == 0) {
517 if (pcb->pcb_onfault)
518 goto copyfault;
519 printf("[u]vm_fault(%p, %lx, %x, 0) -> %x\n",
520 map, va, ftype, rv);
521 goto we_re_toast;
522 }
523
524 report_abort("", fault_status, fault_address, fault_pc);
525 if (rv == ENOMEM) {
526 printf("UVM: pid %d (%s), uid %d killed: "
527 "out of swap\n", p->p_pid, p->p_comm,
528 p->p_cred && p->p_ucred ?
529 p->p_ucred->cr_uid : -1);
530 trapsignal(p, SIGKILL, TRAP_CODE);
531 } else
532 trapsignal(p, SIGSEGV, TRAP_CODE);
533 break;
534 }
535 }
536
537 out:
538 /* Call userret() if it was a USR mode fault */
539 if (user)
540 userret(p);
541 }
542
543
544 /*
545 * void prefetch_abort_handler(trapframe_t *frame)
546 *
547 * Abort handler called when instruction execution occurs at
548 * a non existent or restricted (access permissions) memory page.
549 * If the address is invalid and we were in SVC mode then panic as
550 * the kernel should never prefetch abort.
551 * If the address is invalid and the page is mapped then the user process
552 * does no have read permission so send it a signal.
553 * Otherwise fault the page in and try again.
554 */
555
556 extern int kernel_debug;
557
558 void
559 prefetch_abort_handler(frame)
560 trapframe_t *frame;
561 {
562 struct proc *p;
563 struct vm_map *map;
564 vaddr_t fault_pc, va;
565 int error;
566
567 /*
568 * Enable IRQ's (disabled by the abort) This always comes
569 * from user mode so we know interrupts were not disabled.
570 * But we check anyway.
571 */
572 if (!(frame->tf_spsr & I32_bit))
573 enable_interrupts(I32_bit);
574
575 #ifdef DEBUG
576 if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE)
577 panic("prefetch_abort_handler: not in SVC32 mode");
578 #endif
579
580 /* Update vmmeter statistics */
581 uvmexp.traps++;
582
583 /* Call the cpu specific abort fixup routine */
584 error = cpu_prefetchabt_fixup(frame);
585 if (error == ABORT_FIXUP_RETURN)
586 return;
587 if (error == ABORT_FIXUP_FAILED)
588 panic("prefetch abort fixup failed\n");
589
590 /* Get the current proc structure or proc0 if there is none */
591 if ((p = curproc) == 0) {
592 p = &proc0;
593 #ifdef DEBUG
594 printf("Prefetch abort with curproc == 0\n");
595 #endif
596 }
597
598 #ifdef PMAP_DEBUG
599 if (pmap_debug_level >= 0)
600 printf("prefetch fault in process %p %s\n", p, p->p_comm);
601 #endif
602
603 /* Get fault address */
604 fault_pc = frame->tf_pc;
605 va = trunc_page(fault_pc);
606
607 /* Was the prefectch abort from USR32 mode ? */
608 if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
609 p->p_addr->u_pcb.pcb_tf = frame;
610 } else {
611 /*
612 * All the kernel code pages are loaded at boot time
613 * and do not get paged
614 */
615 panic("Prefetch abort in non-USR mode (frame=%p PC=0x%08lx)\n",
616 frame, fault_pc);
617 }
618
619 map = &p->p_vmspace->vm_map;
620
621 #ifdef PMAP_DEBUG
622 if (pmap_debug_level >= 0)
623 printf("prefetch_abort: PC = %08lx\n", fault_pc);
624 #endif
625 /* Ok validate the address, can only execute in USER space */
626 if (fault_pc < VM_MIN_ADDRESS || fault_pc >= VM_MAXUSER_ADDRESS) {
627 #ifdef DEBUG
628 printf("prefetch: pc (%08x) not in user process space\n",
629 fault_pc);
630 #endif
631 trapsignal(p, SIGSEGV, fault_pc);
632 userret(p);
633 return;
634 }
635
636 #ifdef CPU_SA110
637 /*
638 * There are bugs in the rev K SA110. This is a check for one
639 * of them.
640 */
641 if (curcpu()->ci_cputype == CPU_ID_SA110 && curcpu()->ci_cpurev < 3) {
642 /* Always current pmap */
643 pt_entry_t *pte = vtopte((vaddr_t) fault_pc);
644 struct pmap *pmap = p->p_vmspace->vm_map.pmap;
645
646 if (pmap_pde_v(pmap_pde(pmap, (vaddr_t) fault_pc)) &&
647 pmap_pte_v(pte)) {
648 if (kernel_debug & 1) {
649 printf("prefetch_abort: page is already "
650 "mapped - pte=%p *pte=%08x\n", pte, *pte);
651 printf("prefetch_abort: pc=%08lx proc=%p "
652 "process=%s\n", fault_pc, p, p->p_comm);
653 printf("prefetch_abort: far=%08x fs=%x\n",
654 cpu_faultaddress(), cpu_faultstatus());
655 printf("prefetch_abort: trapframe=%08x\n",
656 (u_int)frame);
657 }
658 #ifdef DDB
659 if (kernel_debug & 2)
660 Debugger();
661 #endif
662 }
663 }
664 #endif /* CPU_SA110 */
665
666 if (pmap_handled_emulation(map->pmap, va))
667 goto out;
668
669 if (current_intr_depth > 0) {
670 #ifdef DDB
671 printf("Non-emulated prefetch abort with intr_depth > 0\n");
672 kdb_trap(-1, frame);
673 return;
674 #else
675 panic("Prefetch Abort with intr_depth > 0");
676 #endif
677 }
678
679 error = uvm_fault(map, va, 0, VM_PROT_READ);
680 if (error == 0)
681 goto out;
682
683 if (error == ENOMEM) {
684 printf("UVM: pid %d (%s), uid %d killed: "
685 "out of swap\n", p->p_pid, p->p_comm,
686 p->p_cred && p->p_ucred ?
687 p->p_ucred->cr_uid : -1);
688 trapsignal(p, SIGKILL, fault_pc);
689 } else
690 trapsignal(p, SIGSEGV, fault_pc);
691 out:
692 userret(p);
693 }
694
695 int
696 cowfault(va)
697 vaddr_t va;
698 {
699 struct vmspace *vm;
700 int error;
701
702 if (va >= VM_MAXUSER_ADDRESS)
703 return (EFAULT);
704
705 /* uvm_fault can't be called from within an interrupt */
706 KASSERT(current_intr_depth == 0);
707
708 vm = curproc->p_vmspace;
709 error = uvm_fault(&vm->vm_map, va, 0, VM_PROT_WRITE);
710 return error;
711 }
712