2 * Copyright (c) 2001, Jake Burkholder
3 * Copyright (C) 1994, David Greenman
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * the University of Utah, and William Jolitz.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * from: @(#)trap.c 7.4 (Berkeley) 5/13/91
35 * from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
41 #include "opt_ktrace.h"
43 #include <sys/param.h>
45 #include <sys/kernel.h>
47 #include <sys/interrupt.h>
50 #include <sys/mutex.h>
51 #include <sys/systm.h>
52 #include <sys/pioctl.h>
53 #include <sys/ptrace.h>
56 #include <sys/signalvar.h>
57 #include <sys/syscall.h>
58 #include <sys/sysctl.h>
59 #include <sys/sysent.h>
60 #include <sys/vmmeter.h>
63 #include <sys/ktrace.h>
66 #include <dev/ofw/openfirm.h>
70 #include <vm/vm_extern.h>
71 #include <vm/vm_param.h>
72 #include <vm/vm_kern.h>
73 #include <vm/vm_map.h>
74 #include <vm/vm_page.h>
76 #include <machine/clock.h>
77 #include <machine/cpu.h>
78 #include <machine/frame.h>
79 #include <machine/intr_machdep.h>
80 #include <machine/pcb.h>
81 #include <machine/smp.h>
82 #include <machine/trap.h>
83 #include <machine/tstate.h>
84 #include <machine/tte.h>
85 #include <machine/tlb.h>
86 #include <machine/tsb.h>
87 #include <machine/watch.h>
88 #include <machine/wstate.h>
90 #include <machine/md_var.h>
91 #include <machine/hypervisorvar.h>
93 #include <security/audit/audit.h>
95 void trap(struct trapframe *tf, int64_t type, uint64_t data);
96 void syscall(struct trapframe *tf);
98 extern vm_paddr_t mmu_fault_status_area;
100 static int trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data);
102 extern char copy_fault[];
103 extern char copy_nofault_begin[];
104 extern char copy_nofault_end[];
106 extern char fs_fault[];
107 extern char fs_nofault_begin[];
108 extern char fs_nofault_end[];
109 extern char fs_nofault_intr_begin[];
110 extern char fs_nofault_intr_end[];
112 extern char fas_fault[];
113 extern char fas_nofault_begin[];
114 extern char fas_nofault_end[];
116 const char *const trap_msg[] = {
118 "instruction access exception",
119 "instruction access error",
120 "instruction access protection",
121 "illtrap instruction",
122 "illegal instruction",
124 "floating point disabled",
125 "floating point exception ieee 754",
126 "floating point exception other",
129 "data access exception",
131 "data access protection",
132 "memory address not aligned",
135 "trap instruction 16",
136 "trap instruction 17",
137 "trap instruction 18",
138 "trap instruction 19",
139 "trap instruction 20",
140 "trap instruction 21",
141 "trap instruction 22",
142 "trap instruction 23",
143 "trap instruction 24",
144 "trap instruction 25",
145 "trap instruction 26",
146 "trap instruction 27",
147 "trap instruction 28",
148 "trap instruction 29",
149 "trap instruction 30",
150 "trap instruction 31",
151 "fast instruction access mmu miss",
152 "fast data access mmu miss",
154 "physical address watchpoint",
155 "virtual address watchpoint",
156 "corrected ecc error",
166 "restore physical watchpoint",
167 "restore virtual watchpoint",
168 "kernel stack fault",
173 const int trap_sig[] = {
174 SIGILL, /* reserved */
175 SIGILL, /* instruction access exception */
176 SIGILL, /* instruction access error */
177 SIGILL, /* instruction access protection */
178 SIGILL, /* illtrap instruction */
179 SIGILL, /* illegal instruction */
180 SIGBUS, /* privileged opcode */
181 SIGFPE, /* floating point disabled */
182 SIGFPE, /* floating point exception ieee 754 */
183 SIGFPE, /* floating point exception other */
184 SIGEMT, /* tag overflow */
185 SIGFPE, /* division by zero */
186 SIGILL, /* data access exception */
187 SIGILL, /* data access error */
188 SIGBUS, /* data access protection */
189 SIGBUS, /* memory address not aligned */
190 SIGBUS, /* privileged action */
191 SIGBUS, /* async data error */
192 SIGILL, /* trap instruction 16 */
193 SIGILL, /* trap instruction 17 */
194 SIGILL, /* trap instruction 18 */
195 SIGILL, /* trap instruction 19 */
196 SIGILL, /* trap instruction 20 */
197 SIGILL, /* trap instruction 21 */
198 SIGILL, /* trap instruction 22 */
199 SIGILL, /* trap instruction 23 */
200 SIGILL, /* trap instruction 24 */
201 SIGILL, /* trap instruction 25 */
202 SIGILL, /* trap instruction 26 */
203 SIGILL, /* trap instruction 27 */
204 SIGILL, /* trap instruction 28 */
205 SIGILL, /* trap instruction 29 */
206 SIGILL, /* trap instruction 30 */
207 SIGILL, /* trap instruction 31 */
208 SIGFPE, /* floating point error */
209 SIGSEGV, /* fast data access mmu miss */
211 -1, /* physical address watchpoint */
212 -1, /* virtual address watchpoint */
213 -1, /* corrected ecc error */
217 SIGTRAP, /* breakpoint */
218 SIGILL, /* clean window */
219 SIGILL, /* range check */
220 SIGILL, /* fix alignment */
221 SIGILL, /* integer overflow */
222 SIGSYS, /* syscall */
223 -1, /* restore physical watchpoint */
224 -1, /* restore virtual watchpoint */
225 -1, /* kernel stack fault */
228 CTASSERT(sizeof(struct trapframe) == 256);
230 int debugger_on_signal = 0;
232 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
233 &debugger_on_signal, 0, "");
237 * This interface allows the client to safely take over the %tba by
238 * the prom's service. The prom will take care of the quiescence of
239 * interrupts and handle any pending soft interrupts.
240 * This call also sets the MMU fault status area for the CPU.
243 set_mmfsa_traptable(void *tba_addr, uint64_t mmfsa_ra)
252 (cell_t)"SUNW,set-trap-table",
256 args.tba_addr = (cell_t)tba_addr;
257 args.mmfsa_ra = mmfsa_ra;
266 mmfsa = mmu_fault_status_area + (MMFSA_SIZE*curcpu);
268 set_wstate(WSTATE_KERN);
269 set_mmfsa_scratchpad(mmfsa);
272 set_mmfsa_traptable(&tl0_base, mmfsa);
276 trap(struct trapframe *tf, int64_t type, uint64_t data)
287 CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
289 (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
291 PCPU_INC(cnt.v_trap);
293 trapno = (type & TRAP_MASK);
294 ctx = (type >> TRAP_CTX_SHIFT);
296 if (((tf->tf_tstate & TSTATE_PRIV) == 0) || (ctx != 0)) {
297 KASSERT(td != NULL, ("trap: curthread NULL"));
298 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
304 if (td->td_ucred != p->p_ucred)
305 cred_update_thread(td);
309 case T_DATA_PROTECTION:
310 addr = TLB_TAR_VA(data);
311 case T_INSTRUCTION_MISS:
312 sig = trap_pfault(td, tf, trapno, data);
315 sig = rwindow_load(td, tf, 2);
318 sig = rwindow_load(td, tf, 1);
321 sig = rwindow_save(td);
323 case T_DATA_EXCEPTION:
325 case T_MEM_ADDRESS_NOT_ALIGNED:
326 printf("bad trap trapno=%ld data=0x%lx pc=0x%lx\n",
327 trapno, data, tf->tf_tpc);
328 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
329 tf->tf_tpc <= (u_long)copy_nofault_end) {
330 tf->tf_tpc = (u_long)copy_fault;
331 tf->tf_tnpc = tf->tf_tpc + 4;
335 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
336 tf->tf_tpc <= (u_long)fs_nofault_end) {
337 tf->tf_tpc = (u_long)fs_fault;
338 tf->tf_tnpc = tf->tf_tpc + 4;
344 sig = trap_sig[trapno];
348 if (trapno < 0 || trapno >= T_MAX ||
349 trap_sig[trapno] == -1)
350 panic("trap: bad trap type");
351 sig = trap_sig[trapno];
356 /* Translate fault for emulators. */
357 if (p->p_sysent->sv_transtrap != NULL) {
358 sig = p->p_sysent->sv_transtrap(sig,
361 if (debugger_on_signal &&
362 (sig == 4 || sig == 10 || sig == 11))
363 kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
365 if (sig == 4 || sig == 10 || sig == 11)
366 printf("trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d sig=%d proc=%s\n",
367 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu, sig, curthread->td_name);
369 /* XXX I've renumbered the traps to largely reflect what the hardware uses
370 * so this will need to be re-visited
372 ksiginfo_init_trap(&ksi);
374 ksi.ksi_code = (int)trapno; /* XXX not POSIX */
375 ksi.ksi_addr = (void *)addr;
376 ksi.ksi_trapno = (int)trapno;
377 trapsignal(td, &ksi);
381 mtx_assert(&Giant, MA_NOTOWNED);
383 KASSERT((type & T_KERNEL) != 0,
384 ("trap: kernel trap isn't - trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d\n",
385 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu));
395 error = (kdb_trap(trapno, 0, tf) == 0);
399 case T_DATA_PROTECTION:
400 case T_INSTRUCTION_MISS:
401 error = trap_pfault(td, tf, trapno, data);
403 case T_DATA_EXCEPTION:
404 printf("data exception on 0x%lx at 0x%lx\n", data, tf->tf_tpc);
405 printf("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx\n", trapno,
406 trap_msg[trapno], data, tf->tf_tpc, tf->tf_tnpc);
407 case T_ILLEGAL_INSTRUCTION:
408 if (tf->tf_tpc > KERNBASE) {
409 printf("illinstr: 0x%lx\n", tf->tf_tpc);
410 printf("illinstr: 0x%x\n", *((uint32_t *)tf->tf_tpc));
414 if (tf->tf_asi == ASI_AIUS) {
415 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
416 tf->tf_tpc <= (u_long)copy_nofault_end) {
417 tf->tf_tpc = (u_long)copy_fault;
418 tf->tf_tnpc = tf->tf_tpc + 4;
423 printf("ASI_AIUS but bad tpc\n");
425 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
426 tf->tf_tpc <= (u_long)fs_nofault_end) {
427 tf->tf_tpc = (u_long)fs_fault;
428 tf->tf_tnpc = tf->tf_tpc + 4;
432 printf("asi=0x%lx\n", tf->tf_asi);
436 printf("unchecked trap 0x%lx asi=0x%lx\n", trapno, tf->tf_asi);
442 panic("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx error=%d asi=0x%lx",
443 trapno, trap_msg[trapno], data, tf->tf_tpc,
444 tf->tf_tnpc, error, tf->tf_asi);
446 CTR1(KTR_TRAP, "trap: td=%p return", td);
450 trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data)
466 ctx = TLB_TAR_CTX(data);
467 type = type & ~T_KERNEL;
468 va = TLB_TAR_VA(data);
471 if (data > VM_MIN_DIRECT_ADDRESS)
472 printf("trap_pfault(type=%ld, data=0x%lx, tpc=0x%lx, ctx=0x%lx)\n",
473 type, data, tf->tf_tpc, ctx);
476 CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
477 td, p->p_vmspace->vm_pmap.pm_context, va, ctx);
479 KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
480 KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
481 KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
484 if (type == T_DATA_PROTECTION) {
485 prot = VM_PROT_WRITE;
486 flags = VM_FAULT_DIRTY;
488 if (type == T_DATA_MISS)
491 prot = VM_PROT_READ | VM_PROT_EXECUTE;
492 flags = VM_FAULT_NORMAL;
495 if (ctx != TLB_CTX_KERNEL) {
496 if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
497 (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
498 tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
499 tf->tf_tpc = (u_long)fs_fault;
500 tf->tf_tnpc = tf->tf_tpc + 4;
505 * This is a fault on non-kernel virtual memory.
510 * Keep swapout from messing with us during this
517 /* Fault in the user page. */
518 rv = vm_fault(&vm->vm_map, va, prot, flags);
521 * Now the process can be swapped again.
528 * This is a fault on kernel virtual memory. Attempts to
529 * access kernel memory from user mode cause privileged
530 * action traps, not page fault.
532 KASSERT(tf->tf_tstate & TSTATE_PRIV,
533 ("trap_pfault: fault on nucleus context from user mode"));
536 * Don't have to worry about process locking or stacks in the
539 rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
542 CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
544 if (rv == KERN_SUCCESS)
546 if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
547 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
548 tf->tf_tpc <= (u_long)fs_nofault_end) {
549 tf->tf_tpc = (u_long)fs_fault;
550 tf->tf_tnpc = tf->tf_tpc + 4;
553 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
554 tf->tf_tpc <= (u_long)copy_nofault_end) {
555 tf->tf_tpc = (u_long)copy_fault;
556 tf->tf_tnpc = tf->tf_tpc + 4;
560 return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
563 /* Maximum number of arguments that can be passed via the out registers. */
564 #define REG_MAXARGS 6
567 cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
569 struct trapframe *tf;
579 regcnt = REG_MAXARGS;
581 sa->code = tf->tf_global[1];
583 if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
584 sa->code = tf->tf_out[reg++];
588 if (p->p_sysent->sv_mask)
589 sa->code &= p->p_sysent->sv_mask;
590 if (sa->code >= p->p_sysent->sv_size)
591 sa->callp = &p->p_sysent->sv_table[0];
593 sa->callp = &p->p_sysent->sv_table[sa->code];
595 sa->narg = sa->callp->sy_narg;
596 KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
597 ("Too many syscall arguments!"));
600 bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
601 if (sa->narg > regcnt)
602 error = copyin((void *)(tf->tf_out[6] + SPOFF +
603 offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
604 (sa->narg - regcnt) * sizeof(sa->args[0]));
606 td->td_retval[0] = 0;
607 td->td_retval[1] = 0;
613 #include "../../kern/subr_syscall.c"
616 * Syscall handler. The arguments to the syscall are passed in the o registers
617 * by the caller, and are saved in the trap frame. The syscall number is passed
618 * in %g1 (and also saved in the trap frame).
621 syscall(struct trapframe *tf)
624 struct syscall_args sa;
630 KASSERT(td != NULL, ("trap: curthread NULL"));
631 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
634 * For syscalls, we don't want to retry the faulting instruction
635 * (usually), instead we need to advance one instruction.
637 td->td_pcb->pcb_tpc = tf->tf_tpc;
640 error = syscallenter(td, &sa);
641 syscallret(td, error, &sa);