1 /* $NetBSD: trap.c,v 1.113 2008/03/11 05:34:03 matt Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Ludd, University of Lule}, Sweden. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed at Ludd, University of Lule}. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* All bugs are subject to removal without further notice */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.113 2008/03/11 05:34:03 matt Exp $"); 37 38 #include "opt_ddb.h" 39 #include "opt_multiprocessor.h" 40 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/proc.h> 44 #include <sys/user.h> 45 #include <sys/syscall.h> 46 #include <sys/systm.h> 47 #include <sys/signalvar.h> 48 #include <sys/exec.h> 49 #include <sys/pool.h> 50 #include <sys/kauth.h> 51 52 #include <uvm/uvm_extern.h> 53 54 #include <machine/mtpr.h> 55 #include <machine/pte.h> 56 #include <machine/pcb.h> 57 #include <machine/trap.h> 58 #include <machine/pmap.h> 59 #include <machine/cpu.h> 60 #include <machine/userret.h> 61 62 #ifdef DDB 63 #include <machine/db_machdep.h> 64 #endif 65 #include <kern/syscalls.c> 66 #include <sys/ktrace.h> 67 68 #ifdef TRAPDEBUG 69 volatile int faultdebug = 0; 70 #endif 71 72 int cpu_printfataltraps = 0; 73 74 void trap (struct trapframe *); 75 76 const char * const traptypes[]={ 77 "reserved addressing", 78 "privileged instruction", 79 "reserved operand", 80 "breakpoint instruction", 81 "XFC instruction", 82 "system call ", 83 "arithmetic trap", 84 "asynchronous system trap", 85 "page table length fault", 86 "translation violation fault", 87 "trace trap", 88 "compatibility mode fault", 89 "access violation fault", 90 "", 91 "", 92 "KSP invalid", 93 "", 94 "kernel debugger trap" 95 }; 96 int no_traps = 18; 97 98 #define USERMODE_P(framep) ((((framep)->psl) & (PSL_U)) == PSL_U) 99 #define FAULTCHK \ 100 if (l->l_addr->u_pcb.iftrap) { \ 101 frame->pc = (unsigned)l->l_addr->u_pcb.iftrap; \ 102 frame->psl &= ~PSL_FPD; \ 103 frame->r0 = EFAULT;/* for copyin/out */ \ 104 frame->r1 = -1; /* for fetch/store */ \ 105 return; \ 106 } 107 108 109 void 110 trap(struct trapframe *frame) 111 { 112 u_int sig = 0, type = frame->trap, code = 0; 113 u_int rv, addr; 114 bool trapsig = true; 115 const bool usermode = USERMODE_P(frame);; 116 struct lwp *l; 117 struct proc *p; 118 u_quad_t oticks = 0; 119 struct vmspace *vm; 120 struct vm_map *map; 121 vm_prot_t ftype; 122 123 l = curlwp; 124 KASSERT(l != NULL); 125 p = l->l_proc; 126 KASSERT(p != NULL); 127 uvmexp.traps++; 128 if (usermode) { 129 type |= T_USER; 130 oticks = p->p_sticks; 131 l->l_addr->u_pcb.framep = frame; 132 LWP_CACHE_CREDS(l, p); 133 } 134 135 type &= ~(T_WRITE|T_PTEFETCH); 136 137 138 #ifdef TRAPDEBUG 139 if(frame->trap==7) goto fram; 140 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 141 frame->trap, frame->code, frame->pc, frame->psl); 142 fram: 143 #endif 144 switch (type) { 145 146 default: 147 #ifdef DDB 148 kdb_trap(frame); 149 #endif 150 panic("trap: type %x, code %x, pc %x, psl %x", 151 (u_int)frame->trap, (u_int)frame->code, 152 (u_int)frame->pc, (u_int)frame->psl); 153 154 case T_KSPNOTVAL: 155 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", 156 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", 157 mfpr(PR_KSP), (u_int)frame->pc, l->l_addr, 158 (u_int)frame->fp, (u_int)frame->psl); 159 160 case T_TRANSFLT|T_USER: 161 case T_TRANSFLT: 162 /* 163 * BUG! BUG! BUG! BUG! BUG! 164 * Due to a hardware bug (at in least KA65x CPUs) a double 165 * page table fetch trap will cause a translation fault 166 * even if access in the SPT PTE entry specifies 'no access'. 167 * In for example section 6.4.2 in VAX Architecture 168 * Reference Manual it states that if a page both are invalid 169 * and have no access set, a 'access violation fault' occurs. 170 * Therefore, we must fall through here... 171 */ 172 #ifdef nohwbug 173 panic("translation fault"); 174 #endif 175 176 case T_PTELEN|T_USER: /* Page table length exceeded */ 177 case T_ACCFLT|T_USER: 178 if (frame->code < 0) { /* Check for kernel space */ 179 sig = SIGSEGV; 180 code = SEGV_ACCERR; 181 break; 182 } 183 184 case T_PTELEN: 185 case T_ACCFLT: 186 #ifdef TRAPDEBUG 187 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 188 frame->trap, frame->code, frame->pc, frame->psl); 189 #endif 190 #ifdef DIAGNOSTIC 191 if (p == 0) 192 panic("trap: access fault: addr %lx code %lx", 193 frame->pc, frame->code); 194 if (frame->psl & PSL_IS) 195 panic("trap: pflt on IS"); 196 #endif 197 198 /* 199 * Page tables are allocated in pmap_enter(). We get 200 * info from below if it is a page table fault, but 201 * UVM may want to map in pages without faults, so 202 * because we must check for PTE pages anyway we don't 203 * bother doing it here. 204 */ 205 addr = trunc_page(frame->code); 206 if (!usermode && (frame->code < 0)) { 207 vm = NULL; 208 map = kernel_map; 209 210 } else { 211 vm = p->p_vmspace; 212 map = &vm->vm_map; 213 } 214 215 if (frame->trap & T_WRITE) 216 ftype = VM_PROT_WRITE; 217 else 218 ftype = VM_PROT_READ; 219 220 if (usermode) 221 KERNEL_LOCK(1, l); 222 else 223 KERNEL_LOCK(1, NULL); 224 225 rv = uvm_fault(map, addr, ftype); 226 if (rv != 0) { 227 if (!usermode) { 228 KERNEL_UNLOCK_ONE(NULL); 229 FAULTCHK; 230 panic("Segv in kernel mode: pc %x addr %x", 231 (u_int)frame->pc, (u_int)frame->code); 232 } 233 code = SEGV_ACCERR; 234 if (rv == ENOMEM) { 235 printf("UVM: pid %d (%s), uid %d killed: " 236 "out of swap\n", 237 p->p_pid, p->p_comm, 238 l->l_cred ? 239 kauth_cred_geteuid(l->l_cred) : -1); 240 sig = SIGKILL; 241 } else { 242 sig = SIGSEGV; 243 if (rv != EACCES) 244 code = SEGV_MAPERR; 245 } 246 } else { 247 trapsig = false; 248 if (map != kernel_map && addr > 0 249 && (void *)addr >= vm->vm_maxsaddr) 250 uvm_grow(p, addr); 251 } 252 if (usermode) 253 KERNEL_UNLOCK_LAST(l); 254 else 255 KERNEL_UNLOCK_ONE(NULL); 256 break; 257 258 case T_BPTFLT|T_USER: 259 sig = SIGTRAP; 260 code = TRAP_BRKPT; 261 break; 262 case T_TRCTRAP|T_USER: 263 sig = SIGTRAP; 264 code = TRAP_TRACE; 265 frame->psl &= ~PSL_T; 266 break; 267 268 case T_PRIVINFLT|T_USER: 269 sig = SIGILL; 270 code = ILL_PRVOPC; 271 break; 272 case T_RESADFLT|T_USER: 273 sig = SIGILL; 274 code = ILL_ILLADR; 275 break; 276 case T_RESOPFLT|T_USER: 277 sig = SIGILL; 278 code = ILL_ILLOPC; 279 break; 280 281 case T_XFCFLT|T_USER: 282 sig = SIGEMT; 283 break; 284 285 case T_ARITHFLT|T_USER: 286 sig = SIGFPE; 287 break; 288 289 case T_ASTFLT|T_USER: 290 mtpr(AST_NO,PR_ASTLVL); 291 trapsig = false; 292 break; 293 294 #ifdef DDB 295 case T_BPTFLT: /* Kernel breakpoint */ 296 case T_KDBTRAP: 297 case T_KDBTRAP|T_USER: 298 case T_TRCTRAP: 299 kdb_trap(frame); 300 return; 301 #endif 302 } 303 if (trapsig) { 304 ksiginfo_t ksi; 305 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 306 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 307 p->p_pid, l->l_lid, p->p_comm, sig, frame->trap, 308 frame->code, frame->pc, frame->psl); 309 KERNEL_LOCK(1, l); 310 KSI_INIT_TRAP(&ksi); 311 ksi.ksi_signo = sig; 312 ksi.ksi_trap = frame->trap; 313 ksi.ksi_addr = (void *)frame->code; 314 ksi.ksi_code = code; 315 trapsignal(l, &ksi); 316 KERNEL_UNLOCK_LAST(l); 317 } 318 319 if (!usermode) 320 return; 321 322 userret(l, frame, oticks); 323 } 324 325 void 326 setregs(struct lwp *l, struct exec_package *pack, u_long stack) 327 { 328 struct trapframe *exptr; 329 330 exptr = l->l_addr->u_pcb.framep; 331 exptr->pc = pack->ep_entry + 2; 332 exptr->sp = stack; 333 exptr->r6 = stack; /* for ELF */ 334 exptr->r7 = 0; /* for ELF */ 335 exptr->r8 = 0; /* for ELF */ 336 exptr->r9 = (u_long) l->l_proc->p_psstr; /* for ELF */ 337 } 338 339 340 /* 341 * Start a new LWP 342 */ 343 void 344 startlwp(void *arg) 345 { 346 int err; 347 ucontext_t *uc = arg; 348 struct lwp *l = curlwp; 349 350 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 351 #if DIAGNOSTIC 352 if (err) { 353 printf("Error %d from cpu_setmcontext.", err); 354 } 355 #endif 356 pool_put(&lwp_uc_pool, uc); 357 358 /* XXX - profiling spoiled here */ 359 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 360 } 361