diff options
-rw-r--r-- | sys/sparc64/include/trap.h | 2 | ||||
-rw-r--r-- | sys/sparc64/sparc64/rwindow.c | 4 | ||||
-rw-r--r-- | sys/sparc64/sparc64/trap.c | 398 |
3 files changed, 165 insertions, 239 deletions
diff --git a/sys/sparc64/include/trap.h b/sys/sparc64/include/trap.h index 0826d7c..2c485b5 100644 --- a/sys/sparc64/include/trap.h +++ b/sys/sparc64/include/trap.h @@ -85,6 +85,8 @@ #define T_RSTRWP_VIRT 50 #define T_KSTACK_FAULT 51 +#define T_MAX (T_KSTACK_FAULT + 1) + #define T_KERNEL 64 #ifndef LOCORE diff --git a/sys/sparc64/sparc64/rwindow.c b/sys/sparc64/sparc64/rwindow.c index 0c5e5a6..675379e 100644 --- a/sys/sparc64/sparc64/rwindow.c +++ b/sys/sparc64/sparc64/rwindow.c @@ -66,7 +66,7 @@ rwindow_load(struct thread *td, struct trapframe *tf, int n) usp = rw.rw_in[6]; } CTR1(KTR_TRAP, "rwindow_load: error=%d", error); - return (error); + return (error == 0 ? 0 : SIGILL); } int @@ -104,5 +104,5 @@ rwindow_save(struct thread *td) CTR1(KTR_TRAP, "rwindow_save: error=%d", error); if (error == 0) pcb->pcb_nsaved = 0; - return (error); + return (error == 0 ? 0 : SIGILL); } diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c index ded23a4..37f9b16 100644 --- a/sys/sparc64/sparc64/trap.c +++ b/sys/sparc64/sparc64/trap.c @@ -75,6 +75,7 @@ #include <vm/vm_page.h> #include <machine/clock.h> +#include <machine/cpu.h> #include <machine/frame.h> #include <machine/intr_machdep.h> #include <machine/pcb.h> @@ -158,6 +159,61 @@ const char *trap_msg[] = { "kernel stack fault", }; +const int trap_sig[] = { + SIGILL, /* reserved */ + SIGILL, /* instruction access exception */ + SIGILL, /* instruction access error */ + SIGILL, /* instruction access protection */ + SIGILL, /* illtrap instruction */ + SIGILL, /* illegal instruction */ + SIGBUS, /* privileged opcode */ + SIGFPE, /* floating point disabled */ + SIGFPE, /* floating point exception ieee 754 */ + SIGFPE, /* floating point exception other */ + SIGEMT, /* tag overflow */ + SIGFPE, /* division by zero */ + SIGILL, /* data access exception */ + SIGILL, /* data access error */ + SIGBUS, /* data access protection */ + SIGBUS, /* memory address not aligned */ + SIGBUS, /* privileged action */ + SIGBUS, /* async data error */ + SIGILL, /* trap instruction 16 */ + SIGILL, /* trap instruction 17 */ + SIGILL, /* trap instruction 18 */ + SIGILL, /* trap instruction 19 */ + SIGILL, /* trap instruction 20 */ + SIGILL, /* trap instruction 21 */ + SIGILL, /* trap instruction 22 */ + SIGILL, /* trap instruction 23 */ + SIGILL, /* trap instruction 24 */ + SIGILL, /* trap instruction 25 */ + SIGILL, /* trap instruction 26 */ + SIGILL, /* trap instruction 27 */ + SIGILL, /* trap instruction 28 */ + SIGILL, /* trap instruction 29 */ + SIGILL, /* trap instruction 30 */ + SIGILL, /* trap instruction 31 */ + -1, /* interrupt */ + -1, /* physical address watchpoint */ + -1, /* virtual address watchpoint */ + -1, /* corrected ecc error */ + SIGSEGV, /* fast instruction access mmu miss */ + SIGSEGV, /* fast data access mmu miss */ + SIGILL, /* spill */ + SIGILL, /* fill */ + SIGILL, /* fill */ + SIGTRAP, /* breakpoint */ + SIGILL, /* clean window */ + SIGILL, /* range check */ + SIGILL, /* fix alignment */ + SIGILL, /* integer overflow */ + -1, /* syscall */ + -1, /* restore physical watchpoint */ + -1, /* restore virtual watchpoint */ + -1, /* kernel stack fault */ +}; + CTASSERT(sizeof(struct trapframe) == 256); int debugger_on_signal = 0; @@ -171,32 +227,22 @@ trap(struct trapframe *tf) struct proc *p; u_int sticks; int error; - int ucode; -#ifdef DDB - int mask; -#endif - int type; int sig; - KASSERT(PCPU_GET(curthread) != NULL, ("trap: curthread NULL")); - KASSERT(PCPU_GET(curthread)->td_kse != NULL, ("trap: curkse NULL")); - KASSERT(PCPU_GET(curthread)->td_proc != NULL, ("trap: curproc NULL")); - - atomic_add_int(&cnt.v_trap, 1); - td = PCPU_GET(curthread); - p = td->td_proc; - error = 0; - type = tf->tf_type; - ucode = type; /* XXX */ + CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td, + trap_msg[tf->tf_type & ~T_KERNEL], + (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil)); - CTR4(KTR_TRAP, "trap: %s type=%s (%s) pil=%#lx", - p->p_comm, trap_msg[type & ~T_KERNEL], - ((type & T_KERNEL) ? "kernel" : "user"), - rdpr(pil)); + atomic_add_int(&cnt.v_trap, 1); + + if ((tf->tf_tstate & TSTATE_PRIV) == 0) { + KASSERT(td != NULL, ("trap: curthread NULL")); + KASSERT(td->td_kse != NULL, ("trap: curkse NULL")); + KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); - if ((type & T_KERNEL) == 0) { + p = td->td_proc; sticks = td->td_kse->ke_sticks; td->td_frame = tf; if (td->td_ucred != p->p_ucred) @@ -207,225 +253,99 @@ trap(struct trapframe *tf) thread_exit(); /* NOTREACHED */ } - } else { - sticks = 0; -if ((type & ~T_KERNEL) != T_BREAKPOINT) - KASSERT(cold || td->td_ucred != NULL, - ("kernel trap doesn't have ucred")); - } - - switch (type) { - /* - * User Mode Traps - */ - case T_MEM_ADDRESS_NOT_ALIGNED: - sig = SIGILL; - goto trapsig; -#if 0 - case T_ALIGN_LDDF: - case T_ALIGN_STDF: - sig = SIGBUS; - goto trapsig; -#endif - case T_BREAKPOINT: - sig = SIGTRAP; - goto trapsig; - case T_DIVISION_BY_ZERO: - sig = SIGFPE; - goto trapsig; - case T_FP_DISABLED: - case T_FP_EXCEPTION_IEEE_754: - case T_FP_EXCEPTION_OTHER: - sig = SIGFPE; - goto trapsig; - case T_DATA_ERROR: - case T_DATA_EXCEPTION: - case T_INSTRUCTION_ERROR: - case T_INSTRUCTION_EXCEPTION: - sig = SIGILL; /* XXX */ - goto trapsig; - case T_DATA_MISS: - case T_DATA_PROTECTION: - case T_INSTRUCTION_MISS: - error = trap_pfault(td, tf); - if (error == 0) - goto user; - sig = error; - goto trapsig; - case T_FILL: - if (rwindow_load(td, tf, 2)) { - PROC_LOCK(p); - sigexit(td, SIGILL); - /* Not reached. */ - } - goto user; - case T_FILL_RET: - if (rwindow_load(td, tf, 1)) { - PROC_LOCK(p); - sigexit(td, SIGILL); - /* Not reached. */ + switch (tf->tf_type) { + case T_DATA_MISS: + case T_DATA_PROTECTION: + case T_INSTRUCTION_MISS: + sig = trap_pfault(td, tf); + break; + case T_FILL: + sig = rwindow_load(td, tf, 2); + break; + case T_FILL_RET: + sig = rwindow_load(td, tf, 1); + break; + case T_SPILL: + sig = rwindow_save(td); + break; + default: + if (tf->tf_type < 0 || tf->tf_type >= T_MAX || + trap_sig[tf->tf_type] == -1) + panic("trap: bad trap type"); + sig = trap_sig[tf->tf_type]; + break; } - goto user; - case T_ILLEGAL_INSTRUCTION: - sig = SIGILL; - goto trapsig; - case T_PRIVILEGED_ACTION: - case T_PRIVILEGED_OPCODE: - sig = SIGBUS; - goto trapsig; - case T_TRAP_INSTRUCTION_16: - case T_TRAP_INSTRUCTION_17: - case T_TRAP_INSTRUCTION_18: - case T_TRAP_INSTRUCTION_19: - case T_TRAP_INSTRUCTION_20: - case T_TRAP_INSTRUCTION_21: - case T_TRAP_INSTRUCTION_22: - case T_TRAP_INSTRUCTION_23: - case T_TRAP_INSTRUCTION_24: - case T_TRAP_INSTRUCTION_25: - case T_TRAP_INSTRUCTION_26: - case T_TRAP_INSTRUCTION_27: - case T_TRAP_INSTRUCTION_28: - case T_TRAP_INSTRUCTION_29: - case T_TRAP_INSTRUCTION_30: - case T_TRAP_INSTRUCTION_31: - sig = SIGILL; - goto trapsig; - case T_SPILL: - if (rwindow_save(td)) { - PROC_LOCK(p); - sigexit(td, SIGILL); - /* Not reached. */ + + if (sig != 0) { + /* Translate fault for emulators. */ + if (p->p_sysent->sv_transtrap != NULL) { + sig = p->p_sysent->sv_transtrap(sig, + tf->tf_type); + } + if (debugger_on_signal && + (sig == 4 || sig == 10 || sig == 11)) + Debugger("trapsig"); + trapsignal(p, sig, tf->tf_type); } - goto user; - case T_TAG_OFERFLOW: - sig = SIGEMT; - goto trapsig; - /* - * Kernel Mode Traps - */ + userret(td, tf, sticks); + mtx_assert(&Giant, MA_NOTOWNED); +#ifdef DIAGNOSTIC + cred_free_thread(td); +#endif + } else { + KASSERT((tf->tf_type & T_KERNEL) != 0, + ("trap: kernel trap isn't")); + + switch (tf->tf_type & ~T_KERNEL) { #ifdef DDB - case T_BREAKPOINT | T_KERNEL: - case T_KSTACK_FAULT | T_KERNEL: - if (kdb_trap(tf) != 0) - goto out; - break; + case T_BREAKPOINT: + case T_KSTACK_FAULT: + error = (kdb_trap(tf) == 0); + break; +#ifdef notyet + case T_PA_WATCHPOINT: + case T_VA_WATCHPOINT: + error = db_watch_trap(tf); + break; +#endif #endif - case T_DATA_EXCEPTION | T_KERNEL: - case T_MEM_ADDRESS_NOT_ALIGNED | T_KERNEL: - if ((tf->tf_sfsr & MMU_SFSR_FV) == 0 || - MMU_SFSR_GET_ASI(tf->tf_sfsr) != ASI_AIUP) + case T_DATA_MISS: + case T_DATA_PROTECTION: + case T_INSTRUCTION_MISS: + error = trap_pfault(td, tf); + break; + case T_DATA_EXCEPTION: + case T_MEM_ADDRESS_NOT_ALIGNED: + if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 && + MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) { + if (tf->tf_tpc >= (u_long)copy_nofault_begin && + tf->tf_tpc <= (u_long)copy_nofault_end) { + tf->tf_tpc = (u_long)copy_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + error = 0; + break; + } + if (tf->tf_tpc >= (u_long)fs_nofault_begin && + tf->tf_tpc <= (u_long)fs_nofault_end) { + tf->tf_tpc = (u_long)fs_fault; + tf->tf_tnpc = tf->tf_tpc + 4; + error = 0; + break; + } + } + error = 1; + break; + default: + error = 1; break; - if (tf->tf_tpc >= (u_long)copy_nofault_begin && - tf->tf_tpc <= (u_long)copy_nofault_end) { - tf->tf_tpc = (u_long)copy_fault; - tf->tf_tnpc = tf->tf_tpc + 4; - goto out; - } - if (tf->tf_tpc >= (u_long)fs_nofault_begin && - tf->tf_tpc <= (u_long)fs_nofault_end) { - tf->tf_tpc = (u_long)fs_fault; - tf->tf_tnpc = tf->tf_tpc + 4; - goto out; } - break; - case T_DATA_MISS | T_KERNEL: - case T_DATA_PROTECTION | T_KERNEL: - case T_INSTRUCTION_MISS | T_KERNEL: - error = trap_pfault(td, tf); - if (error == 0) - goto out; - break; -#ifdef DDB - case T_PA_WATCHPOINT | T_KERNEL: - TR3("trap: watch phys pa=%#lx tpc=%#lx, tnpc=%#lx", - watch_phys_get(&mask), tf->tf_tpc, tf->tf_tnpc); - PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >> - TSTATE_PSTATE_SHIFT); - tf->tf_tstate &= ~TSTATE_IE; - intr_disable(); - PCPU_SET(wp_insn, *((u_int *)tf->tf_tnpc)); - *((u_int *)tf->tf_tnpc) = 0x91d03002; /* ta %xcc, 2 */ - flush(tf->tf_tnpc); - PCPU_SET(wp_va, watch_phys_get(&mask)); - PCPU_SET(wp_mask, mask); - watch_phys_clear(); - goto out; - case T_VA_WATCHPOINT | T_KERNEL: - /* - * At the moment, just print the information from the trap, - * remove the watchpoint, use evil magic to execute the - * instruction (we temporarily save the instruction at - * %tnpc, write a trap instruction, resume, and reset the - * watch point when the trap arrives). - * To make sure that no interrupt gets in between and creates - * a potentially large window where the watchpoint is inactive, - * disable interrupts temporarily. - * This is obviously fragile and evilish. - */ - TR3("trap: watch virt pa=%#lx tpc=%#lx, tnpc=%#lx", - watch_virt_get(&mask), tf->tf_tpc, tf->tf_tnpc); - PCPU_SET(wp_pstate, (tf->tf_tstate & TSTATE_PSTATE_MASK) >> - TSTATE_PSTATE_SHIFT); - tf->tf_tstate &= ~TSTATE_IE; - /* - * This has no matching intr_restore; the PSTATE_IE state of the - * trapping code will be restored when the watch point is - * restored. - */ - intr_disable(); - PCPU_SET(wp_insn, *((u_int *)tf->tf_tnpc)); - *((u_int *)tf->tf_tnpc) = 0x91d03003; /* ta %xcc, 3 */ - flush(tf->tf_tnpc); - PCPU_SET(wp_va, watch_virt_get(&mask)); - PCPU_SET(wp_mask, mask); - watch_virt_clear(); - goto out; - case T_RSTRWP_PHYS | T_KERNEL: - tf->tf_tstate = (tf->tf_tstate & ~TSTATE_PSTATE_MASK) | - PCPU_GET(wp_pstate) << TSTATE_PSTATE_SHIFT; - watch_phys_set_mask(PCPU_GET(wp_va), PCPU_GET(wp_mask)); - *(u_int *)tf->tf_tpc = PCPU_GET(wp_insn); - flush(tf->tf_tpc); - goto out; - case T_RSTRWP_VIRT | T_KERNEL: - /* - * Undo the tweaks tone for T_WATCH, reset the watch point and - * contunue execution. - * Note that here, we run with interrupts enabled, so there - * is a small chance that we will be interrupted before we - * could reset the watch point. - */ - tf->tf_tstate = (tf->tf_tstate & ~TSTATE_PSTATE_MASK) | - PCPU_GET(wp_pstate) << TSTATE_PSTATE_SHIFT; - watch_virt_set_mask(PCPU_GET(wp_va), PCPU_GET(wp_mask)); - *(u_int *)tf->tf_tpc = PCPU_GET(wp_insn); - flush(tf->tf_tpc); - goto out; -#endif - default: - break; + + if (error != 0) + panic("trap: %s", trap_msg[tf->tf_type & ~T_KERNEL]); } - panic("trap: %s", trap_msg[type & ~T_KERNEL]); - -trapsig: - /* Translate fault for emulators. */ - if (p->p_sysent->sv_transtrap != NULL) - sig = (p->p_sysent->sv_transtrap)(sig, type); - if (debugger_on_signal && (sig == 4 || sig == 10 || sig == 11)) - Debugger("trapsig"); - trapsignal(p, sig, ucode); -user: - userret(td, tf, sticks); - mtx_assert(&Giant, MA_NOTOWNED); -#ifdef DIAGNOSTIC - cred_free_thread(td); -#endif -out: CTR1(KTR_TRAP, "trap: td=%p return", td); - return; } static int @@ -441,9 +361,13 @@ trap_pfault(struct thread *td, struct trapframe *tf) int type; int rv; - p = td->td_proc; + if (td == NULL) + return (-1); KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL")); - KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace NULL")); + KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL")); + KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL")); + + p = td->td_proc; rv = KERN_SUCCESS; ctx = TLB_TAR_CTX(tf->tf_tar); @@ -557,15 +481,15 @@ syscall(struct trapframe *tf) int narg; int error; - KASSERT(PCPU_GET(curthread) != NULL, ("trap: curthread NULL")); - KASSERT(PCPU_GET(curthread)->td_kse != NULL, ("trap: curkse NULL")); - KASSERT(PCPU_GET(curthread)->td_proc != NULL, ("trap: curproc NULL")); - - atomic_add_int(&cnt.v_syscall, 1); - td = PCPU_GET(curthread); + KASSERT(td != NULL, ("trap: curthread NULL")); + KASSERT(td->td_kse != NULL, ("trap: curkse NULL")); + KASSERT(td->td_proc != NULL, ("trap: curproc NULL")); + p = td->td_proc; + atomic_add_int(&cnt.v_syscall, 1); + narg = 0; error = 0; reg = 0; |