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/smp.h>
85 #include <machine/trap.h>
86 #include <machine/tstate.h>
87 #include <machine/tte.h>
88 #include <machine/tlb.h>
89 #include <machine/tsb.h>
90 #include <machine/watch.h>
91 #include <machine/wstate.h>
93 #include <machine/md_var.h>
94 #include <machine/hypervisorvar.h>
96 #include <security/audit/audit.h>
98 void trap(struct trapframe *tf, int64_t type, uint64_t data);
99 void syscall(struct trapframe *tf);
101 extern vm_paddr_t mmu_fault_status_area;
103 static int trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data);
105 extern char copy_fault[];
106 extern char copy_nofault_begin[];
107 extern char copy_nofault_end[];
109 extern char fs_fault[];
110 extern char fs_nofault_begin[];
111 extern char fs_nofault_end[];
112 extern char fs_nofault_intr_begin[];
113 extern char fs_nofault_intr_end[];
115 extern char fas_fault[];
116 extern char fas_nofault_begin[];
117 extern char fas_nofault_end[];
119 extern char *syscallnames[];
121 const char *const trap_msg[] = {
123 "instruction access exception",
124 "instruction access error",
125 "instruction access protection",
126 "illtrap instruction",
127 "illegal instruction",
129 "floating point disabled",
130 "floating point exception ieee 754",
131 "floating point exception other",
134 "data access exception",
136 "data access protection",
137 "memory address not aligned",
140 "trap instruction 16",
141 "trap instruction 17",
142 "trap instruction 18",
143 "trap instruction 19",
144 "trap instruction 20",
145 "trap instruction 21",
146 "trap instruction 22",
147 "trap instruction 23",
148 "trap instruction 24",
149 "trap instruction 25",
150 "trap instruction 26",
151 "trap instruction 27",
152 "trap instruction 28",
153 "trap instruction 29",
154 "trap instruction 30",
155 "trap instruction 31",
156 "fast instruction access mmu miss",
157 "fast data access mmu miss",
159 "physical address watchpoint",
160 "virtual address watchpoint",
161 "corrected ecc error",
171 "restore physical watchpoint",
172 "restore virtual watchpoint",
173 "kernel stack fault",
178 const int trap_sig[] = {
179 SIGILL, /* reserved */
180 SIGILL, /* instruction access exception */
181 SIGILL, /* instruction access error */
182 SIGILL, /* instruction access protection */
183 SIGILL, /* illtrap instruction */
184 SIGILL, /* illegal instruction */
185 SIGBUS, /* privileged opcode */
186 SIGFPE, /* floating point disabled */
187 SIGFPE, /* floating point exception ieee 754 */
188 SIGFPE, /* floating point exception other */
189 SIGEMT, /* tag overflow */
190 SIGFPE, /* division by zero */
191 SIGILL, /* data access exception */
192 SIGILL, /* data access error */
193 SIGBUS, /* data access protection */
194 SIGBUS, /* memory address not aligned */
195 SIGBUS, /* privileged action */
196 SIGBUS, /* async data error */
197 SIGILL, /* trap instruction 16 */
198 SIGILL, /* trap instruction 17 */
199 SIGILL, /* trap instruction 18 */
200 SIGILL, /* trap instruction 19 */
201 SIGILL, /* trap instruction 20 */
202 SIGILL, /* trap instruction 21 */
203 SIGILL, /* trap instruction 22 */
204 SIGILL, /* trap instruction 23 */
205 SIGILL, /* trap instruction 24 */
206 SIGILL, /* trap instruction 25 */
207 SIGILL, /* trap instruction 26 */
208 SIGILL, /* trap instruction 27 */
209 SIGILL, /* trap instruction 28 */
210 SIGILL, /* trap instruction 29 */
211 SIGILL, /* trap instruction 30 */
212 SIGILL, /* trap instruction 31 */
213 SIGFPE, /* floating point error */
214 SIGSEGV, /* fast data access mmu miss */
216 -1, /* physical address watchpoint */
217 -1, /* virtual address watchpoint */
218 -1, /* corrected ecc error */
222 SIGTRAP, /* breakpoint */
223 SIGILL, /* clean window */
224 SIGILL, /* range check */
225 SIGILL, /* fix alignment */
226 SIGILL, /* integer overflow */
227 SIGSYS, /* syscall */
228 -1, /* restore physical watchpoint */
229 -1, /* restore virtual watchpoint */
230 -1, /* kernel stack fault */
233 CTASSERT(sizeof(struct trapframe) == 256);
235 int debugger_on_signal = 0;
237 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
238 &debugger_on_signal, 0, "");
242 * This interface allows the client to safely take over the %tba by
243 * the prom's service. The prom will take care of the quiescence of
244 * interrupts and handle any pending soft interrupts.
245 * This call also sets the MMU fault status area for the CPU.
248 set_mmfsa_traptable(void *tba_addr, uint64_t mmfsa_ra)
257 (cell_t)"SUNW,set-trap-table",
261 args.tba_addr = (cell_t)tba_addr;
262 args.mmfsa_ra = mmfsa_ra;
271 mmfsa = mmu_fault_status_area + (MMFSA_SIZE*curcpu);
273 set_wstate(WSTATE_KERN);
274 set_mmfsa_scratchpad(mmfsa);
277 set_mmfsa_traptable(&tl0_base, mmfsa);
281 trap(struct trapframe *tf, int64_t type, uint64_t data)
292 CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
294 (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
296 PCPU_INC(cnt.v_trap);
298 trapno = (type & TRAP_MASK);
299 ctx = (type >> TRAP_CTX_SHIFT);
301 if (((tf->tf_tstate & TSTATE_PRIV) == 0) || (ctx != 0)) {
302 KASSERT(td != NULL, ("trap: curthread NULL"));
303 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
309 if (td->td_ucred != p->p_ucred)
310 cred_update_thread(td);
314 case T_DATA_PROTECTION:
315 addr = TLB_TAR_VA(data);
316 case T_INSTRUCTION_MISS:
317 sig = trap_pfault(td, tf, trapno, data);
320 sig = rwindow_load(td, tf, 2);
323 sig = rwindow_load(td, tf, 1);
326 sig = rwindow_save(td);
328 case T_DATA_EXCEPTION:
330 case T_MEM_ADDRESS_NOT_ALIGNED:
331 printf("bad trap trapno=%ld data=0x%lx pc=0x%lx\n",
332 trapno, data, tf->tf_tpc);
333 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
334 tf->tf_tpc <= (u_long)copy_nofault_end) {
335 tf->tf_tpc = (u_long)copy_fault;
336 tf->tf_tnpc = tf->tf_tpc + 4;
340 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
341 tf->tf_tpc <= (u_long)fs_nofault_end) {
342 tf->tf_tpc = (u_long)fs_fault;
343 tf->tf_tnpc = tf->tf_tpc + 4;
349 sig = trap_sig[trapno];
353 if (trapno < 0 || trapno >= T_MAX ||
354 trap_sig[trapno] == -1)
355 panic("trap: bad trap type");
356 sig = trap_sig[trapno];
361 /* Translate fault for emulators. */
362 if (p->p_sysent->sv_transtrap != NULL) {
363 sig = p->p_sysent->sv_transtrap(sig,
366 if (debugger_on_signal &&
367 (sig == 4 || sig == 10 || sig == 11))
368 kdb_enter_why(KDB_WHY_TRAPSIG, "trapsig");
370 if (sig == 4 || sig == 10 || sig == 11)
371 printf("trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d sig=%d proc=%s\n",
372 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu, sig, curthread->td_proc->p_comm);
374 /* XXX I've renumbered the traps to largely reflect what the hardware uses
375 * so this will need to be re-visited
377 ksiginfo_init_trap(&ksi);
379 ksi.ksi_code = (int)trapno; /* XXX not POSIX */
380 ksi.ksi_addr = (void *)addr;
381 ksi.ksi_trapno = (int)trapno;
382 trapsignal(td, &ksi);
386 mtx_assert(&Giant, MA_NOTOWNED);
388 KASSERT((type & T_KERNEL) != 0,
389 ("trap: kernel trap isn't - trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d\n",
390 trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu));
400 error = (kdb_trap(trapno, 0, tf) == 0);
404 case T_DATA_PROTECTION:
405 case T_INSTRUCTION_MISS:
406 error = trap_pfault(td, tf, trapno, data);
408 case T_DATA_EXCEPTION:
409 printf("data exception on 0x%lx at 0x%lx\n", data, tf->tf_tpc);
410 printf("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx\n", trapno,
411 trap_msg[trapno], data, tf->tf_tpc, tf->tf_tnpc);
412 case T_ILLEGAL_INSTRUCTION:
413 if (tf->tf_tpc > KERNBASE) {
414 printf("illinstr: 0x%lx\n", tf->tf_tpc);
415 printf("illinstr: 0x%x\n", *((uint32_t *)tf->tf_tpc));
419 if (tf->tf_asi == ASI_AIUS) {
420 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
421 tf->tf_tpc <= (u_long)copy_nofault_end) {
422 tf->tf_tpc = (u_long)copy_fault;
423 tf->tf_tnpc = tf->tf_tpc + 4;
428 printf("ASI_AIUS but bad tpc\n");
430 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
431 tf->tf_tpc <= (u_long)fs_nofault_end) {
432 tf->tf_tpc = (u_long)fs_fault;
433 tf->tf_tnpc = tf->tf_tpc + 4;
437 printf("asi=0x%lx\n", tf->tf_asi);
441 printf("unchecked trap 0x%lx asi=0x%lx\n", trapno, tf->tf_asi);
447 panic("trap: %ld=%s: 0x%lx at 0x%lx:0x%lx error=%d asi=0x%lx",
448 trapno, trap_msg[trapno], data, tf->tf_tpc,
449 tf->tf_tnpc, error, tf->tf_asi);
451 CTR1(KTR_TRAP, "trap: td=%p return", td);
455 trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data)
471 ctx = TLB_TAR_CTX(data);
472 type = type & ~T_KERNEL;
473 va = TLB_TAR_VA(data);
476 if (data > VM_MIN_DIRECT_ADDRESS)
477 printf("trap_pfault(type=%ld, data=0x%lx, tpc=0x%lx, ctx=0x%lx)\n",
478 type, data, tf->tf_tpc, ctx);
481 CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
482 td, p->p_vmspace->vm_pmap.pm_context, va, ctx);
484 KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
485 KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
486 KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
489 if (type == T_DATA_PROTECTION) {
490 prot = VM_PROT_WRITE;
491 flags = VM_FAULT_DIRTY;
493 if (type == T_DATA_MISS)
496 prot = VM_PROT_READ | VM_PROT_EXECUTE;
497 flags = VM_FAULT_NORMAL;
500 if (ctx != TLB_CTX_KERNEL) {
501 if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
502 (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
503 tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
504 tf->tf_tpc = (u_long)fs_fault;
505 tf->tf_tnpc = tf->tf_tpc + 4;
510 * This is a fault on non-kernel virtual memory.
515 * Keep swapout from messing with us during this
522 /* Fault in the user page. */
523 rv = vm_fault(&vm->vm_map, va, prot, flags);
526 * Now the process can be swapped again.
533 * This is a fault on kernel virtual memory. Attempts to
534 * access kernel memory from user mode cause privileged
535 * action traps, not page fault.
537 KASSERT(tf->tf_tstate & TSTATE_PRIV,
538 ("trap_pfault: fault on nucleus context from user mode"));
541 * Don't have to worry about process locking or stacks in the
544 rv = vm_fault(kernel_map, va, prot, VM_FAULT_NORMAL);
547 CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
549 if (rv == KERN_SUCCESS)
551 if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
552 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
553 tf->tf_tpc <= (u_long)fs_nofault_end) {
554 tf->tf_tpc = (u_long)fs_fault;
555 tf->tf_tnpc = tf->tf_tpc + 4;
558 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
559 tf->tf_tpc <= (u_long)copy_nofault_end) {
560 tf->tf_tpc = (u_long)copy_fault;
561 tf->tf_tnpc = tf->tf_tpc + 4;
565 return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
568 /* Maximum number of arguments that can be passed via the out registers. */
569 #define REG_MAXARGS 6
572 * Syscall handler. The arguments to the syscall are passed in the o registers
573 * by the caller, and are saved in the trap frame. The syscall number is passed
574 * in %g1 (and also saved in the trap frame).
577 syscall(struct trapframe *tf)
579 struct sysent *callp;
592 KASSERT(td != NULL, ("trap: curthread NULL"));
593 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
597 PCPU_INC(cnt.v_syscall);
601 if (td->td_ucred != p->p_ucred)
602 cred_update_thread(td);
603 code = tf->tf_global[1];
606 * For syscalls, we don't want to retry the faulting instruction
607 * (usually), instead we need to advance one instruction.
613 regcnt = REG_MAXARGS;
614 if (p->p_sysent->sv_prepsyscall) {
616 * The prep code is MP aware.
619 (*p->p_sysent->sv_prepsyscall)(tf, args, &code, ¶ms);
621 } else if (code == SYS_syscall || code == SYS___syscall) {
622 code = tf->tf_out[reg++];
626 if (p->p_sysent->sv_mask)
627 code &= p->p_sysent->sv_mask;
629 if (code >= p->p_sysent->sv_size)
630 callp = &p->p_sysent->sv_table[0];
632 callp = &p->p_sysent->sv_table[code];
634 narg = callp->sy_narg;
636 if (narg <= regcnt) {
637 argp = &tf->tf_out[reg];
640 KASSERT(narg <= sizeof(args) / sizeof(args[0]),
641 ("Too many syscall arguments!"));
643 bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt);
644 error = copyin((void *)(tf->tf_out[6] + SPOFF +
645 offsetof(struct frame, fr_pad[6])),
646 &args[regcnt], (narg - regcnt) * sizeof(args[0]));
649 CTR5(KTR_SYSC, "syscall: td=%p %s(%#lx, %#lx, %#lx)", td,
650 syscallnames[code], argp[0], argp[1], argp[2]);
653 * Try to run the syscall without the MP lock if the syscall
657 if (KTRPOINT(td, KTR_SYSCALL))
658 ktrsyscall(code, narg, argp);
661 td->td_retval[0] = 0;
662 td->td_retval[1] = 0;
664 STOPEVENT(p, S_SCE, narg); /* MP aware */
666 PTRACESTOP_SC(p, td, S_PT_SCE);
668 AUDIT_SYSCALL_ENTER(code, td);
669 error = (*callp->sy_call)(td, argp);
670 AUDIT_SYSCALL_EXIT(error, td);
672 CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx ", p,
673 error, syscallnames[code], td->td_retval[0],
678 * MP SAFE (we may or may not have the MP lock at this point)
682 tf->tf_out[0] = td->td_retval[0];
683 tf->tf_out[1] = td->td_retval[1];
684 tf->tf_tstate &= ~TSTATE_XCC_C;
689 * Undo the tpc advancement we have done above, we want to
690 * reexecute the system call.
700 if (p->p_sysent->sv_errsize) {
701 if (error >= p->p_sysent->sv_errsize)
702 error = -1; /* XXX */
704 error = p->p_sysent->sv_errtbl[error];
706 tf->tf_out[0] = error;
707 tf->tf_tstate |= TSTATE_XCC_C;
712 * Handle reschedule and other end-of-syscall issues
717 if (KTRPOINT(td, KTR_SYSRET))
718 ktrsysret(code, error, td->td_retval[0]);
721 * This works because errno is findable through the
722 * register set. If we ever support an emulation where this
723 * is not the case, this code will need to be revisited.
725 STOPEVENT(p, S_SCX, code);
727 PTRACESTOP_SC(p, td, S_PT_SCX);
729 WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
730 (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
731 mtx_assert(&Giant, MA_NOTOWNED);