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