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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * from: @(#)trap.c 7.4 (Berkeley) 5/13/91
39 * from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
45 #include "opt_ktrace.h"
47 #include <sys/param.h>
49 #include <sys/kernel.h>
51 #include <sys/interrupt.h>
54 #include <sys/mutex.h>
55 #include <sys/systm.h>
56 #include <sys/pioctl.h>
57 #include <sys/ptrace.h>
60 #include <sys/signalvar.h>
61 #include <sys/syscall.h>
62 #include <sys/sysctl.h>
63 #include <sys/sysent.h>
64 #include <sys/vmmeter.h>
67 #include <sys/ktrace.h>
70 #include <dev/ofw/openfirm.h>
74 #include <vm/vm_extern.h>
75 #include <vm/vm_param.h>
76 #include <vm/vm_kern.h>
77 #include <vm/vm_map.h>
78 #include <vm/vm_page.h>
80 #include <machine/clock.h>
81 #include <machine/cpu.h>
82 #include <machine/frame.h>
83 #include <machine/intr_machdep.h>
84 #include <machine/pcb.h>
85 #include <machine/smp.h>
86 #include <machine/trap.h>
87 #include <machine/tstate.h>
88 #include <machine/tte.h>
89 #include <machine/tlb.h>
90 #include <machine/tsb.h>
91 #include <machine/watch.h>
92 #include <machine/wstate.h>
94 #include <machine/md_var.h>
95 #include <machine/hypervisorvar.h>
97 #include <security/audit/audit.h>
99 void trap(struct trapframe *tf, int64_t type, uint64_t data);
100 void syscall(struct trapframe *tf);
102 extern vm_paddr_t mmu_fault_status_area;
104 static int trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data);
106 extern char copy_fault[];
107 extern char copy_nofault_begin[];
108 extern char copy_nofault_end[];
110 extern char fs_fault[];
111 extern char fs_nofault_begin[];
112 extern char fs_nofault_end[];
113 extern char fs_nofault_intr_begin[];
114 extern char fs_nofault_intr_end[];
116 extern char fas_fault[];
117 extern char fas_nofault_begin[];
118 extern char fas_nofault_end[];
120 const char *const trap_msg[] = {
122 "instruction access exception",
123 "instruction access error",
124 "instruction access protection",
125 "illtrap instruction",
126 "illegal instruction",
128 "floating point disabled",
129 "floating point exception ieee 754",
130 "floating point exception other",
133 "data access exception",
135 "data access protection",
136 "memory address not aligned",
139 "trap instruction 16",
140 "trap instruction 17",
141 "trap instruction 18",
142 "trap instruction 19",
143 "trap instruction 20",
144 "trap instruction 21",
145 "trap instruction 22",
146 "trap instruction 23",
147 "trap instruction 24",
148 "trap instruction 25",
149 "trap instruction 26",
150 "trap instruction 27",
151 "trap instruction 28",
152 "trap instruction 29",
153 "trap instruction 30",
154 "trap instruction 31",
155 "fast instruction access mmu miss",
156 "fast data access mmu miss",
158 "physical address watchpoint",
159 "virtual address watchpoint",
160 "corrected ecc error",
170 "restore physical watchpoint",
171 "restore virtual watchpoint",
172 "kernel stack fault",
177 const int trap_sig[] = {
178 SIGILL, /* reserved */
179 SIGILL, /* instruction access exception */
180 SIGILL, /* instruction access error */
181 SIGILL, /* instruction access protection */
182 SIGILL, /* illtrap instruction */
183 SIGILL, /* illegal instruction */
184 SIGBUS, /* privileged opcode */
185 SIGFPE, /* floating point disabled */
186 SIGFPE, /* floating point exception ieee 754 */
187 SIGFPE, /* floating point exception other */
188 SIGEMT, /* tag overflow */
189 SIGFPE, /* division by zero */
190 SIGILL, /* data access exception */
191 SIGILL, /* data access error */
192 SIGBUS, /* data access protection */
193 SIGBUS, /* memory address not aligned */
194 SIGBUS, /* privileged action */
195 SIGBUS, /* async data error */
196 SIGILL, /* trap instruction 16 */
197 SIGILL, /* trap instruction 17 */
198 SIGILL, /* trap instruction 18 */
199 SIGILL, /* trap instruction 19 */
200 SIGILL, /* trap instruction 20 */
201 SIGILL, /* trap instruction 21 */
202 SIGILL, /* trap instruction 22 */
203 SIGILL, /* trap instruction 23 */
204 SIGILL, /* trap instruction 24 */
205 SIGILL, /* trap instruction 25 */
206 SIGILL, /* trap instruction 26 */
207 SIGILL, /* trap instruction 27 */
208 SIGILL, /* trap instruction 28 */
209 SIGILL, /* trap instruction 29 */
210 SIGILL, /* trap instruction 30 */
211 SIGILL, /* trap instruction 31 */
212 SIGFPE, /* floating point error */
213 SIGSEGV, /* fast data access mmu miss */
215 -1, /* physical address watchpoint */
216 -1, /* virtual address watchpoint */
217 -1, /* corrected ecc error */
221 SIGTRAP, /* breakpoint */
222 SIGILL, /* clean window */
223 SIGILL, /* range check */
224 SIGILL, /* fix alignment */
225 SIGILL, /* integer overflow */
226 SIGSYS, /* syscall */
227 -1, /* restore physical watchpoint */
228 -1, /* restore virtual watchpoint */
229 -1, /* kernel stack fault */
232 CTASSERT(sizeof(struct trapframe) == 256);
234 int debugger_on_signal = 0;
236 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
237 &debugger_on_signal, 0, "");
241 * This interface allows the client to safely take over the %tba by
242 * the prom's service. The prom will take care of the quiescence of
243 * interrupts and handle any pending soft interrupts.
244 * This call also sets the MMU fault status area for the CPU.
247 set_mmfsa_traptable(void *tba_addr, uint64_t mmfsa_ra)
256 (cell_t)"SUNW,set-trap-table",
260 args.tba_addr = (cell_t)tba_addr;
261 args.mmfsa_ra = mmfsa_ra;
270 mmfsa = mmu_fault_status_area + (MMFSA_SIZE*curcpu);
272 set_wstate(WSTATE_KERN);
273 set_mmfsa_scratchpad(mmfsa);
276 set_mmfsa_traptable(&tl0_base, mmfsa);
280 trap(struct trapframe *tf, int64_t type, uint64_t data)
291 CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
293 (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
295 PCPU_INC(cnt.v_trap);
297 trapno = (type & TRAP_MASK);
298 ctx = (type >> TRAP_CTX_SHIFT);
300 if (((tf->tf_tstate & TSTATE_PRIV) == 0) || (ctx != 0)) {
301 KASSERT(td != NULL, ("trap: curthread NULL"));
302 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
308 if (td->td_ucred != p->p_ucred)
309 cred_update_thread(td);
313 case T_DATA_PROTECTION:
314 addr = TLB_TAR_VA(data);
315 case T_INSTRUCTION_MISS:
316 sig = trap_pfault(td, tf, trapno, data);
319 sig = rwindow_load(td, tf, 2);
322 sig = rwindow_load(td, tf, 1);
325 sig = rwindow_save(td);
327 case T_DATA_EXCEPTION:
329 case T_MEM_ADDRESS_NOT_ALIGNED:
330 printf("bad trap trapno=%ld data=0x%lx pc=0x%lx\n",
331 trapno, data, tf->tf_tpc);
332 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
333 tf->tf_tpc <= (u_long)copy_nofault_end) {
334 tf->tf_tpc = (u_long)copy_fault;
335 tf->tf_tnpc = tf->tf_tpc + 4;
339 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
340 tf->tf_tpc <= (u_long)fs_nofault_end) {
341 tf->tf_tpc = (u_long)fs_fault;
342 tf->tf_tnpc = tf->tf_tpc + 4;
348 sig = trap_sig[trapno];
352 if (trapno < 0 || trapno >= T_MAX ||
353 trap_sig[trapno] == -1)
354 panic("trap: bad trap type");
355 sig = trap_sig[trapno];
360 /* Translate fault for emulators. */
361 if (p->p_sysent->sv_transtrap != NULL) {
362 sig = p->p_sysent->sv_transtrap(sig,
365 if (debugger_on_signal &&
366 (sig == 4 || sig == 10 || sig == 11))
367 kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
369 if (sig == 4 || sig == 10 || sig == 11)
370 printf("trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d sig=%d proc=%s\n",
371 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu, sig, curthread->td_name);
373 /* XXX I've renumbered the traps to largely reflect what the hardware uses
374 * so this will need to be re-visited
376 ksiginfo_init_trap(&ksi);
378 ksi.ksi_code = (int)trapno; /* XXX not POSIX */
379 ksi.ksi_addr = (void *)addr;
380 ksi.ksi_trapno = (int)trapno;
381 trapsignal(td, &ksi);
385 mtx_assert(&Giant, MA_NOTOWNED);
387 KASSERT((type & T_KERNEL) != 0,
388 ("trap: kernel trap isn't - trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d\n",
389 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu));
399 error = (kdb_trap(trapno, 0, tf) == 0);
403 case T_DATA_PROTECTION:
404 case T_INSTRUCTION_MISS:
405 error = trap_pfault(td, tf, trapno, data);
407 case T_DATA_EXCEPTION:
408 printf("data exception on 0x%lx at 0x%lx\n", data, tf->tf_tpc);
409 printf("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx\n", trapno,
410 trap_msg[trapno], data, tf->tf_tpc, tf->tf_tnpc);
411 case T_ILLEGAL_INSTRUCTION:
412 if (tf->tf_tpc > KERNBASE) {
413 printf("illinstr: 0x%lx\n", tf->tf_tpc);
414 printf("illinstr: 0x%x\n", *((uint32_t *)tf->tf_tpc));
418 if (tf->tf_asi == ASI_AIUS) {
419 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
420 tf->tf_tpc <= (u_long)copy_nofault_end) {
421 tf->tf_tpc = (u_long)copy_fault;
422 tf->tf_tnpc = tf->tf_tpc + 4;
427 printf("ASI_AIUS but bad tpc\n");
429 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
430 tf->tf_tpc <= (u_long)fs_nofault_end) {
431 tf->tf_tpc = (u_long)fs_fault;
432 tf->tf_tnpc = tf->tf_tpc + 4;
436 printf("asi=0x%lx\n", tf->tf_asi);
440 printf("unchecked trap 0x%lx asi=0x%lx\n", trapno, tf->tf_asi);
446 panic("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx error=%d asi=0x%lx",
447 trapno, trap_msg[trapno], data, tf->tf_tpc,
448 tf->tf_tnpc, error, tf->tf_asi);
450 CTR1(KTR_TRAP, "trap: td=%p return", td);
454 trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data)
470 ctx = TLB_TAR_CTX(data);
471 type = type & ~T_KERNEL;
472 va = TLB_TAR_VA(data);
475 if (data > VM_MIN_DIRECT_ADDRESS)
476 printf("trap_pfault(type=%ld, data=0x%lx, tpc=0x%lx, ctx=0x%lx)\n",
477 type, data, tf->tf_tpc, ctx);
480 CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
481 td, p->p_vmspace->vm_pmap.pm_context, va, ctx);
483 KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
484 KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
485 KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
488 if (type == T_DATA_PROTECTION) {
489 prot = VM_PROT_WRITE;
490 flags = VM_FAULT_DIRTY;
492 if (type == T_DATA_MISS)
495 prot = VM_PROT_READ | VM_PROT_EXECUTE;
496 flags = VM_FAULT_NORMAL;
499 if (ctx != TLB_CTX_KERNEL) {
500 if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
501 (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
502 tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
503 tf->tf_tpc = (u_long)fs_fault;
504 tf->tf_tnpc = tf->tf_tpc + 4;
509 * This is a fault on non-kernel virtual memory.
514 * Keep swapout from messing with us during this
521 /* Fault in the user page. */
522 rv = vm_fault(&vm->vm_map, va, prot, flags);
525 * Now the process can be swapped again.
532 * This is a fault on kernel virtual memory. Attempts to
533 * access kernel memory from user mode cause privileged
534 * action traps, not page fault.
536 KASSERT(tf->tf_tstate & TSTATE_PRIV,
537 ("trap_pfault: fault on nucleus context from user mode"));
540 * Don't have to worry about process locking or stacks in the
543 rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
546 CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
548 if (rv == KERN_SUCCESS)
550 if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
551 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
552 tf->tf_tpc <= (u_long)fs_nofault_end) {
553 tf->tf_tpc = (u_long)fs_fault;
554 tf->tf_tnpc = tf->tf_tpc + 4;
557 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
558 tf->tf_tpc <= (u_long)copy_nofault_end) {
559 tf->tf_tpc = (u_long)copy_fault;
560 tf->tf_tnpc = tf->tf_tpc + 4;
564 return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
567 /* Maximum number of arguments that can be passed via the out registers. */
568 #define REG_MAXARGS 6
571 cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
573 struct trapframe *tf;
583 regcnt = REG_MAXARGS;
585 sa->code = tf->tf_global[1];
587 if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
588 sa->code = tf->tf_out[reg++];
592 if (p->p_sysent->sv_mask)
593 sa->code &= p->p_sysent->sv_mask;
594 if (sa->code >= p->p_sysent->sv_size)
595 sa->callp = &p->p_sysent->sv_table[0];
597 sa->callp = &p->p_sysent->sv_table[sa->code];
599 sa->narg = sa->callp->sy_narg;
600 KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
601 ("Too many syscall arguments!"));
604 bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
605 if (sa->narg > regcnt)
606 error = copyin((void *)(tf->tf_out[6] + SPOFF +
607 offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
608 (sa->narg - regcnt) * sizeof(sa->args[0]));
610 td->td_retval[0] = 0;
611 td->td_retval[1] = 0;
618 * Syscall handler. The arguments to the syscall are passed in the o registers
619 * by the caller, and are saved in the trap frame. The syscall number is passed
620 * in %g1 (and also saved in the trap frame).
623 syscall(struct trapframe *tf)
626 struct syscall_args sa;
632 KASSERT(td != NULL, ("trap: curthread NULL"));
633 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
636 * For syscalls, we don't want to retry the faulting instruction
637 * (usually), instead we need to advance one instruction.
639 td->td_pcb->pcb_tpc = tf->tf_tpc;
642 error = syscallenter(td, &sa);
643 syscallret(td, error, &sa);