1 /* $NetBSD: trap.c,v 1.105 2006/07/23 22:06:08 ad 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.105 2006/07/23 22:06:08 ad Exp $"); 37 38 #include "opt_ddb.h" 39 #include "opt_ktrace.h" 40 #include "opt_multiprocessor.h" 41 42 #include <sys/types.h> 43 #include <sys/param.h> 44 #include <sys/proc.h> 45 #include <sys/user.h> 46 #include <sys/syscall.h> 47 #include <sys/systm.h> 48 #include <sys/signalvar.h> 49 #include <sys/exec.h> 50 #include <sys/sa.h> 51 #include <sys/savar.h> 52 #include <sys/pool.h> 53 #include <sys/kauth.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <machine/mtpr.h> 58 #include <machine/pte.h> 59 #include <machine/pcb.h> 60 #include <machine/trap.h> 61 #include <machine/pmap.h> 62 #include <machine/cpu.h> 63 #include <machine/userret.h> 64 65 #ifdef DDB 66 #include <machine/db_machdep.h> 67 #endif 68 #include <kern/syscalls.c> 69 #ifdef KTRACE 70 #include <sys/ktrace.h> 71 #endif 72 73 #ifdef TRAPDEBUG 74 volatile int faultdebug = 0; 75 #endif 76 77 int cpu_printfataltraps = 0; 78 79 void trap (struct trapframe *); 80 81 const char * const traptypes[]={ 82 "reserved addressing", 83 "privileged instruction", 84 "reserved operand", 85 "breakpoint instruction", 86 "XFC instruction", 87 "system call ", 88 "arithmetic trap", 89 "asynchronous system trap", 90 "page table length fault", 91 "translation violation fault", 92 "trace trap", 93 "compatibility mode fault", 94 "access violation fault", 95 "", 96 "", 97 "KSP invalid", 98 "", 99 "kernel debugger trap" 100 }; 101 int no_traps = 18; 102 103 #define USERMODE(framep) ((((framep)->psl) & (PSL_U)) == PSL_U) 104 #define FAULTCHK \ 105 if (l->l_addr->u_pcb.iftrap) { \ 106 frame->pc = (unsigned)l->l_addr->u_pcb.iftrap; \ 107 frame->psl &= ~PSL_FPD; \ 108 frame->r0 = EFAULT;/* for copyin/out */ \ 109 frame->r1 = -1; /* for fetch/store */ \ 110 return; \ 111 } 112 113 114 void 115 trap(struct trapframe *frame) 116 { 117 u_int sig = 0, type = frame->trap, trapsig = 1, code = 0; 118 u_int rv, addr, umode; 119 struct lwp *l; 120 struct proc *p = NULL; 121 u_quad_t oticks = 0; 122 struct vmspace *vm; 123 struct vm_map *map; 124 vm_prot_t ftype; 125 126 if ((l = curlwp) != NULL) 127 p = l->l_proc; 128 uvmexp.traps++; 129 if ((umode = USERMODE(frame))) { 130 type |= T_USER; 131 oticks = p->p_sticks; 132 l->l_addr->u_pcb.framep = frame; 133 LWP_CACHE_CREDS(l, p); 134 } 135 136 type&=~(T_WRITE|T_PTEFETCH); 137 138 139 #ifdef TRAPDEBUG 140 if(frame->trap==7) goto fram; 141 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 142 frame->trap, frame->code, frame->pc, frame->psl); 143 fram: 144 #endif 145 switch(type){ 146 147 default: 148 #ifdef DDB 149 kdb_trap(frame); 150 #endif 151 printf("Trap: type %x, code %x, pc %x, psl %x\n", 152 (u_int)frame->trap, (u_int)frame->code, 153 (u_int)frame->pc, (u_int)frame->psl); 154 panic("trap"); 155 156 case T_KSPNOTVAL: 157 panic("kernel stack invalid"); 158 159 case T_TRANSFLT|T_USER: 160 case T_TRANSFLT: 161 /* 162 * BUG! BUG! BUG! BUG! BUG! 163 * Due to a hardware bug (at in least KA65x CPUs) a double 164 * page table fetch trap will cause a translation fault 165 * even if access in the SPT PTE entry specifies 'no access'. 166 * In for example section 6.4.2 in VAX Architecture 167 * Reference Manual it states that if a page both are invalid 168 * and have no access set, a 'access violation fault' occurs. 169 * Therefore, we must fall through here... 170 */ 171 #ifdef nohwbug 172 panic("translation fault"); 173 #endif 174 175 case T_PTELEN|T_USER: /* Page table length exceeded */ 176 case T_ACCFLT|T_USER: 177 if (frame->code < 0) { /* Check for kernel space */ 178 sig = SIGSEGV; 179 code = SEGV_ACCERR; 180 break; 181 } 182 183 case T_PTELEN: 184 case T_ACCFLT: 185 #ifdef TRAPDEBUG 186 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 187 frame->trap, frame->code, frame->pc, frame->psl); 188 #endif 189 #ifdef DIAGNOSTIC 190 if (p == 0) 191 panic("trap: access fault: addr %lx code %lx", 192 frame->pc, frame->code); 193 if (frame->psl & PSL_IS) 194 panic("trap: pflt on IS"); 195 #endif 196 197 /* 198 * Page tables are allocated in pmap_enter(). We get 199 * info from below if it is a page table fault, but 200 * UVM may want to map in pages without faults, so 201 * because we must check for PTE pages anyway we don't 202 * bother doing it here. 203 */ 204 addr = trunc_page(frame->code); 205 if ((umode == 0) && (frame->code < 0)) { 206 vm = NULL; 207 map = kernel_map; 208 } else { 209 vm = p->p_vmspace; 210 map = &vm->vm_map; 211 } 212 213 if (frame->trap & T_WRITE) 214 ftype = VM_PROT_WRITE; 215 else 216 ftype = VM_PROT_READ; 217 218 if (umode) { 219 KERNEL_PROC_LOCK(l); 220 if (l->l_flag & L_SA) { 221 l->l_savp->savp_faultaddr = (vaddr_t)frame->code; 222 l->l_flag |= L_SA_PAGEFAULT; 223 } 224 } else 225 KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); 226 227 rv = uvm_fault(map, addr, ftype); 228 if (rv != 0) { 229 if (umode == 0) { 230 KERNEL_UNLOCK(); 231 FAULTCHK; 232 panic("Segv in kernel mode: pc %x addr %x", 233 (u_int)frame->pc, (u_int)frame->code); 234 } 235 code = SEGV_ACCERR; 236 if (rv == ENOMEM) { 237 printf("UVM: pid %d (%s), uid %d killed: " 238 "out of swap\n", 239 p->p_pid, p->p_comm, 240 l->l_cred ? 241 kauth_cred_geteuid(l->l_cred) : -1); 242 sig = SIGKILL; 243 } else { 244 sig = SIGSEGV; 245 if (rv != EACCES) 246 code = SEGV_MAPERR; 247 } 248 } else { 249 trapsig = 0; 250 if (map != kernel_map && (caddr_t)addr >= vm->vm_maxsaddr) 251 uvm_grow(p, addr); 252 } 253 if (umode) { 254 l->l_flag &= ~L_SA_PAGEFAULT; 255 KERNEL_PROC_UNLOCK(l); 256 } else 257 KERNEL_UNLOCK(); 258 break; 259 260 case T_BPTFLT|T_USER: 261 sig = SIGTRAP; 262 code = TRAP_BRKPT; 263 break; 264 case T_TRCTRAP|T_USER: 265 sig = SIGTRAP; 266 code = TRAP_TRACE; 267 frame->psl &= ~PSL_T; 268 break; 269 270 case T_PRIVINFLT|T_USER: 271 sig = SIGILL; 272 code = ILL_PRVOPC; 273 break; 274 case T_RESADFLT|T_USER: 275 sig = SIGILL; 276 code = ILL_ILLADR; 277 break; 278 case T_RESOPFLT|T_USER: 279 sig = SIGILL; 280 code = ILL_ILLOPC; 281 break; 282 283 case T_XFCFLT|T_USER: 284 sig = SIGEMT; 285 break; 286 287 case T_ARITHFLT|T_USER: 288 sig = SIGFPE; 289 break; 290 291 case T_ASTFLT|T_USER: 292 mtpr(AST_NO,PR_ASTLVL); 293 trapsig = 0; 294 break; 295 296 #ifdef DDB 297 case T_BPTFLT: /* Kernel breakpoint */ 298 case T_KDBTRAP: 299 case T_KDBTRAP|T_USER: 300 case T_TRCTRAP: 301 kdb_trap(frame); 302 return; 303 #endif 304 } 305 if (trapsig) { 306 ksiginfo_t ksi; 307 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 308 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 309 p->p_pid, l->l_lid, p->p_comm, sig, frame->trap, 310 frame->code, frame->pc, frame->psl); 311 KERNEL_PROC_LOCK(l); 312 KSI_INIT_TRAP(&ksi); 313 ksi.ksi_signo = sig; 314 ksi.ksi_trap = frame->trap; 315 ksi.ksi_addr = (void *)frame->code; 316 ksi.ksi_code = code; 317 trapsignal(l, &ksi); 318 KERNEL_PROC_UNLOCK(l); 319 } 320 321 if (umode == 0) 322 return; 323 324 userret(l, frame, oticks); 325 } 326 327 void 328 setregs(struct lwp *l, struct exec_package *pack, u_long stack) 329 { 330 struct trapframe *exptr; 331 332 exptr = l->l_addr->u_pcb.framep; 333 exptr->pc = pack->ep_entry + 2; 334 exptr->sp = stack; 335 exptr->r6 = stack; /* for ELF */ 336 exptr->r7 = 0; /* for ELF */ 337 exptr->r8 = 0; /* for ELF */ 338 exptr->r9 = (u_long) l->l_proc->p_psstr; /* for ELF */ 339 } 340 341 342 /* 343 * Start a new LWP 344 */ 345 void 346 startlwp(arg) 347 void *arg; 348 { 349 int err; 350 ucontext_t *uc = arg; 351 struct lwp *l = curlwp; 352 353 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 354 #if DIAGNOSTIC 355 if (err) { 356 printf("Error %d from cpu_setmcontext.", err); 357 } 358 #endif 359 pool_put(&lwp_uc_pool, uc); 360 361 /* XXX - profiling spoiled here */ 362 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 363 } 364 365 void 366 upcallret(struct lwp *l) 367 { 368 369 /* XXX - profiling */ 370 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 371 } 372 373