1 /* $NetBSD: trap.c,v 1.225 2011/01/17 15:32:59 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department and Ralph Campbell. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: Utah Hdr: trap.c 1.32 91/04/06 36 * 37 * @(#)trap.c 8.5 (Berkeley) 1/11/94 38 */ 39 /* 40 * Copyright (c) 1988 University of Utah. 41 * 42 * This code is derived from software contributed to Berkeley by 43 * the Systems Programming Group of the University of Utah Computer 44 * Science Department and Ralph Campbell. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * from: Utah Hdr: trap.c 1.32 91/04/06 75 * 76 * @(#)trap.c 8.5 (Berkeley) 1/11/94 77 */ 78 79 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 80 81 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.225 2011/01/17 15:32:59 tsutsui Exp $"); 82 83 #include "opt_cputype.h" /* which mips CPU levels do we support? */ 84 #include "opt_ddb.h" 85 #include "opt_kgdb.h" 86 87 #include <sys/param.h> 88 #include <sys/systm.h> 89 #include <sys/kernel.h> 90 #include <sys/proc.h> 91 #include <sys/ras.h> 92 #include <sys/signalvar.h> 93 #include <sys/syscall.h> 94 #include <sys/buf.h> 95 #include <sys/ktrace.h> 96 #include <sys/sa.h> 97 #include <sys/savar.h> 98 #include <sys/kauth.h> 99 #include <sys/cpu.h> 100 101 #include <mips/cache.h> 102 #include <mips/locore.h> 103 #include <mips/mips_opcode.h> 104 105 #include <uvm/uvm.h> 106 107 #include <machine/cpu.h> 108 #include <mips/trap.h> 109 #include <mips/reg.h> 110 #include <mips/regnum.h> /* symbolic register indices */ 111 #include <mips/pcb.h> 112 #include <mips/pte.h> 113 #include <mips/psl.h> 114 #include <mips/userret.h> 115 116 #ifdef DDB 117 #include <machine/db_machdep.h> 118 #include <ddb/db_sym.h> 119 #endif 120 121 #ifdef KGDB 122 #include <sys/kgdb.h> 123 #endif 124 125 const char * const trap_type[] = { 126 "external interrupt", 127 "TLB modification", 128 "TLB miss (load or instr. fetch)", 129 "TLB miss (store)", 130 "address error (load or I-fetch)", 131 "address error (store)", 132 "bus error (I-fetch)", 133 "bus error (load or store)", 134 "system call", 135 "breakpoint", 136 "reserved instruction", 137 "coprocessor unusable", 138 "arithmetic overflow", 139 "r4k trap/r3k reserved 13", 140 "r4k virtual coherency instruction/r3k reserved 14", 141 "r4k floating point/ r3k reserved 15", 142 "reserved 16", 143 "reserved 17", 144 "mipsNN cp2 exception", 145 "reserved 19", 146 "reserved 20", 147 "reserved 21", 148 "mips64 MDMX", 149 "r4k watch", 150 "mipsNN machine check", 151 "reserved 25", 152 "reserved 26", 153 "reserved 27", 154 "reserved 28", 155 "reserved 29", 156 "mipsNN cache error", 157 "r4000 virtual coherency data", 158 }; 159 160 void trap(unsigned int, unsigned int, vaddr_t, vaddr_t, struct trapframe *); 161 void ast(unsigned int); 162 163 vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned int, int); /* XXX */ 164 void MachEmulateInst(uint32_t, uint32_t, vaddr_t, struct frame *); /* XXX */ 165 void MachFPTrap(uint32_t, uint32_t, vaddr_t, struct frame *); /* XXX */ 166 167 /* 168 * fork syscall returns directly to user process via lwp_trampoline(), 169 * which will be called the very first time when child gets running. 170 */ 171 void 172 child_return(void *arg) 173 { 174 struct lwp *l = arg; 175 struct frame *frame = l->l_md.md_regs; 176 177 frame->f_regs[_R_V0] = 0; 178 frame->f_regs[_R_V1] = 1; 179 frame->f_regs[_R_A3] = 0; 180 userret(l); 181 ktrsysret(SYS_fork, 0, 0); 182 } 183 184 #ifdef MIPS3_PLUS 185 #define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT) 186 #else 187 #define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT) 188 #endif 189 #define KERNLAND(x) ((intptr_t)(x) < 0) 190 191 /* 192 * Trap is called from locore to handle most types of processor traps. 193 * System calls are broken out for efficiency. MIPS can handle software 194 * interrupts as a part of real interrupt processing. 195 */ 196 void 197 trap(unsigned int status, unsigned int cause, vaddr_t vaddr, vaddr_t opc, 198 struct trapframe *frame) 199 { 200 int type, rv; 201 struct lwp *l = curlwp; 202 struct proc *p = curproc; 203 struct pcb *pcb; 204 void *onfault; 205 vm_prot_t ftype; 206 vaddr_t va; 207 ksiginfo_t ksi; 208 struct frame *fp; 209 extern void fswintrberr(void); 210 KSI_INIT_TRAP(&ksi); 211 212 curcpu()->ci_data.cpu_ntrap++; 213 type = TRAPTYPE(cause); 214 if (USERMODE(status)) { 215 type |= T_USER; 216 LWP_CACHE_CREDS(l, p); 217 } 218 219 if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV)) { 220 if (type != T_BREAK) { 221 #ifdef IPL_ICU_MASK 222 spllowersofthigh(); 223 #else 224 _splset((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 225 #endif 226 } 227 } 228 229 switch (type) { 230 default: 231 dopanic: 232 (void)splhigh(); 233 printf("pid %d(%s): ", p->p_pid, p->p_comm); 234 printf("trap: %s in %s mode\n", 235 trap_type[TRAPTYPE(cause)], 236 USERMODE(status) ? "user" : "kernel"); 237 printf("status=0x%x, cause=0x%x, epc=%#" PRIxVADDR 238 ", vaddr=%#" PRIxVADDR, status, cause, opc, vaddr); 239 if (USERMODE(status)) { 240 fp = l->l_md.md_regs; 241 printf(" frame=%p usp=%#" PRIxREGISTER 242 " ra=%#" PRIxREGISTER "\n", 243 fp, fp->f_regs[_R_SP], fp->f_regs[_R_RA]); 244 } else { 245 printf(" tf=%p ksp=%p ra=%#" PRIxREGISTER "\n", 246 frame, frame+1, frame->tf_regs[TF_RA]); 247 } 248 249 #if defined(DDB) 250 kdb_trap(type, frame->tf_regs); 251 /* XXX force halt XXX */ 252 #elif defined(KGDB) 253 { 254 struct frame *f = (struct frame *)&ddb_regs; 255 extern mips_reg_t kgdb_cause, kgdb_vaddr; 256 kgdb_cause = cause; 257 kgdb_vaddr = vaddr; 258 259 /* 260 * init global ddb_regs, used in db_interface.c routines 261 * shared between ddb and gdb. Send ddb_regs to gdb so 262 * that db_machdep.h macros will work with it, and 263 * allow gdb to alter the PC. 264 */ 265 db_set_ddb_regs(type, (mips_reg_t *) frame); 266 PC_BREAK_ADVANCE(f); 267 if (kgdb_trap(type, &ddb_regs)) { 268 frame->tf_regs[TF_EPC] = f->f_regs[_R_PC]; 269 return; 270 } 271 } 272 #else 273 panic("trap"); 274 #endif 275 /*NOTREACHED*/ 276 case T_TLB_MOD: 277 if (KERNLAND(vaddr)) { 278 pt_entry_t *pte; 279 unsigned entry; 280 paddr_t pa; 281 282 pte = kvtopte(vaddr); 283 entry = pte->pt_entry; 284 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { 285 panic("ktlbmod: invalid pte"); 286 } 287 if (entry & mips_pg_ro_bit()) { 288 /* write to read only page in the kernel */ 289 ftype = VM_PROT_WRITE; 290 goto kernelfault; 291 } 292 entry |= mips_pg_m_bit(); 293 pte->pt_entry = entry; 294 vaddr &= ~PGOFSET; 295 MachTLBUpdate(vaddr, entry); 296 pa = mips_tlbpfn_to_paddr(entry); 297 #if defined(DIAGNOSTIC) 298 if (!uvm_pageismanaged(pa)) { 299 panic("ktlbmod: unmanaged page:" 300 " va %#" PRIxVADDR " pa %#"PRIxPADDR, 301 vaddr, pa); 302 } 303 #endif 304 pmap_set_modified(pa); 305 return; /* KERN */ 306 } 307 /*FALLTHROUGH*/ 308 case T_TLB_MOD+T_USER: 309 { 310 pt_entry_t *pte; 311 unsigned entry; 312 paddr_t pa; 313 pmap_t pmap; 314 315 pmap = p->p_vmspace->vm_map.pmap; 316 if (!(pte = pmap_segmap(pmap, vaddr))) 317 panic("utlbmod: invalid segmap"); 318 pte += (vaddr >> PGSHIFT) & (NPTEPG - 1); 319 entry = pte->pt_entry; 320 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) 321 panic("utlbmod: invalid pte"); 322 323 if (entry & mips_pg_ro_bit()) { 324 /* write to read only page */ 325 ftype = VM_PROT_WRITE; 326 goto pagefault; 327 } 328 entry |= mips_pg_m_bit(); 329 pte->pt_entry = entry; 330 vaddr = (vaddr & ~PGOFSET) | 331 (pmap->pm_asid << MIPS_TLB_PID_SHIFT); 332 MachTLBUpdate(vaddr, entry); 333 pa = mips_tlbpfn_to_paddr(entry); 334 #if defined(DIAGNOSTIC) 335 if (!uvm_pageismanaged(pa)) { 336 panic("utlbmod: unmanaged page:" 337 " va %#"PRIxVADDR" pa %#"PRIxPADDR, 338 vaddr, pa); 339 } 340 #endif 341 pmap_set_modified(pa); 342 if (type & T_USER) 343 userret(l); 344 return; /* GEN */ 345 } 346 case T_TLB_LD_MISS: 347 case T_TLB_ST_MISS: 348 ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE; 349 if (KERNLAND(vaddr)) 350 goto kernelfault; 351 /* 352 * It is an error for the kernel to access user space except 353 * through the copyin/copyout routines. 354 */ 355 if (l == NULL) { 356 goto dopanic; 357 } 358 pcb = lwp_getpcb(l); 359 if (pcb->pcb_onfault == NULL) { 360 goto dopanic; 361 } 362 /* check for fuswintr() or suswintr() getting a page fault */ 363 if (pcb->pcb_onfault == (void *)fswintrberr) { 364 frame->tf_regs[TF_EPC] = (intptr_t)fswintrberr; 365 return; /* KERN */ 366 } 367 goto pagefault; 368 case T_TLB_LD_MISS+T_USER: 369 ftype = VM_PROT_READ; 370 goto pagefault; 371 case T_TLB_ST_MISS+T_USER: 372 ftype = VM_PROT_WRITE; 373 pagefault: ; 374 { 375 struct vmspace *vm; 376 struct vm_map *map; 377 378 pcb = lwp_getpcb(l); 379 onfault = pcb->pcb_onfault; 380 vm = p->p_vmspace; 381 map = &vm->vm_map; 382 va = trunc_page(vaddr); 383 384 if ((l->l_flag & LW_SA) && (~l->l_pflag & LP_SA_NOBLOCK)) { 385 l->l_savp->savp_faultaddr = (vaddr_t)vaddr; 386 l->l_pflag |= LP_SA_PAGEFAULT; 387 } 388 389 pcb->pcb_onfault = NULL; 390 if (p->p_emul->e_fault) 391 rv = (*p->p_emul->e_fault)(p, va, ftype); 392 else 393 rv = uvm_fault(map, va, ftype); 394 pcb->pcb_onfault = onfault; 395 396 #ifdef VMFAULT_TRACE 397 printf( 398 "uvm_fault(%p (pmap %p), %#"PRIxVADDR 399 " (0x%x), %d) -> %d at pc %#"PRIxVADDR"\n", 400 map, vm->vm_map.pmap, va, vaddr, ftype, rv, opc); 401 #endif 402 /* 403 * If this was a stack access we keep track of the maximum 404 * accessed stack size. Also, if vm_fault gets a protection 405 * failure it is due to accessing the stack region outside 406 * the current limit and we need to reflect that as an access 407 * error. 408 */ 409 if ((void *)va >= vm->vm_maxsaddr) { 410 if (rv == 0) 411 uvm_grow(p, va); 412 else if (rv == EACCES) 413 rv = EFAULT; 414 } 415 l->l_pflag &= ~LP_SA_PAGEFAULT; 416 if (rv == 0) { 417 if (type & T_USER) { 418 userret(l); 419 } 420 return; /* GEN */ 421 } 422 if ((type & T_USER) == 0) 423 goto copyfault; 424 if (rv == ENOMEM) { 425 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 426 p->p_pid, p->p_comm, 427 l->l_cred ? 428 kauth_cred_geteuid(l->l_cred) : (uid_t) -1); 429 ksi.ksi_signo = SIGKILL; 430 ksi.ksi_code = 0; 431 } else { 432 if (rv == EACCES) { 433 ksi.ksi_signo = SIGBUS; 434 ksi.ksi_code = BUS_OBJERR; 435 } else { 436 ksi.ksi_signo = SIGSEGV; 437 ksi.ksi_code = SEGV_MAPERR; 438 } 439 } 440 ksi.ksi_trap = type & ~T_USER; 441 ksi.ksi_addr = (void *)vaddr; 442 break; /* SIGNAL */ 443 } 444 kernelfault: ; 445 pcb = lwp_getpcb(l); 446 onfault = pcb->pcb_onfault; 447 448 va = trunc_page(vaddr); 449 pcb->pcb_onfault = NULL; 450 rv = uvm_fault(kernel_map, va, ftype); 451 pcb->pcb_onfault = onfault; 452 if (rv == 0) 453 return; /* KERN */ 454 goto copyfault; 455 case T_ADDR_ERR_LD: /* misaligned access */ 456 case T_ADDR_ERR_ST: /* misaligned access */ 457 case T_BUS_ERR_LD_ST: /* BERR asserted to CPU */ 458 pcb = lwp_getpcb(l); 459 onfault = pcb->pcb_onfault; 460 rv = EFAULT; 461 copyfault: 462 if (onfault == NULL) { 463 goto dopanic; 464 } 465 frame->tf_regs[TF_EPC] = (intptr_t)onfault; 466 frame->tf_regs[TF_V0] = rv; 467 return; /* KERN */ 468 469 case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ 470 case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ 471 case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to CPU */ 472 case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to CPU */ 473 ksi.ksi_trap = type & ~T_USER; 474 ksi.ksi_signo = SIGSEGV; /* XXX */ 475 ksi.ksi_addr = (void *)vaddr; 476 ksi.ksi_code = SEGV_MAPERR; /* XXX */ 477 break; /* SIGNAL */ 478 479 case T_BREAK: 480 #if defined(DDB) 481 kdb_trap(type, frame->tf_regs); 482 return; /* KERN */ 483 #elif defined(KGDB) 484 { 485 struct frame *f = (struct frame *)&ddb_regs; 486 extern mips_reg_t kgdb_cause, kgdb_vaddr; 487 kgdb_cause = cause; 488 kgdb_vaddr = vaddr; 489 490 /* 491 * init global ddb_regs, used in db_interface.c routines 492 * shared between ddb and gdb. Send ddb_regs to gdb so 493 * that db_machdep.h macros will work with it, and 494 * allow gdb to alter the PC. 495 */ 496 db_set_ddb_regs(type, frame->f_regs); 497 PC_BREAK_ADVANCE(f); 498 if (!kgdb_trap(type, &ddb_regs)) 499 printf("kgdb: ignored %s\n", 500 trap_type[TRAPTYPE(cause)]); 501 else 502 frame->tf_regs[TF_EPC] = f->f_regs[_R_PC]; 503 504 return; 505 } 506 #else 507 goto dopanic; 508 #endif 509 case T_BREAK+T_USER: 510 { 511 uint32_t instr; 512 513 /* compute address of break instruction */ 514 va = (cause & MIPS_CR_BR_DELAY) ? opc + sizeof(int) : opc; 515 516 /* read break instruction */ 517 instr = fuiword((void *)va); 518 519 if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) { 520 ksi.ksi_trap = type & ~T_USER; 521 ksi.ksi_signo = SIGTRAP; 522 ksi.ksi_addr = (void *)va; 523 ksi.ksi_code = TRAP_TRACE; 524 break; 525 } 526 /* 527 * Restore original instruction and clear BP 528 */ 529 rv = ustore_uint32_isync((void *)va, l->l_md.md_ss_instr); 530 if (rv < 0) { 531 vaddr_t sa, ea; 532 sa = trunc_page(va); 533 ea = round_page(va + sizeof(int) - 1); 534 rv = uvm_map_protect(&p->p_vmspace->vm_map, 535 sa, ea, VM_PROT_ALL, false); 536 if (rv == 0) { 537 rv = ustore_uint32_isync((void *)va, l->l_md.md_ss_instr); 538 (void)uvm_map_protect(&p->p_vmspace->vm_map, 539 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false); 540 } 541 } 542 mips_icache_sync_all(); /* XXXJRT -- necessary? */ 543 mips_dcache_wbinv_all(); /* XXXJRT -- necessary? */ 544 545 if (rv < 0) 546 printf("Warning: can't restore instruction" 547 " at %#"PRIxVADDR": 0x%x\n", 548 l->l_md.md_ss_addr, l->l_md.md_ss_instr); 549 l->l_md.md_ss_addr = 0; 550 ksi.ksi_trap = type & ~T_USER; 551 ksi.ksi_signo = SIGTRAP; 552 ksi.ksi_addr = (void *)va; 553 ksi.ksi_code = TRAP_BRKPT; 554 break; /* SIGNAL */ 555 } 556 case T_RES_INST+T_USER: 557 case T_COP_UNUSABLE+T_USER: 558 #if !defined(SOFTFLOAT) && !defined(NOFPU) 559 if ((cause & MIPS_CR_COP_ERR) == 0x10000000) { 560 savefpregs(fpcurlwp); /* yield FPA */ 561 loadfpregs(l); /* load FPA */ 562 fpcurlwp = l; 563 l->l_md.md_flags |= MDP_FPUSED; 564 } else 565 #endif 566 { 567 MachEmulateInst(status, cause, opc, l->l_md.md_regs); 568 } 569 userret(l); 570 return; /* GEN */ 571 case T_FPE+T_USER: 572 #if defined(SOFTFLOAT) 573 MachEmulateInst(status, cause, opc, l->l_md.md_regs); 574 #elif !defined(NOFPU) 575 MachFPTrap(status, cause, opc, l->l_md.md_regs); 576 #endif 577 userret(l); 578 return; /* GEN */ 579 case T_OVFLOW+T_USER: 580 case T_TRAP+T_USER: 581 ksi.ksi_trap = type & ~T_USER; 582 ksi.ksi_signo = SIGFPE; 583 fp = l->l_md.md_regs; 584 ksi.ksi_addr = (void *)(intptr_t)fp->f_regs[_R_PC]; 585 ksi.ksi_code = FPE_FLTOVF; /* XXX */ 586 break; /* SIGNAL */ 587 } 588 fp = l->l_md.md_regs; 589 fp->f_regs[_R_CAUSE] = cause; 590 fp->f_regs[_R_BADVADDR] = vaddr; 591 #if defined(DEBUG) 592 printf("trap: pid %d(%s): sig %d: cause=%#x epc=%#"PRIxREGISTER 593 " va=%#"PRIxVADDR"\n", 594 p->p_pid, p->p_comm, ksi.ksi_signo, cause, 595 fp->f_regs[_R_PC], vaddr); 596 printf("registers:\n"); 597 for (size_t i = 0; i < 32; i += 4) { 598 printf( 599 "[%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER 600 " [%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER "\n", 601 i+0, fp->f_regs[i+0], i+1, fp->f_regs[i+1], 602 i+2, fp->f_regs[i+2], i+3, fp->f_regs[i+3]); 603 } 604 #endif 605 (*p->p_emul->e_trapsignal)(l, &ksi); 606 if ((type & T_USER) == 0) { 607 #ifdef DDB 608 Debugger(); 609 #endif 610 panic("trapsignal"); 611 } 612 userret(l); 613 return; 614 } 615 616 /* 617 * Handle asynchronous software traps. 618 * This is called from MachUserIntr() either to deliver signals or 619 * to make involuntary context switch (preemption). 620 */ 621 void 622 ast(unsigned pc) /* pc is program counter where to continue */ 623 { 624 struct lwp *l = curlwp; 625 626 while (l->l_md.md_astpending) { 627 //curcpu()->ci_data.cpu_nast++; 628 l->l_md.md_astpending = 0; 629 630 if (l->l_pflag & LP_OWEUPC) { 631 l->l_pflag &= ~LP_OWEUPC; 632 ADDUPROF(l); 633 } 634 635 userret(l); 636 637 if (curcpu()->ci_want_resched) { 638 /* 639 * We are being preempted. 640 */ 641 preempt(); 642 } 643 } 644 } 645 646 647 /* XXX need to rewrite acient comment XXX 648 * This routine is called by procxmt() to single step one instruction. 649 * We do this by storing a break instruction after the current instruction, 650 * resuming execution, and then restoring the old instruction. 651 */ 652 int 653 mips_singlestep(struct lwp *l) 654 { 655 struct frame *f = l->l_md.md_regs; 656 struct proc *p = l->l_proc; 657 vaddr_t pc, va; 658 int rv; 659 660 if (l->l_md.md_ss_addr) { 661 printf("SS %s (%d): breakpoint already set at %#"PRIxVADDR"\n", 662 p->p_comm, p->p_pid, l->l_md.md_ss_addr); 663 return EFAULT; 664 } 665 pc = (vaddr_t)f->f_regs[_R_PC]; 666 if (fuiword((void *)pc) != 0) { 667 struct pcb *pcb = lwp_getpcb(l); 668 /* not a NOP instruction */ 669 va = MachEmulateBranch(f, pc, PCB_FSR(pcb), 1); 670 } else 671 va = pc + sizeof(int); 672 673 /* 674 * We can't single-step into a RAS. Check if we're in 675 * a RAS, and set the breakpoint just past it. 676 */ 677 if (p->p_raslist != NULL) { 678 while (ras_lookup(p, (void *)va) != (void *)-1) 679 va += sizeof(int); 680 } 681 682 l->l_md.md_ss_addr = va; 683 l->l_md.md_ss_instr = fuiword((void *)va); 684 rv = ustore_uint32_isync((void *)va, MIPS_BREAK_SSTEP); 685 if (rv < 0) { 686 vaddr_t sa, ea; 687 sa = trunc_page(va); 688 ea = round_page(va + sizeof(int) - 1); 689 rv = uvm_map_protect(&p->p_vmspace->vm_map, 690 sa, ea, VM_PROT_ALL, false); 691 if (rv == 0) { 692 rv = ustore_uint32_isync((void *)va, MIPS_BREAK_SSTEP); 693 (void)uvm_map_protect(&p->p_vmspace->vm_map, 694 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false); 695 } 696 } 697 #if 0 698 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", 699 p->p_comm, p->p_pid, p->p_md.md_ss_addr, 700 p->p_md.md_ss_instr, pc, ufetch_uint32((void *)va)); /* XXX */ 701 #endif 702 return 0; 703 } 704 705 706 #ifndef DDB_TRACE 707 708 #if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo) 709 mips_reg_t kdbrpeek(vaddr_t, size_t); 710 711 int 712 kdbpeek(vaddr_t addr) 713 { 714 int rc; 715 716 if (addr & 3) { 717 printf("kdbpeek: unaligned address %#"PRIxVADDR"\n", addr); 718 /* We might have been called from DDB, so do not go there. */ 719 stacktrace(); 720 rc = -1 ; 721 } else if (addr == 0) { 722 printf("kdbpeek: NULL\n"); 723 rc = 0xdeadfeed; 724 } else { 725 rc = *(int *)addr; 726 } 727 return rc; 728 } 729 730 mips_reg_t 731 kdbrpeek(vaddr_t addr, size_t n) 732 { 733 mips_reg_t rc; 734 735 if (addr & (n - 1)) { 736 printf("kdbrpeek: unaligned address %#"PRIxVADDR"\n", addr); 737 /* We might have been called from DDB, so do not go there. */ 738 stacktrace(); 739 rc = -1 ; 740 } else if (addr == 0) { 741 printf("kdbrpeek: NULL\n"); 742 rc = 0xdeadfeed; 743 } else { 744 if (sizeof(mips_reg_t) == 8 && n == 8) 745 rc = *(int64_t *)addr; 746 else 747 rc = *(int32_t *)addr; 748 } 749 return rc; 750 } 751 752 extern char start[], edata[], verylocore[]; 753 extern char mips1_KernGenException[]; 754 extern char mips1_UserGenException[]; 755 extern char mips1_KernIntr[]; 756 extern char mips1_UserIntr[]; 757 extern char mips1_SystemCall[]; 758 extern char mips3_KernGenException[]; 759 extern char mips3_UserGenException[]; 760 extern char mips3_KernIntr[]; 761 extern char mips3_UserIntr[]; 762 extern char mips3_SystemCall[]; 763 int main(void *); /* XXX */ 764 765 /* 766 * stack trace code, also useful to DDB one day 767 */ 768 769 /* forward */ 770 const char *fn_name(vaddr_t addr); 771 void stacktrace_subr(mips_reg_t, mips_reg_t, mips_reg_t, mips_reg_t, 772 vaddr_t, vaddr_t, vaddr_t, vaddr_t, void (*)(const char*, ...)); 773 774 #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ 775 #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ 776 #define MIPS_ERET 0x42000018 /* instruction code for eret */ 777 778 /* 779 * Do a stack backtrace. 780 * (*printfn)() prints the output to either the system log, 781 * the console, or both. 782 */ 783 void 784 stacktrace_subr(mips_reg_t a0, mips_reg_t a1, mips_reg_t a2, mips_reg_t a3, 785 vaddr_t pc, vaddr_t sp, vaddr_t fp, vaddr_t ra, 786 void (*printfn)(const char*, ...)) 787 { 788 vaddr_t va, subr; 789 unsigned instr, mask; 790 InstFmt i; 791 int more, stksize; 792 unsigned int frames = 0; 793 int foundframesize = 0; 794 #ifdef DDB 795 db_expr_t diff; 796 db_sym_t sym; 797 #endif 798 799 /* Jump here when done with a frame, to start a new one */ 800 loop: 801 stksize = 0; 802 subr = 0; 803 if (frames++ > 100) { 804 (*printfn)("\nstackframe count exceeded\n"); 805 /* return breaks stackframe-size heuristics with gcc -O2 */ 806 goto finish; /*XXX*/ 807 } 808 809 /* check for bad SP: could foul up next frame */ 810 if (sp & 3 || (intptr_t)sp >= 0) { 811 (*printfn)("SP 0x%x: not in kernel\n", sp); 812 ra = 0; 813 subr = 0; 814 goto done; 815 } 816 817 /* Check for bad PC */ 818 if (pc & 3 || (intptr_t)pc >= 0 || (intptr_t)pc >= (intptr_t)edata) { 819 (*printfn)("PC 0x%x: not in kernel space\n", pc); 820 ra = 0; 821 goto done; 822 } 823 824 #ifdef DDB 825 /* 826 * Check the kernel symbol table to see the beginning of 827 * the current subroutine. 828 */ 829 diff = 0; 830 sym = db_search_symbol(pc, DB_STGY_ANY, &diff); 831 if (sym != DB_SYM_NULL && diff == 0) { 832 /* check func(foo) __attribute__((__noreturn__)) case */ 833 instr = kdbpeek(pc - 2 * sizeof(int)); 834 i.word = instr; 835 if (i.JType.op == OP_JAL) { 836 sym = db_search_symbol(pc - sizeof(int), 837 DB_STGY_ANY, &diff); 838 if (sym != DB_SYM_NULL && diff != 0) 839 diff += sizeof(int); 840 } 841 } 842 if (sym == DB_SYM_NULL) { 843 ra = 0; 844 goto done; 845 } 846 va = pc - diff; 847 #else 848 /* 849 * Find the beginning of the current subroutine by scanning backwards 850 * from the current PC for the end of the previous subroutine. 851 * 852 * XXX This won't work well because nowadays gcc is so aggressive 853 * as to reorder instruction blocks for branch-predict. 854 * (i.e. 'jr ra' wouldn't indicate the end of subroutine) 855 */ 856 va = pc; 857 do { 858 va -= sizeof(int); 859 if (va <= (vaddr_t)verylocore) 860 goto finish; 861 instr = kdbpeek(va); 862 if (instr == MIPS_ERET) 863 goto mips3_eret; 864 } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0); 865 /* skip back over branch & delay slot */ 866 va += sizeof(int); 867 mips3_eret: 868 va += sizeof(int); 869 /* skip over nulls which might separate .o files */ 870 while ((instr = kdbpeek(va)) == 0) 871 va += sizeof(int); 872 #endif 873 subr = va; 874 875 /* scan forwards to find stack size and any saved registers */ 876 stksize = 0; 877 more = 3; 878 mask = 0; 879 foundframesize = 0; 880 for (va = subr; more; va += sizeof(int), 881 more = (more == 3) ? 3 : more - 1) { 882 /* stop if hit our current position */ 883 if (va >= pc) 884 break; 885 instr = kdbpeek(va); 886 i.word = instr; 887 switch (i.JType.op) { 888 case OP_SPECIAL: 889 switch (i.RType.func) { 890 case OP_JR: 891 case OP_JALR: 892 more = 2; /* stop after next instruction */ 893 break; 894 895 case OP_SYSCALL: 896 case OP_BREAK: 897 more = 1; /* stop now */ 898 }; 899 break; 900 901 case OP_BCOND: 902 case OP_J: 903 case OP_JAL: 904 case OP_BEQ: 905 case OP_BNE: 906 case OP_BLEZ: 907 case OP_BGTZ: 908 more = 2; /* stop after next instruction */ 909 break; 910 911 case OP_COP0: 912 case OP_COP1: 913 case OP_COP2: 914 case OP_COP3: 915 switch (i.RType.rs) { 916 case OP_BCx: 917 case OP_BCy: 918 more = 2; /* stop after next instruction */ 919 }; 920 break; 921 922 case OP_SW: 923 #if !defined(__mips_o32) 924 case OP_SD: 925 #endif 926 { 927 size_t size = (i.JType.op == OP_SW) ? 4 : 8; 928 929 /* look for saved registers on the stack */ 930 if (i.IType.rs != 29) 931 break; 932 /* only restore the first one */ 933 if (mask & (1 << i.IType.rt)) 934 break; 935 mask |= (1 << i.IType.rt); 936 switch (i.IType.rt) { 937 case 4: /* a0 */ 938 a0 = kdbrpeek(sp + (short)i.IType.imm, size); 939 break; 940 941 case 5: /* a1 */ 942 a1 = kdbrpeek(sp + (short)i.IType.imm, size); 943 break; 944 945 case 6: /* a2 */ 946 a2 = kdbrpeek(sp + (short)i.IType.imm, size); 947 break; 948 949 case 7: /* a3 */ 950 a3 = kdbrpeek(sp + (short)i.IType.imm, size); 951 break; 952 953 case 30: /* fp */ 954 fp = kdbrpeek(sp + (short)i.IType.imm, size); 955 break; 956 957 case 31: /* ra */ 958 ra = kdbrpeek(sp + (short)i.IType.imm, size); 959 } 960 break; 961 } 962 963 case OP_ADDI: 964 case OP_ADDIU: 965 #if !defined(__mips_o32) 966 case OP_DADDI: 967 case OP_DADDIU: 968 #endif 969 /* look for stack pointer adjustment */ 970 if (i.IType.rs != 29 || i.IType.rt != 29) 971 break; 972 /* don't count pops for mcount */ 973 if (!foundframesize) { 974 stksize = - ((short)i.IType.imm); 975 foundframesize = 1; 976 } 977 } 978 } 979 done: 980 (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n", 981 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize); 982 983 if (ra) { 984 if (pc == ra && stksize == 0) 985 (*printfn)("stacktrace: loop!\n"); 986 else { 987 pc = ra; 988 sp += stksize; 989 ra = 0; 990 goto loop; 991 } 992 } else { 993 finish: 994 if (curlwp) 995 (*printfn)("User-level: pid %d.%d\n", 996 curlwp->l_proc->p_pid, curlwp->l_lid); 997 else 998 (*printfn)("User-level: curlwp NULL\n"); 999 } 1000 } 1001 1002 /* 1003 * Functions ``special'' enough to print by name 1004 */ 1005 #ifdef __STDC__ 1006 #define Name(_fn) { (void*)_fn, # _fn } 1007 #else 1008 #define Name(_fn) { _fn, "_fn"} 1009 #endif 1010 static struct { void *addr; const char *name;} names[] = { 1011 Name(stacktrace), 1012 Name(stacktrace_subr), 1013 Name(main), 1014 Name(trap), 1015 1016 #ifdef MIPS1 /* r2000 family (mips-I CPU) */ 1017 Name(mips1_KernGenException), 1018 Name(mips1_UserGenException), 1019 Name(mips1_SystemCall), 1020 Name(mips1_KernIntr), 1021 Name(mips1_UserIntr), 1022 #endif /* MIPS1 */ 1023 1024 /* XXX simonb: need mips32 and mips64 checks here too */ 1025 #if defined(MIPS3) && !defined(MIPS3_5900) /* r4000 family (mips-III CPU) */ 1026 Name(mips3_KernGenException), 1027 Name(mips3_UserGenException), 1028 Name(mips3_SystemCall), 1029 Name(mips3_KernIntr), 1030 Name(mips3_UserIntr), 1031 #endif /* MIPS3 && !MIPS3_5900 */ 1032 1033 Name(cpu_idle), 1034 Name(cpu_switchto), 1035 {0, 0} 1036 }; 1037 1038 /* 1039 * Map a function address to a string name, if known; or a hex string. 1040 */ 1041 const char * 1042 fn_name(vaddr_t addr) 1043 { 1044 static char buf[17]; 1045 int i = 0; 1046 #ifdef DDB 1047 db_expr_t diff; 1048 db_sym_t sym; 1049 const char *symname; 1050 #endif 1051 1052 #ifdef DDB 1053 diff = 0; 1054 symname = NULL; 1055 sym = db_search_symbol(addr, DB_STGY_ANY, &diff); 1056 db_symbol_values(sym, &symname, 0); 1057 if (symname && diff == 0) 1058 return (symname); 1059 #endif 1060 for (i = 0; names[i].name; i++) 1061 if (names[i].addr == (void*)addr) 1062 return (names[i].name); 1063 sprintf(buf, "%#"PRIxVADDR, addr); 1064 return (buf); 1065 } 1066 1067 #endif /* DEBUG */ 1068 #endif /* DDB_TRACE */ 1069