1/* $NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* All bugs are subject to removal without further notice */ 29 30#include <sys/cdefs.h> 31__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 ad Exp $"); 32 33#include "opt_ddb.h" 34#include "opt_multiprocessor.h" 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/cpu.h> 39#include <sys/exec.h> 40#include <sys/kauth.h> 41#include <sys/proc.h> 42#include <sys/signalvar.h> 43 44#include <uvm/uvm_extern.h> 45 46#include <machine/trap.h> 47#include <machine/userret.h> 48 49#ifdef DDB 50#include <machine/db_machdep.h> 51#endif 52#include <vax/vax/db_disasm.h> 53#include <kern/syscalls.c> 54#include <sys/ktrace.h> 55 56#ifdef TRAPDEBUG 57volatile int faultdebug = 0; 58#endif 59 60int cpu_printfataltraps = 0; 61 62void trap (struct trapframe *); 63 64const char * const traptypes[]={ 65 "reserved addressing", 66 "privileged instruction", 67 "reserved operand", 68 "breakpoint instruction", 69 "XFC instruction", 70 "system call ", 71 "arithmetic trap", 72 "asynchronous system trap", 73 "page table length fault", 74 "translation violation fault", 75 "trace trap", 76 "compatibility mode fault", 77 "access violation fault", 78 "", 79 "", 80 "KSP invalid", 81 "", 82 "kernel debugger trap" 83}; 84int no_traps = 18; 85 86#define USERMODE_P(tf) ((((tf)->tf_psl) & (PSL_U)) == PSL_U) 87 88void 89trap(struct trapframe *tf) 90{ 91 u_int sig = 0, type = tf->tf_trap, code = 0; 92 u_int rv, addr; 93 bool trapsig = true; 94 const bool usermode = USERMODE_P(tf); 95 struct lwp * const l = curlwp; 96 struct proc * const p = l->l_proc; 97 struct pcb * const pcb = lwp_getpcb(l); 98 u_quad_t oticks = 0; 99 struct vmspace *vm; 100 struct vm_map *map; 101 vm_prot_t ftype; 102 void *onfault = pcb->pcb_onfault; 103 104 KASSERT(p != NULL); 105 curcpu()->ci_data.cpu_ntrap++; 106 if (usermode) { 107 type |= T_USER; 108 oticks = p->p_sticks; 109 l->l_md.md_utf = tf; 110 } 111 112 type &= ~(T_WRITE|T_PTEFETCH); 113 114 115#ifdef TRAPDEBUG 116if(tf->tf_trap==7) goto fram; 117if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n", 118 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 119fram: 120#endif 121 switch (type) { 122 123 default: 124#ifdef DDB 125 kdb_trap(tf); 126#endif 127 panic("trap: type %x, code %x, pc %x, psl %x", 128 (u_int)tf->tf_trap, (u_int)tf->tf_code, 129 (u_int)tf->tf_pc, (u_int)tf->tf_psl); 130 131 case T_KSPNOTVAL: 132 panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)", 133 p->p_pid, l->l_lid, l->l_name ? l->l_name : "??", 134 mfpr(PR_KSP), (u_int)tf->tf_pc, pcb, 135 (u_int)tf->tf_fp, (u_int)tf->tf_psl); 136 137 case T_TRANSFLT|T_USER: 138 case T_TRANSFLT: 139 /* 140 * BUG! BUG! BUG! BUG! BUG! 141 * Due to a hardware bug (at in least KA65x CPUs) a double 142 * page table fetch trap will cause a translation fault 143 * even if access in the SPT PTE entry specifies 'no access'. 144 * In for example section 6.4.2 in VAX Architecture 145 * Reference Manual it states that if a page both are invalid 146 * and have no access set, a 'access violation fault' occurs. 147 * Therefore, we must fall through here... 148 */ 149#ifdef nohwbug 150 panic("translation fault"); 151#endif 152 153 case T_PTELEN|T_USER: /* Page table length exceeded */ 154 case T_ACCFLT|T_USER: 155 if (tf->tf_code < 0) { /* Check for kernel space */ 156 sig = SIGSEGV; 157 code = SEGV_ACCERR; 158 break; 159 } 160 161 case T_PTELEN: 162#ifndef MULTIPROCESSOR 163 /* 164 * If we referred to an address beyond the end of the system 165 * page table, it may be due to a failed CAS 166 * restartable-atomic-sequence. If it is, restart it at the 167 * beginning and restart. 168 */ 169 { 170 extern const uint8_t cas32_ras_start[], cas32_ras_end[]; 171 if (tf->tf_code == CASMAGIC 172 && tf->tf_pc >= (uintptr_t) cas32_ras_start 173 && tf->tf_pc < (uintptr_t) cas32_ras_end) { 174 tf->tf_pc = (uintptr_t) cas32_ras_start; 175 trapsig = false; 176 break; 177 } 178 } 179 /* FALLTHROUGH */ 180#endif 181 case T_ACCFLT: 182#ifdef TRAPDEBUG 183if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n", 184 tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl); 185#endif 186#ifdef DIAGNOSTIC 187 if (p == 0) 188 panic("trap: access fault: addr %lx code %lx", 189 tf->tf_pc, tf->tf_code); 190 if (tf->tf_psl & PSL_IS) 191 panic("trap: pflt on IS"); 192#endif 193 194 /* 195 * Page tables are allocated in pmap_enter(). We get 196 * info from below if it is a page table fault, but 197 * UVM may want to map in pages without faults, so 198 * because we must check for PTE pages anyway we don't 199 * bother doing it here. 200 */ 201 addr = trunc_page(tf->tf_code); 202 if (!usermode && (tf->tf_code < 0)) { 203 vm = NULL; 204 map = kernel_map; 205 206 } else { 207 vm = p->p_vmspace; 208 map = &vm->vm_map; 209 } 210 211 if (tf->tf_trap & T_WRITE) 212 ftype = VM_PROT_WRITE; 213 else 214 ftype = VM_PROT_READ; 215 216 pcb->pcb_onfault = NULL; 217 rv = uvm_fault(map, addr, ftype); 218 pcb->pcb_onfault = onfault; 219 if (rv != 0) { 220 if (!usermode) { 221 if (onfault) { 222 pcb->pcb_onfault = NULL; 223 tf->tf_pc = (unsigned)onfault; 224 tf->tf_psl &= ~PSL_FPD; 225 tf->tf_r0 = rv; 226 return; 227 } 228 printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ", 229 tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3); 230 printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", 231 tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7); 232 printf( 233 "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", 234 tf->tf_r8, tf->tf_r9, tf->tf_r10, 235 tf->tf_r11); 236 printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n", 237 tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc); 238 panic("SEGV in kernel mode: pc %#lx addr %#lx", 239 tf->tf_pc, tf->tf_code); 240 } 241 switch (rv) { 242 case ENOMEM: 243 printf("UVM: pid %d (%s), uid %d killed: " 244 "out of swap\n", 245 p->p_pid, p->p_comm, 246 l->l_cred ? 247 kauth_cred_geteuid(l->l_cred) : -1); 248 sig = SIGKILL; 249 code = SI_NOINFO; 250 break; 251 case EINVAL: 252 code = BUS_ADRERR; 253 sig = SIGBUS; 254 break; 255 case EACCES: 256 code = SEGV_ACCERR; 257 sig = SIGSEGV; 258 break; 259 default: 260 code = SEGV_MAPERR; 261 sig = SIGSEGV; 262 break; 263 } 264 } else { 265 trapsig = false; 266 if (map != kernel_map && addr > 0 267 && (void *)addr >= vm->vm_maxsaddr) 268 uvm_grow(p, addr); 269 } 270 break; 271 272 case T_BPTFLT|T_USER: 273 sig = SIGTRAP; 274 code = TRAP_BRKPT; 275 break; 276 case T_TRCTRAP|T_USER: 277 sig = SIGTRAP; 278 code = TRAP_TRACE; 279 tf->tf_psl &= ~PSL_T; 280 break; 281 282 case T_PRIVINFLT|T_USER: 283 sig = SIGILL; 284 code = ILL_PRVOPC; 285 break; 286 case T_RESADFLT|T_USER: 287 sig = SIGILL; 288 code = ILL_ILLADR; 289 break; 290 case T_RESOPFLT|T_USER: 291 sig = SIGILL; 292 code = ILL_ILLOPC; 293 break; 294 295 case T_XFCFLT|T_USER: 296 sig = SIGEMT; 297 break; 298 299 case T_ARITHFLT|T_USER: 300 sig = SIGFPE; 301 switch (tf->tf_code) { 302 case ATRP_INTOVF: code = FPE_INTOVF; break; 303 case ATRP_INTDIV: code = FPE_INTDIV; break; 304 case ATRP_FLTOVF: code = FPE_FLTOVF; break; 305 case ATRP_FLTDIV: code = FPE_FLTDIV; break; 306 case ATRP_FLTUND: code = FPE_FLTUND; break; 307 case ATRP_DECOVF: code = FPE_INTOVF; break; 308 case ATRP_FLTSUB: code = FPE_FLTSUB; break; 309 case AFLT_FLTDIV: code = FPE_FLTDIV; break; 310 case AFLT_FLTUND: code = FPE_FLTUND; break; 311 case AFLT_FLTOVF: code = FPE_FLTOVF; break; 312 default: code = FPE_FLTINV; break; 313 } 314 break; 315 316 case T_ASTFLT|T_USER: 317 pcb->P0LR = (pcb->P0LR & ~AST_MASK) | AST_PCB; 318 mtpr(AST_NO,PR_ASTLVL); 319 trapsig = false; 320 break; 321 322#ifdef DDB 323 case T_BPTFLT: /* Kernel breakpoint */ 324 case T_KDBTRAP: 325 case T_KDBTRAP|T_USER: 326 case T_TRCTRAP: 327 kdb_trap(tf); 328 return; 329#endif 330 } 331 if (trapsig) { 332 ksiginfo_t ksi; 333 if ((sig == SIGSEGV || sig == SIGILL) 334 && cpu_printfataltraps 335 && (p->p_slflag & PSL_TRACED) == 0 336 && !sigismember(&p->p_sigctx.ps_sigcatch, sig)) 337 printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n", 338 p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap, 339 tf->tf_code, tf->tf_pc, tf->tf_psl); 340 KSI_INIT_TRAP(&ksi); 341 ksi.ksi_signo = sig; 342 ksi.ksi_trap = tf->tf_trap; 343 ksi.ksi_addr = (void *)tf->tf_code; 344 ksi.ksi_code = code; 345 346 /* 347 * Arithmetic exceptions can be of two kinds: 348 * - traps (codes 1..7), where pc points to the 349 * next instruction to execute. 350 * - faults (codes 8..10), where pc points to the 351 * faulting instruction. 352 * In the latter case, we need to advance pc by ourselves 353 * to prevent a signal loop. 354 * 355 * XXX this is gross -- miod 356 */ 357 if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8)) 358 tf->tf_pc = skip_opcode(tf->tf_pc); 359 360 trapsignal(l, &ksi); 361 } 362 363 if (!usermode) 364 return; 365 366 userret(l, tf, oticks); 367} 368 369void 370setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 371{ 372 struct trapframe * const tf = l->l_md.md_utf; 373 374 tf->tf_pc = pack->ep_entry + 2; 375 tf->tf_sp = stack; 376 tf->tf_r6 = stack; /* for ELF */ 377 tf->tf_r7 = 0; /* for ELF */ 378 tf->tf_r8 = 0; /* for ELF */ 379 tf->tf_r9 = l->l_proc->p_psstrp; /* for ELF */ 380} 381 382 383/* 384 * Start a new LWP 385 */ 386void 387startlwp(void *arg) 388{ 389 ucontext_t * const uc = arg; 390 lwp_t * const l = curlwp; 391 int error __diagused; 392 393 error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); 394 KASSERT(error == 0); 395 396 kmem_free(uc, sizeof(ucontext_t)); 397 /* XXX - profiling spoiled here */ 398 userret(l, l->l_md.md_utf, l->l_proc->p_sticks); 399} 400