Annotation of src/sys/arch/mips/mips/trap.c, Revision 1.209
1.209 ! christos 1: /* $NetBSD: trap.c,v 1.208 2007/02/28 04:21:53 thorpej Exp $ */
1.8 cgd 2:
1.1 deraadt 3: /*
1.3 glass 4: * Copyright (c) 1992, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 deraadt 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.
1.181 agc 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.
1.1 deraadt 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
1.3 glass 75: *
1.8 cgd 76: * @(#)trap.c 8.5 (Berkeley) 1/11/94
1.1 deraadt 77: */
78:
1.78 jonathan 79: #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
1.125 nisimura 80:
1.209 ! christos 81: __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.208 2007/02/28 04:21:53 thorpej Exp $");
1.82 thorpej 82:
1.85 jonathan 83: #include "opt_cputype.h" /* which mips CPU levels do we support? */
1.84 thorpej 84: #include "opt_ktrace.h"
1.85 jonathan 85: #include "opt_ddb.h"
1.162 lukem 86: #include "opt_kgdb.h"
1.78 jonathan 87:
1.1 deraadt 88: #include <sys/param.h>
89: #include <sys/systm.h>
1.125 nisimura 90: #include <sys/kernel.h>
1.1 deraadt 91: #include <sys/proc.h>
1.171 gmcgarry 92: #include <sys/ras.h>
1.1 deraadt 93: #include <sys/signalvar.h>
94: #include <sys/syscall.h>
95: #include <sys/user.h>
96: #include <sys/buf.h>
97: #ifdef KTRACE
98: #include <sys/ktrace.h>
99: #endif
1.203 yamt 100: #include <sys/kauth.h>
1.46 jonathan 101:
1.165 thorpej 102: #include <mips/cache.h>
1.58 jonathan 103: #include <mips/locore.h>
104: #include <mips/mips_opcode.h>
1.78 jonathan 105:
1.82 thorpej 106: #include <uvm/uvm_extern.h>
107:
1.70 jonathan 108: #include <machine/cpu.h>
109: #include <mips/trap.h>
110: #include <mips/reg.h>
111: #include <mips/regnum.h> /* symbolic register indices */
112: #include <mips/pte.h>
1.129 nisimura 113: #include <mips/psl.h>
1.154 thorpej 114: #include <mips/userret.h>
1.1 deraadt 115:
1.125 nisimura 116: #include <net/netisr.h>
1.53 jonathan 117:
1.125 nisimura 118: #ifdef DDB
119: #include <machine/db_machdep.h>
120: #include <ddb/db_sym.h>
121: #endif
1.23 jonathan 122:
1.144 jeffs 123: #ifdef KGDB
124: #include <sys/kgdb.h>
125: #endif
126:
1.92 jonathan 127: int want_resched;
1.85 jonathan 128:
1.99 castor 129: const char *trap_type[] = {
1.1 deraadt 130: "external interrupt",
131: "TLB modification",
132: "TLB miss (load or instr. fetch)",
133: "TLB miss (store)",
134: "address error (load or I-fetch)",
135: "address error (store)",
136: "bus error (I-fetch)",
137: "bus error (load or store)",
138: "system call",
139: "breakpoint",
140: "reserved instruction",
141: "coprocessor unusable",
142: "arithmetic overflow",
1.32 jonathan 143: "r4k trap/r3k reserved 13",
144: "r4k virtual coherency instruction/r3k reserved 14",
145: "r4k floating point/ r3k reserved 15",
146: "reserved 16",
147: "reserved 17",
1.168 simonb 148: "mipsNN cp2 exception",
1.32 jonathan 149: "reserved 19",
150: "reserved 20",
151: "reserved 21",
1.168 simonb 152: "mips64 MDMX",
153: "r4k watch",
154: "mipsNN machine check",
1.32 jonathan 155: "reserved 25",
156: "reserved 26",
157: "reserved 27",
158: "reserved 28",
159: "reserved 29",
1.168 simonb 160: "mipsNN cache error",
1.46 jonathan 161: "r4000 virtual coherency data",
1.99 castor 162: };
163:
1.206 matt 164: void trap(unsigned int, unsigned int, vaddr_t, vaddr_t, struct trapframe *);
165: void ast(unsigned int);
1.99 castor 166:
1.206 matt 167: vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned int, int); /* XXX */
168: void MachEmulateInst(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */
169: void MachFPTrap(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */
1.16 jonathan 170:
1.63 mhitch 171: #define DELAYBRANCH(x) ((int)(x)<0)
1.57 mhitch 172:
173: /*
174: * fork syscall returns directly to user process via proc_trampoline,
175: * which will be called the very first time when child gets running.
176: */
177: void
1.190 simonb 178: child_return(void *arg)
1.57 mhitch 179: {
1.176 thorpej 180: struct lwp *l = arg;
181: struct frame *frame = (struct frame *)l->l_md.md_regs;
1.57 mhitch 182:
1.189 he 183: frame->f_regs[_R_V0] = 0;
184: frame->f_regs[_R_V1] = 1;
185: frame->f_regs[_R_A3] = 0;
1.176 thorpej 186: userret(l);
1.57 mhitch 187: #ifdef KTRACE
1.176 thorpej 188: if (KTRPOINT(l->l_proc, KTR_SYSRET))
1.198 christos 189: ktrsysret(l, SYS_fork, 0, 0);
1.57 mhitch 190: #endif
191: }
192:
1.168 simonb 193: #ifdef MIPS3_PLUS
1.65 jonathan 194: #define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 195: #else
1.65 jonathan 196: #define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 197: #endif
1.206 matt 198: #define KERNLAND(x) ((intptr_t)(x) < 0)
1.57 mhitch 199:
200: /*
201: * Trap is called from locore to handle most types of processor traps.
202: * System calls are broken out for efficiency. MIPS can handle software
203: * interrupts as a part of real interrupt processing.
204: */
205: void
1.206 matt 206: trap(unsigned int status, unsigned int cause, vaddr_t vaddr, vaddr_t opc,
1.190 simonb 207: struct trapframe *frame)
1.57 mhitch 208: {
1.184 christos 209: int type;
1.176 thorpej 210: struct lwp *l = curlwp;
1.184 christos 211: struct proc *p = curproc;
1.1 deraadt 212: vm_prot_t ftype;
1.184 christos 213: ksiginfo_t ksi;
1.185 christos 214: struct frame *fp;
1.168 simonb 215: extern void fswintrberr(void);
1.184 christos 216: KSI_INIT_TRAP(&ksi);
1.1 deraadt 217:
1.82 thorpej 218: uvmexp.traps++;
1.57 mhitch 219: type = TRAPTYPE(cause);
1.204 ad 220: if (USERMODE(status)) {
1.1 deraadt 221: type |= T_USER;
1.204 ad 222: LWP_CACHE_CREDS(l, p);
223: }
1.1 deraadt 224:
1.148 jeffs 225: if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV)) {
1.164 uch 226: if (type != T_BREAK) {
227: #ifdef IPL_ICU_MASK
228: spllowersofthigh();
229: #else
1.148 jeffs 230: _splset((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
1.164 uch 231: #endif
232: }
1.148 jeffs 233: }
1.1 deraadt 234:
235: switch (type) {
1.57 mhitch 236: default:
237: dopanic:
1.150 jeffs 238: (void)splhigh();
1.97 nisimura 239: printf("trap: %s in %s mode\n",
240: trap_type[TRAPTYPE(cause)],
241: USERMODE(status) ? "user" : "kernel");
1.206 matt 242: printf("status=0x%x, cause=0x%x, epc=%#lx, vaddr=%#lx\n",
1.97 nisimura 243: status, cause, opc, vaddr);
1.185 christos 244: if (curlwp != NULL) {
245: fp = (struct frame *)l->l_md.md_regs;
1.97 nisimura 246: printf("pid=%d cmd=%s usp=0x%x ",
1.189 he 247: p->p_pid, p->p_comm, (int)fp->f_regs[_R_SP]);
1.185 christos 248: } else
1.176 thorpej 249: printf("curlwp == NULL ");
1.206 matt 250: printf("ksp=%p\n", &status);
1.144 jeffs 251: #if defined(DDB)
1.99 castor 252: kdb_trap(type, (mips_reg_t *) frame);
253: /* XXX force halt XXX */
1.144 jeffs 254: #elif defined(KGDB)
255: {
256: struct frame *f = (struct frame *)&ddb_regs;
257: extern mips_reg_t kgdb_cause, kgdb_vaddr;
258: kgdb_cause = cause;
259: kgdb_vaddr = vaddr;
260:
261: /*
262: * init global ddb_regs, used in db_interface.c routines
263: * shared between ddb and gdb. Send ddb_regs to gdb so
264: * that db_machdep.h macros will work with it, and
265: * allow gdb to alter the PC.
266: */
267: db_set_ddb_regs(type, (mips_reg_t *) frame);
268: PC_BREAK_ADVANCE(f);
269: if (kgdb_trap(type, &ddb_regs)) {
1.189 he 270: ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC];
1.144 jeffs 271: return;
272: }
273: }
1.99 castor 274: #else
1.57 mhitch 275: panic("trap");
1.99 castor 276: #endif
1.57 mhitch 277: /*NOTREACHED*/
1.1 deraadt 278: case T_TLB_MOD:
1.57 mhitch 279: if (KERNLAND(vaddr)) {
280: pt_entry_t *pte;
281: unsigned entry;
1.139 soda 282: paddr_t pa;
1.1 deraadt 283:
1.57 mhitch 284: pte = kvtopte(vaddr);
1.1 deraadt 285: entry = pte->pt_entry;
1.60 jonathan 286: if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
1.57 mhitch 287: panic("ktlbmod: invalid pte");
288: }
1.104 mhitch 289: if (entry & mips_pg_ro_bit()) {
1.1 deraadt 290: /* write to read only page in the kernel */
291: ftype = VM_PROT_WRITE;
1.57 mhitch 292: goto kernelfault;
1.1 deraadt 293: }
1.60 jonathan 294: entry |= mips_pg_m_bit();
1.1 deraadt 295: pte->pt_entry = entry;
1.57 mhitch 296: vaddr &= ~PGOFSET;
297: MachTLBUpdate(vaddr, entry);
1.140 soda 298: pa = mips_tlbpfn_to_paddr(entry);
1.96 mhitch 299: if (!IS_VM_PHYSADDR(pa)) {
1.206 matt 300: printf("ktlbmod: va %#lx pa %#llx\n",
1.139 soda 301: vaddr, (long long)pa);
1.57 mhitch 302: panic("ktlbmod: unmanaged page");
1.96 mhitch 303: }
304: pmap_set_modified(pa);
1.57 mhitch 305: return; /* KERN */
1.1 deraadt 306: }
1.57 mhitch 307: /*FALLTHROUGH*/
1.1 deraadt 308: case T_TLB_MOD+T_USER:
309: {
1.57 mhitch 310: pt_entry_t *pte;
311: unsigned entry;
1.139 soda 312: paddr_t pa;
1.57 mhitch 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);
1.3 glass 319: entry = pte->pt_entry;
1.60 jonathan 320: if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
1.57 mhitch 321: panic("utlbmod: invalid pte");
322:
1.104 mhitch 323: if (entry & mips_pg_ro_bit()) {
1.3 glass 324: /* write to read only page */
1.1 deraadt 325: ftype = VM_PROT_WRITE;
1.57 mhitch 326: goto pagefault;
1.1 deraadt 327: }
1.60 jonathan 328: entry |= mips_pg_m_bit();
1.3 glass 329: pte->pt_entry = entry;
1.57 mhitch 330: vaddr = (vaddr & ~PGOFSET) |
1.109 nisimura 331: (pmap->pm_asid << MIPS_TLB_PID_SHIFT);
1.108 simonb 332: MachTLBUpdate(vaddr, entry);
1.140 soda 333: pa = mips_tlbpfn_to_paddr(entry);
1.96 mhitch 334: if (!IS_VM_PHYSADDR(pa)) {
1.206 matt 335: printf("utlbmod: va %#lx pa %#llx\n",
1.139 soda 336: vaddr, (long long)pa);
1.57 mhitch 337: panic("utlbmod: unmanaged page");
1.96 mhitch 338: }
339: pmap_set_modified(pa);
1.57 mhitch 340: if (type & T_USER)
1.176 thorpej 341: userret(l);
1.57 mhitch 342: return; /* GEN */
1.1 deraadt 343: }
344: case T_TLB_LD_MISS:
345: case T_TLB_ST_MISS:
1.57 mhitch 346: ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
347: if (KERNLAND(vaddr))
348: goto kernelfault;
1.1 deraadt 349: /*
350: * It is an error for the kernel to access user space except
351: * through the copyin/copyout routines.
352: */
1.176 thorpej 353: if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
1.57 mhitch 354: goto dopanic;
1.1 deraadt 355: /* check for fuswintr() or suswintr() getting a page fault */
1.209 ! christos 356: if (l->l_addr->u_pcb.pcb_onfault == (void *)fswintrberr) {
1.174 thorpej 357: frame->tf_regs[TF_EPC] = (int)fswintrberr;
1.57 mhitch 358: return; /* KERN */
359: }
360: goto pagefault;
1.1 deraadt 361: case T_TLB_LD_MISS+T_USER:
362: ftype = VM_PROT_READ;
1.57 mhitch 363: goto pagefault;
1.1 deraadt 364: case T_TLB_ST_MISS+T_USER:
365: ftype = VM_PROT_WRITE;
1.57 mhitch 366: pagefault: ;
1.1 deraadt 367: {
1.98 nisimura 368: vaddr_t va;
1.108 simonb 369: struct vmspace *vm;
1.163 chs 370: struct vm_map *map;
1.1 deraadt 371: int rv;
372:
1.3 glass 373: vm = p->p_vmspace;
374: map = &vm->vm_map;
1.98 nisimura 375: va = trunc_page(vaddr);
1.172 manu 376:
377: if (p->p_emul->e_fault)
1.200 drochner 378: rv = (*p->p_emul->e_fault)(p, va, ftype);
1.172 manu 379: else
1.199 drochner 380: rv = uvm_fault(map, va, ftype);
1.82 thorpej 381: #ifdef VMFAULT_TRACE
382: printf(
1.199 drochner 383: "uvm_fault(%p (pmap %p), %lx (0x%x), %d) -> %d at pc %p\n",
1.82 thorpej 384: map, vm->vm_map.pmap, va, vaddr, ftype, rv, (void*)opc);
385: #endif
1.1 deraadt 386: /*
387: * If this was a stack access we keep track of the maximum
388: * accessed stack size. Also, if vm_fault gets a protection
389: * failure it is due to accessing the stack region outside
390: * the current limit and we need to reflect that as an access
391: * error.
392: */
1.209 ! christos 393: if ((void *)va >= vm->vm_maxsaddr) {
1.194 jdolecek 394: if (rv == 0)
395: uvm_grow(p, va);
1.161 chs 396: else if (rv == EACCES)
397: rv = EFAULT;
1.1 deraadt 398: }
1.161 chs 399: if (rv == 0) {
1.99 castor 400: if (type & T_USER) {
1.176 thorpej 401: userret(l);
1.99 castor 402: }
1.57 mhitch 403: return; /* GEN */
404: }
1.108 simonb 405: if ((type & T_USER) == 0)
1.57 mhitch 406: goto copyfault;
1.161 chs 407: if (rv == ENOMEM) {
1.105 chs 408: printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
409: p->p_pid, p->p_comm,
1.205 ad 410: l->l_cred ?
411: kauth_cred_geteuid(l->l_cred) : (uid_t) -1);
1.184 christos 412: ksi.ksi_signo = SIGKILL;
413: ksi.ksi_code = 0;
1.105 chs 414: } else {
1.184 christos 415: if (rv == EACCES) {
416: ksi.ksi_signo = SIGBUS;
417: ksi.ksi_code = BUS_OBJERR;
418: } else {
419: ksi.ksi_signo = SIGSEGV;
420: ksi.ksi_code = SEGV_MAPERR;
421: }
1.105 chs 422: }
1.184 christos 423: ksi.ksi_trap = type & ~T_USER;
424: ksi.ksi_addr = (void *)vaddr;
1.108 simonb 425: break; /* SIGNAL */
1.99 castor 426: }
1.57 mhitch 427: kernelfault: ;
428: {
1.98 nisimura 429: vaddr_t va;
1.108 simonb 430: int rv;
1.57 mhitch 431:
1.98 nisimura 432: va = trunc_page(vaddr);
1.199 drochner 433: rv = uvm_fault(kernel_map, va, ftype);
1.161 chs 434: if (rv == 0)
1.57 mhitch 435: return; /* KERN */
436: /*FALLTHROUGH*/
1.1 deraadt 437: }
1.57 mhitch 438: case T_ADDR_ERR_LD: /* misaligned access */
439: case T_ADDR_ERR_ST: /* misaligned access */
1.191 wiz 440: case T_BUS_ERR_LD_ST: /* BERR asserted to CPU */
1.57 mhitch 441: copyfault:
1.176 thorpej 442: if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
1.57 mhitch 443: goto dopanic;
1.206 matt 444: frame->tf_regs[TF_EPC] = (intptr_t)l->l_addr->u_pcb.pcb_onfault;
1.57 mhitch 445: return; /* KERN */
1.1 deraadt 446:
447: case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
448: case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
1.191 wiz 449: case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to CPU */
450: case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to CPU */
1.184 christos 451: ksi.ksi_trap = type & ~T_USER;
452: ksi.ksi_signo = SIGSEGV; /* XXX */
453: ksi.ksi_addr = (void *)vaddr;
454: ksi.ksi_code = SEGV_MAPERR; /* XXX */
1.57 mhitch 455: break; /* SIGNAL */
1.69 jonathan 456:
457: case T_BREAK:
1.144 jeffs 458: #if defined(DDB)
1.99 castor 459: kdb_trap(type, (mips_reg_t *) frame);
1.69 jonathan 460: return; /* KERN */
1.144 jeffs 461: #elif defined(KGDB)
462: {
463: struct frame *f = (struct frame *)&ddb_regs;
464: extern mips_reg_t kgdb_cause, kgdb_vaddr;
465: kgdb_cause = cause;
466: kgdb_vaddr = vaddr;
467:
468: /*
469: * init global ddb_regs, used in db_interface.c routines
470: * shared between ddb and gdb. Send ddb_regs to gdb so
471: * that db_machdep.h macros will work with it, and
472: * allow gdb to alter the PC.
473: */
474: db_set_ddb_regs(type, (mips_reg_t *) frame);
475: PC_BREAK_ADVANCE(f);
476: if (!kgdb_trap(type, &ddb_regs))
477: printf("kgdb: ignored %s\n",
478: trap_type[TRAPTYPE(cause)]);
479: else
1.189 he 480: ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC];
1.144 jeffs 481:
482: return;
483: }
1.69 jonathan 484: #else
485: goto dopanic;
486: #endif
1.1 deraadt 487: case T_BREAK+T_USER:
488: {
1.206 matt 489: vaddr_t va;
490: uint32_t instr;
1.57 mhitch 491: int rv;
1.1 deraadt 492:
493: /* compute address of break instruction */
1.57 mhitch 494: va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc;
1.1 deraadt 495:
496: /* read break instruction */
1.99 castor 497: instr = fuiword((void *)va);
1.57 mhitch 498:
1.176 thorpej 499: if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
1.184 christos 500: ksi.ksi_trap = type & ~T_USER;
501: ksi.ksi_signo = SIGTRAP;
502: ksi.ksi_addr = (void *)va;
503: ksi.ksi_code = TRAP_TRACE;
1.1 deraadt 504: break;
505: }
1.97 nisimura 506: /*
1.57 mhitch 507: * Restore original instruction and clear BP
1.97 nisimura 508: */
1.176 thorpej 509: rv = suiword((void *)va, l->l_md.md_ss_instr);
1.57 mhitch 510: if (rv < 0) {
1.98 nisimura 511: vaddr_t sa, ea;
512: sa = trunc_page(va);
513: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 514: rv = uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 515: sa, ea, VM_PROT_ALL, false);
1.161 chs 516: if (rv == 0) {
1.197 drochner 517: rv = suiword((void *)va, l->l_md.md_ss_instr);
1.82 thorpej 518: (void)uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 519: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
1.82 thorpej 520: }
1.97 nisimura 521: }
1.165 thorpej 522: mips_icache_sync_all(); /* XXXJRT -- necessary? */
523: mips_dcache_wbinv_all(); /* XXXJRT -- necessary? */
1.69 jonathan 524:
1.57 mhitch 525: if (rv < 0)
1.175 thorpej 526: printf("Warning: can't restore instruction at 0x%lx: 0x%x\n",
1.176 thorpej 527: l->l_md.md_ss_addr, l->l_md.md_ss_instr);
528: l->l_md.md_ss_addr = 0;
1.184 christos 529: ksi.ksi_trap = type & ~T_USER;
530: ksi.ksi_signo = SIGTRAP;
531: ksi.ksi_addr = (void *)va;
532: ksi.ksi_code = TRAP_BRKPT;
1.57 mhitch 533: break; /* SIGNAL */
1.99 castor 534: }
1.1 deraadt 535: case T_RES_INST+T_USER:
536: case T_COP_UNUSABLE+T_USER:
1.170 gmcgarry 537: #if !defined(SOFTFLOAT) && !defined(NOFPU)
538: if ((cause & MIPS_CR_COP_ERR) == 0x10000000) {
539: struct frame *f;
540:
1.176 thorpej 541: f = (struct frame *)l->l_md.md_regs;
542: savefpregs(fpcurlwp); /* yield FPA */
543: loadfpregs(l); /* load FPA */
544: fpcurlwp = l;
545: l->l_md.md_flags |= MDP_FPUSED;
1.189 he 546: f->f_regs[_R_SR] |= MIPS_SR_COP_1_BIT;
1.170 gmcgarry 547: } else
1.118 shin 548: #endif
1.133 nisimura 549: {
1.176 thorpej 550: MachEmulateInst(status, cause, opc, l->l_md.md_regs);
1.133 nisimura 551: }
1.176 thorpej 552: userret(l);
1.57 mhitch 553: return; /* GEN */
1.32 jonathan 554: case T_FPE+T_USER:
1.170 gmcgarry 555: #if defined(SOFTFLOAT)
1.176 thorpej 556: MachEmulateInst(status, cause, opc, l->l_md.md_regs);
1.170 gmcgarry 557: #elif !defined(NOFPU)
1.176 thorpej 558: MachFPTrap(status, cause, opc, l->l_md.md_regs);
1.118 shin 559: #endif
1.176 thorpej 560: userret(l);
1.108 simonb 561: return; /* GEN */
1.1 deraadt 562: case T_OVFLOW+T_USER:
1.146 jeffs 563: case T_TRAP+T_USER:
1.184 christos 564: ksi.ksi_trap = type & ~T_USER;
565: ksi.ksi_signo = SIGFPE;
1.186 christos 566: fp = (struct frame *)l->l_md.md_regs;
1.189 he 567: ksi.ksi_addr = (void *)fp->f_regs[_R_PC];
1.184 christos 568: ksi.ksi_code = FPE_FLTOVF; /* XXX */
1.108 simonb 569: break; /* SIGNAL */
1.97 nisimura 570: }
1.185 christos 571: fp = (struct frame *)l->l_md.md_regs;
1.189 he 572: fp->f_regs[_R_CAUSE] = cause;
573: fp->f_regs[_R_BADVADDR] = vaddr;
1.184 christos 574: (*p->p_emul->e_trapsignal)(l, &ksi);
1.57 mhitch 575: if ((type & T_USER) == 0)
576: panic("trapsignal");
1.176 thorpej 577: userret(l);
1.108 simonb 578: return;
1.57 mhitch 579: }
1.1 deraadt 580:
1.127 soda 581: /*
582: * Software (low priority) network interrupt. i.e. softnet().
583: */
1.22 jonathan 584: void
1.190 simonb 585: netintr(void)
1.1 deraadt 586: {
1.125 nisimura 587: #define DONETISR(bit, fn) \
588: do { \
589: if (n & (1 << bit)) \
590: fn(); \
591: } while (0)
1.85 jonathan 592:
1.125 nisimura 593: int n;
1.190 simonb 594:
595: n = netisr;
596: netisr = 0;
1.85 jonathan 597:
1.121 erh 598: #include <net/netisr_dispatch.h>
599:
600: #undef DONETISR
1.1 deraadt 601: }
602:
603: /*
1.57 mhitch 604: * Handle asynchronous software traps.
605: * This is called from MachUserIntr() either to deliver signals or
606: * to make involuntary context switch (preemption).
1.1 deraadt 607: */
1.22 jonathan 608: void
1.190 simonb 609: ast(unsigned pc) /* pc is program counter where to continue */
1.1 deraadt 610: {
1.176 thorpej 611: struct lwp *l = curlwp;
1.1 deraadt 612:
1.207 ad 613: while (l->l_md.md_astpending) {
1.155 thorpej 614: uvmexp.softs++;
1.207 ad 615: l->l_md.md_astpending = 0;
1.153 thorpej 616:
1.207 ad 617: if (l->l_pflag & LP_OWEUPC) {
618: l->l_pflag &= ~LP_OWEUPC;
619: ADDUPROF(l);
1.155 thorpej 620: }
621:
1.207 ad 622: userret(l);
1.155 thorpej 623:
624: if (want_resched) {
625: /*
626: * We are being preempted.
627: */
1.207 ad 628: preempt();
1.155 thorpej 629: }
1.153 thorpej 630: }
1.57 mhitch 631: }
1.1 deraadt 632:
633:
1.99 castor 634: /* XXX need to rewrite acient comment XXX
1.1 deraadt 635: * This routine is called by procxmt() to single step one instruction.
636: * We do this by storing a break instruction after the current instruction,
637: * resuming execution, and then restoring the old instruction.
638: */
1.22 jonathan 639: int
1.190 simonb 640: mips_singlestep(struct lwp *l)
1.1 deraadt 641: {
1.176 thorpej 642: struct frame *f = (struct frame *)l->l_md.md_regs;
643: struct proc *p = l->l_proc;
1.98 nisimura 644: vaddr_t pc, va;
1.108 simonb 645: int rv;
1.1 deraadt 646:
1.176 thorpej 647: if (l->l_md.md_ss_addr) {
1.175 thorpej 648: printf("SS %s (%d): breakpoint already set at %lx\n",
1.176 thorpej 649: p->p_comm, p->p_pid, l->l_md.md_ss_addr);
1.97 nisimura 650: return EFAULT;
1.1 deraadt 651: }
1.189 he 652: pc = (vaddr_t)f->f_regs[_R_PC];
1.98 nisimura 653: if (fuiword((void *)pc) != 0) /* not a NOP instruction */
1.177 simonb 654: va = MachEmulateBranch(f, pc, PCB_FSR(&l->l_addr->u_pcb), 1);
1.97 nisimura 655: else
1.99 castor 656: va = pc + sizeof(int);
1.171 gmcgarry 657:
658: /*
659: * We can't single-step into a RAS. Check if we're in
660: * a RAS, and set the breakpoint just past it.
661: */
1.188 simonb 662: if (!LIST_EMPTY(&p->p_raslist)) {
1.209 ! christos 663: while (ras_lookup(p, (void *)va) != (void *)-1)
1.171 gmcgarry 664: va += sizeof(int);
665: }
666:
1.176 thorpej 667: l->l_md.md_ss_addr = va;
668: l->l_md.md_ss_instr = fuiword((void *)va);
1.99 castor 669: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.97 nisimura 670: if (rv < 0) {
1.98 nisimura 671: vaddr_t sa, ea;
672: sa = trunc_page(va);
673: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 674: rv = uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 675: sa, ea, VM_PROT_ALL, false);
1.161 chs 676: if (rv == 0) {
1.99 castor 677: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.82 thorpej 678: (void)uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 679: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
1.82 thorpej 680: }
1.1 deraadt 681: }
1.3 glass 682: #if 0
1.45 christos 683: printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
1.1 deraadt 684: p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1.99 castor 685: p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */
1.3 glass 686: #endif
1.97 nisimura 687: return 0;
1.1 deraadt 688: }
689:
1.99 castor 690:
691: #ifndef DDB_TRACE
692:
1.144 jeffs 693: #if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo)
1.168 simonb 694: mips_reg_t kdbrpeek(vaddr_t);
1.99 castor 695:
1.22 jonathan 696: int
1.190 simonb 697: kdbpeek(vaddr_t addr)
1.1 deraadt 698: {
1.99 castor 699: int rc;
1.190 simonb 700:
1.1 deraadt 701: if (addr & 3) {
1.56 jonathan 702: printf("kdbpeek: unaligned address %lx\n", addr);
1.99 castor 703: /* We might have been called from DDB, so do not go there. */
704: stacktrace();
705: rc = -1 ;
1.183 tsutsui 706: } else if (addr == 0) {
1.99 castor 707: printf("kdbpeek: NULL\n");
708: rc = 0xdeadfeed;
709: } else {
710: rc = *(int *)addr;
711: }
712: return rc;
713: }
714:
715: mips_reg_t
1.190 simonb 716: kdbrpeek(vaddr_t addr)
1.99 castor 717: {
718: mips_reg_t rc;
1.190 simonb 719:
1.99 castor 720: if (addr & (sizeof(mips_reg_t) - 1)) {
721: printf("kdbrpeek: unaligned address %lx\n", addr);
722: /* We might have been called from DDB, so do not go there. */
1.69 jonathan 723: stacktrace();
1.99 castor 724: rc = -1 ;
1.183 tsutsui 725: } else if (addr == 0) {
1.99 castor 726: printf("kdbrpeek: NULL\n");
727: rc = 0xdeadfeed;
728: } else {
729: rc = *(mips_reg_t *)addr;
1.1 deraadt 730: }
1.99 castor 731: return rc;
1.1 deraadt 732: }
733:
1.99 castor 734: extern char start[], edata[], verylocore[];
735: extern char mips1_KernGenException[];
736: extern char mips1_UserGenException[];
737: extern char mips1_KernIntr[];
738: extern char mips1_UserIntr[];
739: extern char mips1_SystemCall[];
740: extern char mips3_KernGenException[];
741: extern char mips3_UserGenException[];
742: extern char mips3_KernIntr[];
743: extern char mips3_UserIntr[];
744: extern char mips3_SystemCall[];
1.179 simonb 745: int main(void *); /* XXX */
746: void mips_idle(void); /* XXX */
1.99 castor 747:
748: /*
749: * stack trace code, also useful to DDB one day
750: */
1.1 deraadt 751:
1.16 jonathan 752: /* forward */
1.206 matt 753: const char *fn_name(vaddr_t addr);
1.168 simonb 754: void stacktrace_subr(int, int, int, int, u_int, u_int, u_int, u_int,
755: void (*)(const char*, ...));
1.16 jonathan 756:
1.99 castor 757: #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
758: #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */
1.102 nisimura 759: #define MIPS_ERET 0x42000018 /* instruction code for eret */
1.99 castor 760:
1.1 deraadt 761: /*
1.56 jonathan 762: * Do a stack backtrace.
763: * (*printfn)() prints the output to either the system log,
764: * the console, or both.
1.1 deraadt 765: */
1.16 jonathan 766: void
1.190 simonb 767: stacktrace_subr(int a0, int a1, int a2, int a3,
768: u_int pc, u_int sp, u_int fp, u_int ra,
769: void (*printfn)(const char*, ...))
1.16 jonathan 770: {
1.206 matt 771: vaddr_t va, subr;
1.1 deraadt 772: unsigned instr, mask;
773: InstFmt i;
774: int more, stksize;
1.16 jonathan 775: unsigned int frames = 0;
1.71 jonathan 776: int foundframesize = 0;
1.1 deraadt 777:
1.16 jonathan 778: /* Jump here when done with a frame, to start a new one */
1.1 deraadt 779: loop:
1.16 jonathan 780: stksize = 0;
781: subr = 0;
1.99 castor 782: if (frames++ > 100) {
1.16 jonathan 783: (*printfn)("\nstackframe count exceeded\n");
1.17 jonathan 784: /* return breaks stackframe-size heuristics with gcc -O2 */
785: goto finish; /*XXX*/
1.16 jonathan 786: }
787:
788: /* check for bad SP: could foul up next frame */
789: if (sp & 3 || sp < 0x80000000) {
790: (*printfn)("SP 0x%x: not in kernel\n", sp);
791: ra = 0;
792: subr = 0;
793: goto done;
794: }
795:
1.47 jonathan 796: /* Check for bad PC */
1.1 deraadt 797: if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
1.37 jonathan 798: (*printfn)("PC 0x%x: not in kernel space\n", pc);
799: ra = 0;
800: goto done;
801: }
1.1 deraadt 802:
803: /*
804: * Find the beginning of the current subroutine by scanning backwards
805: * from the current PC for the end of the previous subroutine.
806: */
1.99 castor 807: va = pc;
808: do {
1.1 deraadt 809: va -= sizeof(int);
1.99 castor 810: if (va <= (unsigned)verylocore)
811: goto finish;
812: instr = kdbpeek(va);
813: if (instr == MIPS_ERET)
814: goto mips3_eret;
815: } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
816: /* skip back over branch & delay slot */
1.108 simonb 817: va += sizeof(int);
1.99 castor 818: mips3_eret:
1.108 simonb 819: va += sizeof(int);
1.99 castor 820: /* skip over nulls which might separate .o files */
821: while ((instr = kdbpeek(va)) == 0)
822: va += sizeof(int);
823: subr = va;
1.1 deraadt 824:
825: /* scan forwards to find stack size and any saved registers */
826: stksize = 0;
827: more = 3;
828: mask = 0;
1.71 jonathan 829: foundframesize = 0;
1.16 jonathan 830: for (va = subr; more; va += sizeof(int),
1.97 nisimura 831: more = (more == 3) ? 3 : more - 1) {
1.1 deraadt 832: /* stop if hit our current position */
833: if (va >= pc)
834: break;
835: instr = kdbpeek(va);
836: i.word = instr;
837: switch (i.JType.op) {
838: case OP_SPECIAL:
839: switch (i.RType.func) {
840: case OP_JR:
841: case OP_JALR:
842: more = 2; /* stop after next instruction */
843: break;
844:
845: case OP_SYSCALL:
846: case OP_BREAK:
847: more = 1; /* stop now */
848: };
849: break;
850:
851: case OP_BCOND:
852: case OP_J:
853: case OP_JAL:
854: case OP_BEQ:
855: case OP_BNE:
856: case OP_BLEZ:
857: case OP_BGTZ:
858: more = 2; /* stop after next instruction */
859: break;
860:
861: case OP_COP0:
862: case OP_COP1:
863: case OP_COP2:
864: case OP_COP3:
865: switch (i.RType.rs) {
866: case OP_BCx:
867: case OP_BCy:
868: more = 2; /* stop after next instruction */
869: };
870: break;
871:
872: case OP_SW:
873: /* look for saved registers on the stack */
874: if (i.IType.rs != 29)
875: break;
876: /* only restore the first one */
877: if (mask & (1 << i.IType.rt))
878: break;
1.16 jonathan 879: mask |= (1 << i.IType.rt);
1.1 deraadt 880: switch (i.IType.rt) {
881: case 4: /* a0 */
882: a0 = kdbpeek(sp + (short)i.IType.imm);
883: break;
884:
885: case 5: /* a1 */
886: a1 = kdbpeek(sp + (short)i.IType.imm);
887: break;
888:
889: case 6: /* a2 */
890: a2 = kdbpeek(sp + (short)i.IType.imm);
891: break;
892:
893: case 7: /* a3 */
894: a3 = kdbpeek(sp + (short)i.IType.imm);
895: break;
896:
897: case 30: /* fp */
898: fp = kdbpeek(sp + (short)i.IType.imm);
899: break;
900:
901: case 31: /* ra */
902: ra = kdbpeek(sp + (short)i.IType.imm);
903: }
904: break;
905:
906: case OP_ADDI:
907: case OP_ADDIU:
908: /* look for stack pointer adjustment */
909: if (i.IType.rs != 29 || i.IType.rt != 29)
910: break;
1.71 jonathan 911: /* don't count pops for mcount */
912: if (!foundframesize) {
913: stksize = - ((short)i.IType.imm);
914: foundframesize = 1;
1.108 simonb 915: }
1.1 deraadt 916: }
917: }
918: done:
1.16 jonathan 919: (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
920: fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1.1 deraadt 921:
922: if (ra) {
923: if (pc == ra && stksize == 0)
1.16 jonathan 924: (*printfn)("stacktrace: loop!\n");
1.1 deraadt 925: else {
926: pc = ra;
1.16 jonathan 927: sp += stksize;
928: ra = 0;
1.1 deraadt 929: goto loop;
930: }
1.16 jonathan 931: } else {
1.17 jonathan 932: finish:
1.176 thorpej 933: if (curlwp)
934: (*printfn)("User-level: pid %d.%d\n",
935: curlwp->l_proc->p_pid, curlwp->l_lid);
1.16 jonathan 936: else
1.176 thorpej 937: (*printfn)("User-level: curlwp NULL\n");
1.1 deraadt 938: }
939: }
1.16 jonathan 940:
941: /*
942: * Functions ``special'' enough to print by name
943: */
944: #ifdef __STDC__
945: #define Name(_fn) { (void*)_fn, # _fn }
946: #else
947: #define Name(_fn) { _fn, "_fn"}
948: #endif
1.196 drochner 949: static struct { void *addr; const char *name;} names[] = {
1.23 jonathan 950: Name(stacktrace),
951: Name(stacktrace_subr),
952: Name(main),
1.16 jonathan 953: Name(trap),
1.42 jonathan 954:
1.191 wiz 955: #ifdef MIPS1 /* r2000 family (mips-I CPU) */
1.50 jonathan 956: Name(mips1_KernGenException),
957: Name(mips1_UserGenException),
1.57 mhitch 958: Name(mips1_SystemCall),
1.50 jonathan 959: Name(mips1_KernIntr),
960: Name(mips1_UserIntr),
1.42 jonathan 961: #endif /* MIPS1 */
1.35 jonathan 962:
1.168 simonb 963: /* XXX simonb: need mips32 and mips64 checks here too */
1.191 wiz 964: #if defined(MIPS3) && !defined(MIPS3_5900) /* r4000 family (mips-III CPU) */
1.50 jonathan 965: Name(mips3_KernGenException),
966: Name(mips3_UserGenException),
1.57 mhitch 967: Name(mips3_SystemCall),
1.50 jonathan 968: Name(mips3_KernIntr),
969: Name(mips3_UserIntr),
1.169 uch 970: #endif /* MIPS3 && !MIPS3_5900 */
1.35 jonathan 971:
1.119 takemura 972: Name(mips_idle),
1.16 jonathan 973: Name(cpu_switch),
974: {0, 0}
975: };
976:
977: /*
978: * Map a function address to a string name, if known; or a hex string.
979: */
1.195 simonb 980: const char *
1.206 matt 981: fn_name(vaddr_t addr)
1.16 jonathan 982: {
983: static char buf[17];
984: int i = 0;
1.77 mhitch 985: #ifdef DDB
986: db_expr_t diff;
987: db_sym_t sym;
1.195 simonb 988: const char *symname;
1.77 mhitch 989: #endif
1.16 jonathan 990:
1.77 mhitch 991: #ifdef DDB
992: diff = 0;
993: symname = NULL;
994: sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
995: db_symbol_values(sym, &symname, 0);
996: if (symname && diff == 0)
997: return (symname);
998: #endif
1.16 jonathan 999: for (i = 0; names[i].name; i++)
1000: if (names[i].addr == (void*)addr)
1001: return (names[i].name);
1.206 matt 1002: sprintf(buf, "%lx", addr);
1.16 jonathan 1003: return (buf);
1004: }
1005:
1.1 deraadt 1006: #endif /* DEBUG */
1.99 castor 1007: #endif /* DDB_TRACE */
CVSweb <webmaster@jp.NetBSD.org>