1 /* $NetBSD: trap.c,v 1.103 2006/05/15 20:56:34 yamt 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.103 2006/05/15 20:56:34 yamt 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 } 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 printf("Trap: type %x, code %x, pc %x, psl %x\n", 151 (u_int)frame->trap, (u_int)frame->code, 152 (u_int)frame->pc, (u_int)frame->psl); 153 panic("trap"); 154 155 case T_KSPNOTVAL: 156 panic("kernel stack invalid"); 157 158 case T_TRANSFLT|T_USER: 159 case T_TRANSFLT: 160 /* 161 * BUG! BUG! BUG! BUG! BUG! 162 * Due to a hardware bug (at in least KA65x CPUs) a double 163 * page table fetch trap will cause a translation fault 164 * even if access in the SPT PTE entry specifies 'no access'. 165 * In for example section 6.4.2 in VAX Architecture 166 * Reference Manual it states that if a page both are invalid 167 * and have no access set, a 'access violation fault' occurs. 168 * Therefore, we must fall through here... 169 */ 170 #ifdef nohwbug 171 panic("translation fault"); 172 #endif 173 174 case T_PTELEN|T_USER: /* Page table length exceeded */ 175 case T_ACCFLT|T_USER: 176 if (frame->code < 0) { /* Check for kernel space */ 177 sig = SIGSEGV; 178 code = SEGV_ACCERR; 179 break; 180 } 181 182 case T_PTELEN: 183 case T_ACCFLT: 184 #ifdef TRAPDEBUG 185 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 186 frame->trap, frame->code, frame->pc, frame->psl); 187 #endif 188 #ifdef DIAGNOSTIC 189 if (p == 0) 190 panic("trap: access fault: addr %lx code %lx", 191 frame->pc, frame->code); 192 if (frame->psl & PSL_IS) 193 panic("trap: pflt on IS"); 194 #endif 195 196 /* 197 * Page tables are allocated in pmap_enter(). We get 198 * info from below if it is a page table fault, but 199 * UVM may want to map in pages without faults, so 200 * because we must check for PTE pages anyway we don't 201 * bother doing it here. 202 */ 203 addr = trunc_page(frame->code); 204 if ((umode == 0) && (frame->code < 0)) { 205 vm = NULL; 206 map = kernel_map; 207 } else { 208 vm = p->p_vmspace; 209 map = &vm->vm_map; 210 } 211 212 if (frame->trap & T_WRITE) 213 ftype = VM_PROT_WRITE; 214 else 215 ftype = VM_PROT_READ; 216 217 if (umode) { 218 KERNEL_PROC_LOCK(l); 219 if (l->l_flag & L_SA) { 220 l->l_savp->savp_faultaddr = (vaddr_t)frame->code; 221 l->l_flag |= L_SA_PAGEFAULT; 222 } 223 } else 224 KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE); 225 226 rv = uvm_fault(map, addr, ftype); 227 if (rv != 0) { 228 if (umode == 0) { 229 KERNEL_UNLOCK(); 230 FAULTCHK; 231 panic("Segv in kernel mode: pc %x addr %x", 232 (u_int)frame->pc, (u_int)frame->code); 233 } 234 code = SEGV_ACCERR; 235 if (rv == ENOMEM) { 236 printf("UVM: pid %d (%s), uid %d killed: " 237 "out of swap\n", 238 p->p_pid, p->p_comm, 239 p->p_cred ? 240 kauth_cred_geteuid(p->p_cred) : -1); 241 sig = SIGKILL; 242 } else { 243 sig = SIGSEGV; 244 if (rv != EACCES) 245 code = SEGV_MAPERR; 246 } 247 } else { 248 trapsig = 0; 249 if (map != kernel_map && (caddr_t)addr >= vm->vm_maxsaddr) 250 uvm_grow(p, addr); 251 } 252 if (umode) { 253 l->l_flag &= ~L_SA_PAGEFAULT; 254 KERNEL_PROC_UNLOCK(l); 255 } else 256 KERNEL_UNLOCK(); 257 break; 258 259 case T_BPTFLT|T_USER: 260 sig = SIGTRAP; 261 code = TRAP_BRKPT; 262 break; 263 case T_TRCTRAP|T_USER: 264 sig = SIGTRAP; 265 code = TRAP_TRACE; 266 frame->psl &= ~PSL_T; 267 break; 268 269 case T_PRIVINFLT|T_USER: 270 sig = SIGILL; 271 code = ILL_PRVOPC; 272 break; 273 case T_RESADFLT|T_USER: 274 sig = SIGILL; 275 code = ILL_ILLADR; 276 break; 277 case T_RESOPFLT|T_USER: 278 sig = SIGILL; 279 code = ILL_ILLOPC; 280 break; 281 282 case T_XFCFLT|T_USER: 283 sig = SIGEMT; 284 break; 285 286 case T_ARITHFLT|T_USER: 287 sig = SIGFPE; 288 break; 289 290 case T_ASTFLT|T_USER: 291 mtpr(AST_NO,PR_ASTLVL); 292 trapsig = 0; 293 break; 294 295 #ifdef DDB 296 case T_BPTFLT: /* Kernel breakpoint */ 297 case T_KDBTRAP: 298 case T_KDBTRAP|T_USER: 299 case T_TRCTRAP: 300 kdb_trap(frame); 301 return; 302 #endif 303 } 304 if (trapsig) { 305 ksiginfo_t ksi; 306 if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps) 307 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 308 p->p_pid, l->l_lid, p->p_comm, sig, frame->trap, 309 frame->code, frame->pc, frame->psl); 310 KERNEL_PROC_LOCK(l); 311 KSI_INIT_TRAP(&ksi); 312 ksi.ksi_signo = sig; 313 ksi.ksi_trap = frame->trap; 314 ksi.ksi_addr = (void *)frame->code; 315 ksi.ksi_code = code; 316 trapsignal(l, &ksi); 317 KERNEL_PROC_UNLOCK(l); 318 } 319 320 if (umode == 0) 321 return; 322 323 userret(l, frame, oticks); 324 } 325 326 void 327 setregs(struct lwp *l, struct exec_package *pack, u_long stack) 328 { 329 struct trapframe *exptr; 330 331 exptr = l->l_addr->u_pcb.framep; 332 exptr->pc = pack->ep_entry + 2; 333 exptr->sp = stack; 334 exptr->r6 = stack; /* for ELF */ 335 exptr->r7 = 0; /* for ELF */ 336 exptr->r8 = 0; /* for ELF */ 337 exptr->r9 = (u_long) l->l_proc->p_psstr; /* for ELF */ 338 } 339 340 341 /* 342 * Start a new LWP 343 */ 344 void 345 startlwp(arg) 346 void *arg; 347 { 348 int err; 349 ucontext_t *uc = arg; 350 struct lwp *l = curlwp; 351 352 err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 353 #if DIAGNOSTIC 354 if (err) { 355 printf("Error %d from cpu_setmcontext.", err); 356 } 357 #endif 358 pool_put(&lwp_uc_pool, uc); 359 360 /* XXX - profiling spoiled here */ 361 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 362 } 363 364 void 365 upcallret(struct lwp *l) 366 { 367 368 /* XXX - profiling */ 369 userret(l, l->l_addr->u_pcb.framep, l->l_proc->p_sticks); 370 } 371 372