Annotation of src/sys/arch/mips/mips/trap.c, Revision 1.100
1.100 ! nisimura 1: /* $NetBSD: trap.c,v 1.99 1999/01/15 01:23:15 castor Exp $ */
1.8 cgd 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1988 University of Utah.
1.3 glass 5: * Copyright (c) 1992, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 deraadt 7: *
8: * This code is derived from software contributed to Berkeley by
9: * the Systems Programming Group of the University of Utah Computer
10: * Science Department and Ralph Campbell.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
40: * from: Utah Hdr: trap.c 1.32 91/04/06
1.3 glass 41: *
1.8 cgd 42: * @(#)trap.c 8.5 (Berkeley) 1/11/94
1.1 deraadt 43: */
44:
1.78 jonathan 45: #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
1.100 ! nisimura 46: __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.99 1999/01/15 01:23:15 castor Exp $");
1.82 thorpej 47:
1.85 jonathan 48: #include "opt_cputype.h" /* which mips CPU levels do we support? */
1.86 jonathan 49: #include "opt_inet.h"
50: #include "opt_atalk.h"
1.87 jonathan 51: #include "opt_ccitt.h"
52: #include "opt_iso.h"
1.88 jonathan 53: #include "opt_ns.h"
1.89 jonathan 54: #include "opt_natm.h"
1.84 thorpej 55: #include "opt_ktrace.h"
1.82 thorpej 56: #include "opt_uvm.h"
1.85 jonathan 57: #include "opt_ddb.h"
1.78 jonathan 58:
1.43 jonathan 59: #if !defined(MIPS1) && !defined(MIPS3)
1.57 mhitch 60: #error Neither "MIPS1" (r2000 family), "MIPS3" (r4000 family) was configured.
1.37 jonathan 61: #endif
62:
1.1 deraadt 63: #include <sys/param.h>
64: #include <sys/systm.h>
1.23 jonathan 65: #include <sys/device.h>
1.1 deraadt 66: #include <sys/proc.h>
67: #include <sys/kernel.h>
68: #include <sys/signalvar.h>
69: #include <sys/syscall.h>
70: #include <sys/user.h>
71: #include <sys/buf.h>
1.99 castor 72: #include <sys/reboot.h>
1.1 deraadt 73: #ifdef KTRACE
74: #include <sys/ktrace.h>
75: #endif
1.46 jonathan 76:
1.58 jonathan 77: #include <mips/locore.h>
78: #include <mips/mips_opcode.h>
79:
1.78 jonathan 80: #include <vm/vm.h>
81: #include <vm/vm_kern.h>
82: #include <vm/vm_page.h>
83:
1.82 thorpej 84: #if defined(UVM)
85: #include <uvm/uvm_extern.h>
86: #endif
87:
1.70 jonathan 88: #include <machine/cpu.h>
89: #include <mips/trap.h>
1.1 deraadt 90: #include <machine/psl.h>
1.70 jonathan 91: #include <mips/reg.h>
92: #include <mips/regnum.h> /* symbolic register indices */
93: #include <mips/pte.h>
1.1 deraadt 94:
1.16 jonathan 95: #include <sys/cdefs.h>
96: #include <sys/syslog.h>
1.37 jonathan 97: #include <miscfs/procfs/procfs.h>
98:
1.69 jonathan 99: #ifdef DDB
100: #include <mips/db_machdep.h>
1.77 mhitch 101: #include <ddb/db_sym.h>
1.69 jonathan 102: #endif
103:
1.37 jonathan 104: /* all this to get prototypes for ipintr() and arpintr() */
105: #include <sys/socket.h>
106: #include <net/if.h>
107: #include <netinet/in.h>
1.51 is 108: #include <netinet/if_inarp.h>
1.37 jonathan 109: #include <netinet/ip_var.h>
1.39 mhitch 110:
111: #include "ppp.h"
1.16 jonathan 112:
1.53 jonathan 113: #if NPPP > 0
114: #include <net/ppp_defs.h> /* decls of struct pppstat for.. */
115: #include <net/if_pppvar.h> /* decl of enum for... */
116: #include <net/if_ppp.h> /* pppintr() prototype */
117: #endif
118:
1.71 jonathan 119:
1.33 jonathan 120: /*
121: * Port-specific hardware interrupt handler
122: */
1.23 jonathan 123:
1.92 jonathan 124: int astpending;
125: int want_resched;
126:
1.99 castor 127: int (*mips_hardware_intr) __P((unsigned, unsigned, unsigned, unsigned)) = 0;
128: void (*mips_software_intr) __P((int)) = 0;
129: int softisr; /* for extensible software interrupt framework */
1.1 deraadt 130:
1.92 jonathan 131: #if defined(MIPS3) && defined(MIPS3_INTERNAL_TIMER_INTERRUPT)
1.85 jonathan 132: u_int32_t mips3_intr_cycle_count;
1.92 jonathan 133: u_int32_t mips3_timer_delta;
1.85 jonathan 134: #endif
135:
1.99 castor 136: const char *trap_type[] = {
1.1 deraadt 137: "external interrupt",
138: "TLB modification",
139: "TLB miss (load or instr. fetch)",
140: "TLB miss (store)",
141: "address error (load or I-fetch)",
142: "address error (store)",
143: "bus error (I-fetch)",
144: "bus error (load or store)",
145: "system call",
146: "breakpoint",
147: "reserved instruction",
148: "coprocessor unusable",
149: "arithmetic overflow",
1.32 jonathan 150: "r4k trap/r3k reserved 13",
151: "r4k virtual coherency instruction/r3k reserved 14",
152: "r4k floating point/ r3k reserved 15",
153: "reserved 16",
154: "reserved 17",
155: "reserved 18",
156: "reserved 19",
157: "reserved 20",
158: "reserved 21",
159: "reserved 22",
1.46 jonathan 160: "r4000 watch",
1.32 jonathan 161: "reserved 24",
162: "reserved 25",
163: "reserved 26",
164: "reserved 27",
165: "reserved 28",
166: "reserved 29",
167: "reserved 30",
1.46 jonathan 168: "r4000 virtual coherency data",
1.1 deraadt 169: };
170:
1.99 castor 171: struct trapframe {
172: mips_reg_t tf_regs[17];
173: mips_reg_t tf_ra;
174: mips_reg_t tf_sr;
175: mips_reg_t tf_mullo;
176: mips_reg_t tf_mulhi;
177: mips_reg_t tf_epc;
178: };
179:
180: void userret __P((struct proc *, unsigned, u_quad_t));
181: void trap __P((unsigned, unsigned, unsigned, unsigned, struct trapframe *));
182: void syscall __P((unsigned, unsigned, unsigned));
183: void interrupt __P((unsigned, unsigned, unsigned));
184: void ast __P((unsigned));
185: void dealfpu __P((unsigned, unsigned, unsigned));
186:
187: extern void MachEmulateFP __P((unsigned));
188: extern void MachFPInterrupt __P((unsigned, unsigned, unsigned, mips_reg_t *));
1.66 mhitch 189:
1.33 jonathan 190: /*
191: * Other forward declarations.
192: */
1.98 nisimura 193: vaddr_t MachEmulateBranch __P((struct frame *, vaddr_t, unsigned, int));
1.16 jonathan 194:
1.99 castor 195: void
1.57 mhitch 196: userret(p, pc, sticks)
197: struct proc *p;
198: unsigned pc;
199: u_quad_t sticks;
200: {
201: int sig;
202:
203: /* take pending signals */
204: while ((sig = CURSIG(p)) != 0)
205: postsig(sig);
206: p->p_priority = p->p_usrpri;
207: if (want_resched) {
208: int s;
209: /*
210: * Since we are curproc, a clock interrupt could
211: * change our priority without changing run queues
212: * (the running process is not kept on a run queue).
213: * If this happened after we setrunqueue ourselves but
214: * before we switch()'ed, we might not be on the queue
215: * indicated by our priority.
216: */
217: s = splstatclock();
218: setrunqueue(p);
219: p->p_stats->p_ru.ru_nivcsw++;
220: mi_switch();
221: splx(s);
222: while ((sig = CURSIG(p)) != 0)
223: postsig(sig);
224: }
225: /*
226: * If profiling, charge system time to the trapped pc.
227: */
228: if (p->p_flag & P_PROFIL) {
229: extern int psratio;
230:
231: addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
232: }
233: curpriority = p->p_priority;
234: }
1.1 deraadt 235:
1.63 mhitch 236: #define DELAYBRANCH(x) ((int)(x)<0)
1.1 deraadt 237: /*
1.57 mhitch 238: * Process a system call.
239: *
240: * System calls are strange beasts. They are passed the syscall number
241: * in v0, and the arguments in the registers (as normal). They return
242: * an error flag in a3 (if a3 != 0 on return, the syscall had an error),
243: * and the return value (if any) in v0 and possibly v1.
244: */
245: void
1.99 castor 246: syscall(status, cause, opc)
247: unsigned status;
248: unsigned cause;
249: unsigned opc;
1.1 deraadt 250: {
1.57 mhitch 251: struct proc *p = curproc;
1.99 castor 252: struct frame *frame = (struct frame *)p->p_md.md_regs;
1.1 deraadt 253: u_quad_t sticks;
1.57 mhitch 254: int args[8], rval[2], error;
255: size_t code, numsys, nsaved, argsiz;
256: struct sysent *callp;
257:
1.82 thorpej 258: #if defined(UVM)
259: uvmexp.syscalls++;
260: #else
1.57 mhitch 261: cnt.v_syscall++;
1.82 thorpej 262: #endif
1.76 jonathan 263:
264: if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV))
265: splx(MIPS_SR_INT_IE | (status & MIPS_HARD_INT_MASK));
1.57 mhitch 266:
267: sticks = p->p_sticks;
268: if (DELAYBRANCH(cause))
1.98 nisimura 269: frame->f_regs[PC] = MachEmulateBranch(frame, opc, 0, 0);
1.57 mhitch 270: else
271: frame->f_regs[PC] = opc + sizeof(int);
272: callp = p->p_emul->e_sysent;
273: numsys = p->p_emul->e_nsysent;
274: code = frame->f_regs[V0];
275: switch (code) {
276: case SYS_syscall:
277: /*
278: * Code is first argument, followed by actual args.
279: */
280: code = frame->f_regs[A0];
281: args[0] = frame->f_regs[A1];
282: args[1] = frame->f_regs[A2];
283: args[2] = frame->f_regs[A3];
284: nsaved = 3;
285: break;
286: case SYS___syscall:
287: /*
288: * Like syscall, but code is a quad, so as to maintain
289: * quad alignment for the rest of the arguments.
290: */
291: code = frame->f_regs[A0 + _QUAD_LOWWORD];
292: args[0] = frame->f_regs[A2];
293: args[1] = frame->f_regs[A3];
294: nsaved = 2;
295: break;
296: default:
297: args[0] = frame->f_regs[A0];
298: args[1] = frame->f_regs[A1];
299: args[2] = frame->f_regs[A2];
300: args[3] = frame->f_regs[A3];
301: nsaved = 4;
302: break;
303: }
304: if (code >= p->p_emul->e_nsysent)
305: callp += p->p_emul->e_nosys;
306: else
307: callp += code;
308: argsiz = callp->sy_argsize / sizeof(int);
309: if (argsiz > nsaved) {
1.99 castor 310: #if 0
311: error = copyin(
312: (void *)((int *)frame->f_regs[SP] + 4),
313: (void *)(args + nsaved),
314: (argsiz - nsaved) * sizeof(int));
315: #else
316: int sp32;
317: sp32 = frame->f_regs[SP];
1.57 mhitch 318: error = copyin(
1.99 castor 319: (void *)((int *)sp32 + 4),
320: (void *)(args + nsaved),
1.57 mhitch 321: (argsiz - nsaved) * sizeof(int));
1.99 castor 322: #endif
1.57 mhitch 323: if (error)
324: goto bad;
325: }
326: #ifdef SYSCALL_DEBUG
327: scdebug_call(p, code, args);
328: #endif
329: #ifdef KTRACE
330: if (KTRPOINT(p, KTR_SYSCALL))
331: ktrsyscall(p->p_tracep, code, callp->sy_argsize, args);
332: #endif
333: rval[0] = 0;
334: rval[1] = frame->f_regs[V1];
335: #ifdef DEBUG
336: /* XXX save code */
337: #endif
338: error = (*callp->sy_call)(p, args, rval);
339:
340: #ifdef DEBUG
341: /* XXX save syscall result in trapdebug */
342: #endif
343: switch (error) {
344: case 0:
345: frame->f_regs[V0] = rval[0];
346: frame->f_regs[V1] = rval[1];
347: frame->f_regs[A3] = 0;
348: break;
349: case ERESTART:
350: frame->f_regs[PC] = opc;
351: break;
352: case EJUSTRETURN:
353: break; /* nothing to do */
354: default:
355: bad:
356: frame->f_regs[V0] = error;
357: frame->f_regs[A3] = 1;
358: break;
359: }
360: #ifdef SYSCALL_DEBUG
361: scdebug_ret(p, code, error, rval);
362: #endif
363: userret(p, opc, sticks);
364: #ifdef KTRACE
365: if (KTRPOINT(p, KTR_SYSRET))
366: ktrsysret(p->p_tracep, code, error, rval[0]);
367: #endif
368: }
369:
370: /*
371: * fork syscall returns directly to user process via proc_trampoline,
372: * which will be called the very first time when child gets running.
373: * no more FORK_BRAINDAMAGED.
374: */
375: void
1.95 thorpej 376: child_return(arg)
377: void *arg;
1.57 mhitch 378: {
1.95 thorpej 379: struct proc *p = arg;
1.57 mhitch 380: struct frame *frame = (struct frame *)p->p_md.md_regs;
381:
382: frame->f_regs[V0] = 0;
383: frame->f_regs[V1] = 1;
384: frame->f_regs[A3] = 0;
385: userret(p, frame->f_regs[PC] - sizeof(int), 0); /* XXX */
386: #ifdef KTRACE
387: if (KTRPOINT(p, KTR_SYSRET))
388: ktrsysret(p->p_tracep, SYS_fork, 0, 0);
389: #endif
390: }
391:
392: #ifdef MIPS3
1.65 jonathan 393: #define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 394: #else
1.65 jonathan 395: #define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 396: #endif
397: #define KERNLAND(x) ((int)(x) < 0)
398:
399: /*
400: * Trap is called from locore to handle most types of processor traps.
401: * System calls are broken out for efficiency. MIPS can handle software
402: * interrupts as a part of real interrupt processing.
403: */
404: void
405: trap(status, cause, vaddr, opc, frame)
1.99 castor 406: unsigned status;
407: unsigned cause;
408: unsigned vaddr;
409: unsigned opc;
410: struct trapframe *frame;
1.57 mhitch 411: {
412: int type, sig;
413: int ucode = 0;
414: u_quad_t sticks = 0;
415: struct proc *p = curproc;
1.1 deraadt 416: vm_prot_t ftype;
1.99 castor 417: extern struct proc *fpcurproc;
1.57 mhitch 418: extern void fswintrberr __P((void));
1.1 deraadt 419:
1.82 thorpej 420: #if defined(UVM)
421: uvmexp.traps++;
422: #else
1.1 deraadt 423: cnt.v_trap++;
1.82 thorpej 424: #endif
1.57 mhitch 425: type = TRAPTYPE(cause);
426: if (USERMODE(status)) {
1.1 deraadt 427: type |= T_USER;
428: sticks = p->p_sticks;
429: }
430:
1.60 jonathan 431: if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV))
1.65 jonathan 432: splx((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
1.1 deraadt 433:
434: switch (type) {
1.57 mhitch 435: default:
436: dopanic:
1.97 nisimura 437: printf("trap: %s in %s mode\n",
438: trap_type[TRAPTYPE(cause)],
439: USERMODE(status) ? "user" : "kernel");
440: printf("status=0x%x, cause=0x%x, epc=0x%x, vaddr=0x%x\n",
441: status, cause, opc, vaddr);
1.57 mhitch 442: if (curproc != NULL)
1.97 nisimura 443: printf("pid=%d cmd=%s usp=0x%x ",
444: p->p_pid, p->p_comm,
445: (int)((struct frame *)p->p_md.md_regs)->f_regs[SP]);
1.57 mhitch 446: else
1.97 nisimura 447: printf("curproc == NULL ");
448: printf("ksp=0x%x\n", (int)&status);
1.99 castor 449: #ifdef DDB
450: kdb_trap(type, (mips_reg_t *) frame);
451: /* XXX force halt XXX */
452: #else
1.57 mhitch 453: panic("trap");
1.99 castor 454: #endif
1.57 mhitch 455: /*NOTREACHED*/
1.1 deraadt 456: case T_TLB_MOD:
1.57 mhitch 457: if (KERNLAND(vaddr)) {
458: pt_entry_t *pte;
459: unsigned entry;
1.98 nisimura 460: vaddr_t pa;
1.1 deraadt 461:
1.57 mhitch 462: pte = kvtopte(vaddr);
1.1 deraadt 463: entry = pte->pt_entry;
1.60 jonathan 464: if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
1.57 mhitch 465: panic("ktlbmod: invalid pte");
466: }
1.60 jonathan 467: /*XXX MIPS3? */ if (entry & mips_pg_ro_bit()) {
1.1 deraadt 468: /* write to read only page in the kernel */
469: ftype = VM_PROT_WRITE;
1.57 mhitch 470: goto kernelfault;
1.1 deraadt 471: }
1.60 jonathan 472: entry |= mips_pg_m_bit();
1.1 deraadt 473: pte->pt_entry = entry;
1.57 mhitch 474: vaddr &= ~PGOFSET;
475: MachTLBUpdate(vaddr, entry);
476: pa = pfn_to_vad(entry);
1.96 mhitch 477: if (!IS_VM_PHYSADDR(pa)) {
478: printf("ktlbmod: va %x pa %lx\n", vaddr, pa);
1.57 mhitch 479: panic("ktlbmod: unmanaged page");
1.96 mhitch 480: }
481: pmap_set_modified(pa);
1.57 mhitch 482: return; /* KERN */
1.1 deraadt 483: }
1.57 mhitch 484: /*FALLTHROUGH*/
1.1 deraadt 485: case T_TLB_MOD+T_USER:
486: {
1.57 mhitch 487: pt_entry_t *pte;
488: unsigned entry;
1.98 nisimura 489: vaddr_t pa;
1.57 mhitch 490: pmap_t pmap;
491:
492: pmap = p->p_vmspace->vm_map.pmap;
493: if (!(pte = pmap_segmap(pmap, vaddr)))
494: panic("utlbmod: invalid segmap");
495: pte += (vaddr >> PGSHIFT) & (NPTEPG - 1);
1.3 glass 496: entry = pte->pt_entry;
1.60 jonathan 497: if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
1.57 mhitch 498: panic("utlbmod: invalid pte");
499:
1.60 jonathan 500: /*XXX MIPS3? */ if (entry & mips_pg_ro_bit()) {
1.3 glass 501: /* write to read only page */
1.1 deraadt 502: ftype = VM_PROT_WRITE;
1.57 mhitch 503: goto pagefault;
1.1 deraadt 504: }
1.60 jonathan 505: entry |= mips_pg_m_bit();
1.3 glass 506: pte->pt_entry = entry;
1.57 mhitch 507: vaddr = (vaddr & ~PGOFSET) |
1.64 jonathan 508: (pmap->pm_tlbpid << MIPS_TLB_PID_SHIFT);
1.57 mhitch 509: MachTLBUpdate(vaddr, entry);
510: pa = pfn_to_vad(entry);
1.96 mhitch 511: if (!IS_VM_PHYSADDR(pa)) {
512: printf("utlbmod: va %x pa %lx\n", vaddr, pa);
1.57 mhitch 513: panic("utlbmod: unmanaged page");
1.96 mhitch 514: }
515: pmap_set_modified(pa);
1.57 mhitch 516: if (type & T_USER)
517: userret(p, opc, sticks);
518: return; /* GEN */
1.1 deraadt 519: }
520: case T_TLB_LD_MISS:
521: case T_TLB_ST_MISS:
1.57 mhitch 522: ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
523: if (KERNLAND(vaddr))
524: goto kernelfault;
1.1 deraadt 525: /*
526: * It is an error for the kernel to access user space except
527: * through the copyin/copyout routines.
528: */
1.99 castor 529: if (p->p_addr->u_pcb.pcb_onfault == NULL)
1.57 mhitch 530: goto dopanic;
1.1 deraadt 531: /* check for fuswintr() or suswintr() getting a page fault */
1.99 castor 532: if (p->p_addr->u_pcb.pcb_onfault == (caddr_t)fswintrberr) {
533: frame->tf_epc = (int)fswintrberr;
1.57 mhitch 534: return; /* KERN */
535: }
536: goto pagefault;
1.1 deraadt 537: case T_TLB_LD_MISS+T_USER:
538: ftype = VM_PROT_READ;
1.57 mhitch 539: goto pagefault;
1.1 deraadt 540: case T_TLB_ST_MISS+T_USER:
541: ftype = VM_PROT_WRITE;
1.57 mhitch 542: pagefault: ;
1.1 deraadt 543: {
1.98 nisimura 544: vaddr_t va;
1.57 mhitch 545: struct vmspace *vm;
546: vm_map_t map;
1.1 deraadt 547: int rv;
548:
1.3 glass 549: vm = p->p_vmspace;
550: map = &vm->vm_map;
1.98 nisimura 551: va = trunc_page(vaddr);
1.82 thorpej 552: #if defined(UVM)
553: rv = uvm_fault(map, va, 0, ftype);
554: #ifdef VMFAULT_TRACE
555: printf(
556: "uvm_fault(%p (pmap %p), %lx (0x%x), 0, ftype) -> %d at pc %p\n",
557: map, vm->vm_map.pmap, va, vaddr, ftype, rv, (void*)opc);
558: #endif
559: #else /* ! UVM */
1.1 deraadt 560: rv = vm_fault(map, va, ftype, FALSE);
1.5 glass 561: #ifdef VMFAULT_TRACE
1.57 mhitch 562: printf(
1.75 jonathan 563: "vm_fault(%p (pmap %p), %lx (0x%x), %d, %d) -> %d at pc %p\n",
564: map, vm->vm_map.pmap, va, vaddr, ftype, FALSE, rv,
565: (void*)opc);
1.5 glass 566: #endif
1.82 thorpej 567: #endif /* UVM */
1.1 deraadt 568: /*
569: * If this was a stack access we keep track of the maximum
570: * accessed stack size. Also, if vm_fault gets a protection
571: * failure it is due to accessing the stack region outside
572: * the current limit and we need to reflect that as an access
573: * error.
574: */
575: if ((caddr_t)va >= vm->vm_maxsaddr) {
576: if (rv == KERN_SUCCESS) {
577: unsigned nss;
578:
579: nss = clrnd(btoc(USRSTACK-(unsigned)va));
580: if (nss > vm->vm_ssize)
581: vm->vm_ssize = nss;
1.57 mhitch 582: }
583: else if (rv == KERN_PROTECTION_FAILURE)
1.1 deraadt 584: rv = KERN_INVALID_ADDRESS;
585: }
586: if (rv == KERN_SUCCESS) {
1.99 castor 587: if (type & T_USER) {
1.57 mhitch 588: userret(p, opc, sticks);
1.99 castor 589: }
1.57 mhitch 590: return; /* GEN */
591: }
592: if ((type & T_USER) == 0)
593: goto copyfault;
594: sig = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
595: ucode = vaddr;
596: break; /* SIGNAL */
1.99 castor 597: }
1.57 mhitch 598: kernelfault: ;
599: {
1.98 nisimura 600: vaddr_t va;
1.57 mhitch 601: int rv;
602:
1.98 nisimura 603: va = trunc_page(vaddr);
1.82 thorpej 604: #if defined(UVM)
605: rv = uvm_fault(kernel_map, va, 0, ftype);
606: #else
1.57 mhitch 607: rv = vm_fault(kernel_map, va, ftype, FALSE);
1.82 thorpej 608: #endif
1.57 mhitch 609: if (rv == KERN_SUCCESS)
610: return; /* KERN */
611: /*FALLTHROUGH*/
1.1 deraadt 612: }
1.57 mhitch 613: case T_ADDR_ERR_LD: /* misaligned access */
614: case T_ADDR_ERR_ST: /* misaligned access */
615: case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */
616: copyfault:
1.99 castor 617: if (p->p_addr->u_pcb.pcb_onfault == NULL)
1.57 mhitch 618: goto dopanic;
1.99 castor 619: frame->tf_epc = (int)p->p_addr->u_pcb.pcb_onfault;
1.57 mhitch 620: return; /* KERN */
1.1 deraadt 621:
622: case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
623: case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
624: case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */
625: case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */
1.57 mhitch 626: sig = SIGSEGV;
627: ucode = vaddr;
628: break; /* SIGNAL */
1.69 jonathan 629:
630: case T_BREAK:
631: #ifdef DDB
1.99 castor 632: kdb_trap(type, (mips_reg_t *) frame);
1.69 jonathan 633: return; /* KERN */
634: #else
635: goto dopanic;
636: #endif
1.1 deraadt 637: case T_BREAK+T_USER:
638: {
1.57 mhitch 639: unsigned va, instr;
640: int rv;
1.1 deraadt 641:
642: /* compute address of break instruction */
1.57 mhitch 643: va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc;
1.1 deraadt 644:
645: /* read break instruction */
1.99 castor 646: instr = fuiword((void *)va);
1.69 jonathan 647: #ifdef DEBUG
648: /*XXX*/ printf("break insn 0x%x\n", instr);
649: #endif
1.57 mhitch 650:
1.65 jonathan 651: if (p->p_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
1.57 mhitch 652: sig = SIGTRAP;
1.1 deraadt 653: break;
654: }
1.97 nisimura 655: /*
1.57 mhitch 656: * Restore original instruction and clear BP
1.97 nisimura 657: */
1.99 castor 658: rv = suiword((void *)va, p->p_md.md_ss_instr);
1.57 mhitch 659: if (rv < 0) {
1.98 nisimura 660: vaddr_t sa, ea;
661: sa = trunc_page(va);
662: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 663: #if defined(UVM)
664: rv = uvm_map_protect(&p->p_vmspace->vm_map,
665: sa, ea, VM_PROT_DEFAULT, FALSE);
666: if (rv == KERN_SUCCESS) {
1.99 castor 667: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.82 thorpej 668: (void)uvm_map_protect(&p->p_vmspace->vm_map,
669: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
670: }
671: #else
1.57 mhitch 672: rv = vm_map_protect(&p->p_vmspace->vm_map,
673: sa, ea, VM_PROT_DEFAULT, FALSE);
1.1 deraadt 674: if (rv == KERN_SUCCESS) {
1.99 castor 675: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.57 mhitch 676: (void)vm_map_protect(&p->p_vmspace->vm_map,
677: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1.1 deraadt 678: }
1.82 thorpej 679: #endif /* UVM */
1.97 nisimura 680: }
1.69 jonathan 681: MachFlushCache();
682:
1.57 mhitch 683: if (rv < 0)
684: printf("Warning: can't restore instruction at 0x%x: 0x%x\n",
1.3 glass 685: p->p_md.md_ss_addr, p->p_md.md_ss_instr);
1.1 deraadt 686: p->p_md.md_ss_addr = 0;
1.57 mhitch 687: sig = SIGTRAP;
688: break; /* SIGNAL */
1.99 castor 689: }
1.1 deraadt 690: case T_RES_INST+T_USER:
1.57 mhitch 691: sig = SIGILL;
692: break; /* SIGNAL */
1.1 deraadt 693: case T_COP_UNUSABLE+T_USER:
1.65 jonathan 694: if ((cause & MIPS_CR_COP_ERR) != 0x10000000) {
1.57 mhitch 695: sig = SIGILL; /* only FPU instructions allowed */
696: break; /* SIGNAL */
1.97 nisimura 697: }
1.57 mhitch 698: switchfpregs(fpcurproc, p);
699: fpcurproc = p;
1.97 nisimura 700: ((struct frame *)p->p_md.md_regs)->f_regs[SR]
701: |= MIPS_SR_COP_1_BIT;
1.1 deraadt 702: p->p_md.md_flags |= MDP_FPUSED;
1.57 mhitch 703: userret(p, opc, sticks);
704: return; /* GEN */
1.32 jonathan 705: case T_FPE+T_USER:
1.99 castor 706: /* dealfpu(status, cause, opc); */
1.57 mhitch 707: MachFPInterrupt(status, cause, opc, p->p_md.md_regs);
708: userret(p, opc, sticks);
709: return; /* GEN */
1.1 deraadt 710: case T_OVFLOW+T_USER:
1.57 mhitch 711: sig = SIGFPE;
712: break; /* SIGNAL */
1.97 nisimura 713: }
714: ((struct frame *)p->p_md.md_regs)->f_regs[CAUSE] = cause;
715: ((struct frame *)p->p_md.md_regs)->f_regs[BADVADDR] = vaddr;
1.57 mhitch 716: trapsignal(p, sig, ucode);
717: if ((type & T_USER) == 0)
718: panic("trapsignal");
719: userret(p, opc, sticks);
720: return;
721: }
1.1 deraadt 722:
1.57 mhitch 723: #include <net/netisr.h>
1.79 veego 724: #include "arp.h"
1.57 mhitch 725: #include "ppp.h"
1.1 deraadt 726:
1.80 wrstuden 727: #ifdef NS
1.87 jonathan 728: #include <netns/ns_var.h>
1.80 wrstuden 729: #endif
1.87 jonathan 730:
1.80 wrstuden 731: #ifdef ISO
1.87 jonathan 732: #include <netiso/iso.h>
733: #include <netiso/clnp.h>
734: #endif
735:
736: #ifdef CCITT
737: #include <netccitt/x25.h>
738: #include <netccitt/pk.h>
739: #include <netccitt/pk_extern.h>
740: #endif
741:
742: #ifdef NATM
743: #include <netnatm/natm.h>
744: #endif
745: #ifdef NETATALK
746: #include <netatalk/at_extern.h>
1.80 wrstuden 747: #endif
748:
1.57 mhitch 749: /*
750: * Handle an interrupt.
1.99 castor 751: * N.B., curproc might be NULL.
1.57 mhitch 752: */
1.22 jonathan 753: void
1.99 castor 754: interrupt(status, cause, pc)
755: unsigned status;
756: unsigned cause;
757: unsigned pc;
1.1 deraadt 758: {
1.57 mhitch 759: unsigned mask;
1.85 jonathan 760: extern u_int32_t mips3_cycle_count __P((void));
761:
762: mask = cause & status; /* pending interrupts & enable mask */
763:
1.99 castor 764: #if defined(MIPS3) && defined(MIPS_INT_MASK_CLOCK)
765: if ((mask & MIPS_INT_MASK_CLOCK) && CPUISMIPS3)
1.85 jonathan 766: mips3_intr_cycle_count = mips3_cycle_count();
1.1 deraadt 767: #endif
768:
1.82 thorpej 769: #if defined(UVM)
770: uvmexp.intrs++;
771: #else
1.1 deraadt 772: cnt.v_intr++;
1.82 thorpej 773: #endif
1.99 castor 774: /* real device interrupt */
775: if ((mask & INT_MASK_REAL_DEV) && mips_hardware_intr) {
1.57 mhitch 776: splx((*mips_hardware_intr)(mask, pc, status, cause));
1.99 castor 777: }
1.83 jonathan 778:
1.99 castor 779: #ifdef INT_MASK_FPU_DEAL
780: if (mask & INT_MASK_FPU_DEAL) {
1.28 jonathan 781: intrcnt[FPU_INTR]++;
1.99 castor 782: if (!USERMODE(status))
783: panic("kernel used FPU: PC %x, CR %x, SR %x",
784: pc, cause, status);
785: /* dealfpu(status, cause, pc); */
786: MachFPInterrupt(status, cause, pc, curproc->p_md.md_regs);
1.1 deraadt 787: }
1.99 castor 788: #endif
1.14 jonathan 789:
1.99 castor 790: /* simulated interrupt */
1.65 jonathan 791: if ((mask & MIPS_SOFT_INT_MASK_1)
1.99 castor 792: || ((netisr|softisr) && (status & MIPS_SOFT_INT_MASK_1))) {
793: register int isr, sisr;
794: isr = netisr; netisr = 0;
795: sisr = softisr; softisr = 0;
1.1 deraadt 796: clearsoftnet();
1.82 thorpej 797: #if defined(UVM)
798: uvmexp.softs++;
799: #else
1.1 deraadt 800: cnt.v_soft++;
1.82 thorpej 801: #endif
1.99 castor 802: if (isr) {
803: intrcnt[SOFTNET_INTR]++;
1.1 deraadt 804: #ifdef INET
1.79 veego 805: #if NARP > 0
1.99 castor 806: if (isr & (1 << NETISR_ARP)) arpintr();
1.57 mhitch 807: #endif
1.99 castor 808: if (isr & (1 << NETISR_IP)) ipintr();
1.80 wrstuden 809: #endif
810: #ifdef NETATALK
1.99 castor 811: if (isr & (1 << NETISR_ATALK)) atintr();
1.1 deraadt 812: #endif
813: #ifdef NS
1.99 castor 814: if (isr & (1 << NETISR_NS)) nsintr();
1.1 deraadt 815: #endif
816: #ifdef ISO
1.99 castor 817: if (isr & (1 << NETISR_ISO)) clnlintr();
1.87 jonathan 818: #endif
819: #ifdef CCITT
1.99 castor 820: if (isr & (1 << NETISR_CCITT)) ccittintr();
1.1 deraadt 821: #endif
1.20 paulus 822: #if NPPP > 0
1.99 castor 823: if (isr & (1 << NETISR_PPP)) pppintr();
1.20 paulus 824: #endif
1.99 castor 825: }
826: if (sisr && mips_software_intr)
827: (*mips_software_intr)(sisr);
1.21 jonathan 828: }
1.20 paulus 829:
1.99 castor 830: /* 'softclock' interrupt */
1.65 jonathan 831: if (mask & MIPS_SOFT_INT_MASK_0) {
1.14 jonathan 832: clearsoftclock();
1.82 thorpej 833: #if defined(UVM)
834: uvmexp.softs++;
835: #else
1.57 mhitch 836: cnt.v_soft++;
1.82 thorpej 837: #endif
1.28 jonathan 838: intrcnt[SOFTCLOCK_INTR]++;
1.14 jonathan 839: softclock();
1.43 jonathan 840: }
1.1 deraadt 841: }
842:
843: /*
1.57 mhitch 844: * Handle asynchronous software traps.
845: * This is called from MachUserIntr() either to deliver signals or
846: * to make involuntary context switch (preemption).
1.1 deraadt 847: */
1.22 jonathan 848: void
1.57 mhitch 849: ast(pc)
1.1 deraadt 850: unsigned pc; /* program counter where to continue */
851: {
1.57 mhitch 852: struct proc *p = curproc;
1.1 deraadt 853:
1.82 thorpej 854: #if defined(UVM)
855: uvmexp.softs++;
856: #else
1.1 deraadt 857: cnt.v_soft++;
1.82 thorpej 858: #endif
1.1 deraadt 859: astpending = 0;
1.3 glass 860: if (p->p_flag & P_OWEUPC) {
861: p->p_flag &= ~P_OWEUPC;
1.1 deraadt 862: ADDUPROF(p);
863: }
1.57 mhitch 864: userret(p, pc, p->p_sticks);
865: }
1.1 deraadt 866:
1.99 castor 867: /* XXX XXX XXX */
868: #define set_cp0sr(x) \
869: { \
870: register int _r = (x); \
871: __asm __volatile(" \
872: .set noreorder ; \
873: mtc0 %0, $12 ; \
874: nop;nop;nop;nop ; \
875: .set reorder" \
876: : : "r"(_r)); \
877: }
878:
879: #define get_fpcsr() \
880: ({ \
881: register int _r; \
882: __asm __volatile(" \
883: .set noreorder ; \
884: cfc1 %0, $31 ; \
885: cfc1 %0, $31 ; \
886: nop ; \
887: .set reorder" \
888: : "=r"(_r)); \
889: _r; \
890: })
891:
892: #define clr_fpcsr() \
893: __asm __volatile("ctc1 $0, $31")
894: /* XXX XXX XXX */
1.1 deraadt 895:
1.99 castor 896: /*
897: * Software emulation of umimplemented floating point instructions
898: */
1.22 jonathan 899: void
1.99 castor 900: dealfpu(status, cause, opc)
901: unsigned status;
902: unsigned cause;
903: unsigned opc;
1.1 deraadt 904: {
1.99 castor 905: struct frame *f = (struct frame *)curproc->p_md.md_regs;
906: unsigned v0;
1.100 ! nisimura 907: int sig;
1.1 deraadt 908:
1.99 castor 909: set_cp0sr(status | MIPS_SR_COP_1_BIT);
910: v0 = get_fpcsr();
1.100 ! nisimura 911:
! 912: /* was it 'unimplemented operation' ? */
! 913: if ((v0 & MIPS_FPU_EXCEPTION_UNIMPL) == 0) {
! 914: sig = SIGFPE;
! 915: goto notforemulation;
! 916: }
! 917:
1.99 castor 918: if (DELAYBRANCH(cause)) {
919: f->f_regs[PC] = MachEmulateBranch(f, opc, v0, 0);
920: v0 = *(unsigned *)(opc + sizeof(unsigned));
921: }
922: else {
923: f->f_regs[PC] = opc + sizeof(unsigned);
924: v0 = *(unsigned *)opc;
925: }
1.100 ! nisimura 926: /* make sure the instruction is for FPU */
! 927: if (MIPS_OPCODE_C1 != (v0 >> MIPS_OPCODE_SHIFT)) {
! 928: sig = SIGILL;
! 929: goto notforemulation;
! 930: }
1.99 castor 931:
932: MachEmulateFP(v0);
933: set_cp0sr(status &~ MIPS_SR_COP_1_BIT);
934: return;
935:
1.100 ! nisimura 936: notforemulation:
1.99 castor 937: clr_fpcsr();
1.100 ! nisimura 938: trapsignal(curproc, sig, v0);
1.99 castor 939: set_cp0sr(status &~ MIPS_SR_COP_1_BIT);
940: return;
1.1 deraadt 941: }
942:
1.46 jonathan 943: /*
1.98 nisimura 944: * Analyse 'next' PC address taking account of branch/jump instructions
1.46 jonathan 945: */
1.98 nisimura 946: vaddr_t
947: MachEmulateBranch(f, instpc, fpuCSR, allowNonBranch)
948: struct frame *f;
949: vaddr_t instpc;
950: unsigned fpuCSR;
1.1 deraadt 951: int allowNonBranch;
952: {
1.98 nisimura 953: #define BRANCHTARGET(p) (4 + (p) + ((short)((InstFmt *)(p))->IType.imm << 2))
1.1 deraadt 954: InstFmt inst;
1.98 nisimura 955: vaddr_t nextpc;
1.24 jonathan 956:
1.98 nisimura 957: if (instpc < MIPS_KSEG0_START)
958: inst.word = fuiword((void *)instpc);
959: else
960: inst.word = *(unsigned *)instpc;
1.46 jonathan 961:
1.1 deraadt 962: switch ((int)inst.JType.op) {
963: case OP_SPECIAL:
1.98 nisimura 964: if (inst.RType.func == OP_JR || inst.RType.func == OP_JALR)
965: nextpc = f->f_regs[inst.RType.rs];
966: else if (allowNonBranch)
967: nextpc = instpc + 4;
968: else
969: panic("MachEmulateBranch: Non-branch");
1.1 deraadt 970: break;
971:
972: case OP_BCOND:
973: switch ((int)inst.IType.rt) {
974: case OP_BLTZ:
975: case OP_BLTZAL:
1.34 jonathan 976: case OP_BLTZL: /* squashed */
977: case OP_BLTZALL: /* squashed */
1.98 nisimura 978: if ((int)(f->f_regs[inst.RType.rs]) < 0)
979: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 980: else
1.98 nisimura 981: nextpc = instpc + 8;
1.1 deraadt 982: break;
983:
1.34 jonathan 984: case OP_BGEZ:
1.1 deraadt 985: case OP_BGEZAL:
1.34 jonathan 986: case OP_BGEZL: /* squashed */
987: case OP_BGEZALL: /* squashed */
1.98 nisimura 988: if ((int)(f->f_regs[inst.RType.rs]) >= 0)
989: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 990: else
1.98 nisimura 991: nextpc = instpc + 8;
1.1 deraadt 992: break;
993:
994: default:
995: panic("MachEmulateBranch: Bad branch cond");
996: }
997: break;
998:
999: case OP_J:
1000: case OP_JAL:
1.98 nisimura 1001: nextpc = (inst.JType.target << 2) |
1002: ((unsigned)instpc & 0xF0000000);
1.1 deraadt 1003: break;
1004:
1005: case OP_BEQ:
1.98 nisimura 1006: case OP_BEQL: /* squashed */
1007: if (f->f_regs[inst.RType.rs] == f->f_regs[inst.RType.rt])
1008: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 1009: else
1.98 nisimura 1010: nextpc = instpc + 8;
1.1 deraadt 1011: break;
1012:
1013: case OP_BNE:
1.98 nisimura 1014: case OP_BNEL: /* squashed */
1015: if (f->f_regs[inst.RType.rs] != f->f_regs[inst.RType.rt])
1016: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 1017: else
1.98 nisimura 1018: nextpc = instpc + 8;
1.1 deraadt 1019: break;
1020:
1021: case OP_BLEZ:
1.98 nisimura 1022: case OP_BLEZL: /* squashed */
1023: if ((int)(f->f_regs[inst.RType.rs]) <= 0)
1024: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 1025: else
1.98 nisimura 1026: nextpc = instpc + 8;
1.1 deraadt 1027: break;
1028:
1029: case OP_BGTZ:
1.98 nisimura 1030: case OP_BGTZL: /* squashed */
1031: if ((int)(f->f_regs[inst.RType.rs]) > 0)
1032: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 1033: else
1.98 nisimura 1034: nextpc = instpc + 8;
1.1 deraadt 1035: break;
1036:
1037: case OP_COP1:
1.98 nisimura 1038: if (inst.RType.rs == OP_BCx || inst.RType.rs == OP_BCy) {
1039: int condition = (fpuCSR & MIPS_FPU_COND_BIT) != 0;
1040: if ((inst.RType.rt & COPz_BC_TF_MASK) != COPz_BC_TRUE)
1041: condition = !condition;
1.1 deraadt 1042: if (condition)
1.98 nisimura 1043: nextpc = BRANCHTARGET(instpc);
1.1 deraadt 1044: else
1.98 nisimura 1045: nextpc = instpc + 8;
1.1 deraadt 1046: }
1.98 nisimura 1047: else if (allowNonBranch)
1048: nextpc = instpc + 4;
1049: else
1050: panic("MachEmulateBranch: Bad COP1 branch instruction");
1.1 deraadt 1051: break;
1052:
1053: default:
1054: if (!allowNonBranch)
1055: panic("MachEmulateBranch: Non-branch instruction");
1.98 nisimura 1056: nextpc = instpc + 4;
1.1 deraadt 1057: }
1.98 nisimura 1058: return nextpc;
1059: #undef BRANCHTARGET
1.1 deraadt 1060: }
1061:
1.99 castor 1062: /* XXX need to rewrite acient comment XXX
1.1 deraadt 1063: * This routine is called by procxmt() to single step one instruction.
1064: * We do this by storing a break instruction after the current instruction,
1065: * resuming execution, and then restoring the old instruction.
1066: */
1.22 jonathan 1067: int
1.54 jonathan 1068: mips_singlestep(p)
1.57 mhitch 1069: struct proc *p;
1.1 deraadt 1070: {
1.97 nisimura 1071: struct frame *f = (struct frame *)p->p_md.md_regs;
1.98 nisimura 1072: vaddr_t pc, va;
1.97 nisimura 1073: int rv;
1.1 deraadt 1074:
1.97 nisimura 1075: if (p->p_md.md_ss_addr) {
1.45 christos 1076: printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1.99 castor 1077: p->p_comm, p->p_pid, p->p_md.md_ss_addr, (int)va);
1.97 nisimura 1078: return EFAULT;
1.1 deraadt 1079: }
1.98 nisimura 1080: pc = (vaddr_t)f->f_regs[PC];
1081: if (fuiword((void *)pc) != 0) /* not a NOP instruction */
1082: va = MachEmulateBranch(f, pc,
1.97 nisimura 1083: p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1);
1084: else
1.99 castor 1085: va = pc + sizeof(int);
1.1 deraadt 1086: p->p_md.md_ss_addr = va;
1.99 castor 1087: p->p_md.md_ss_instr = fuiword((void *)va);
1088: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.97 nisimura 1089: if (rv < 0) {
1.98 nisimura 1090: vaddr_t sa, ea;
1091: sa = trunc_page(va);
1092: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 1093: #if defined(UVM)
1094: rv = uvm_map_protect(&p->p_vmspace->vm_map,
1095: sa, ea, VM_PROT_DEFAULT, FALSE);
1.1 deraadt 1096: if (rv == KERN_SUCCESS) {
1.99 castor 1097: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.82 thorpej 1098: (void)uvm_map_protect(&p->p_vmspace->vm_map,
1099: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1100: }
1101: #else
1102: rv = vm_map_protect(&p->p_vmspace->vm_map,
1103: sa, ea, VM_PROT_DEFAULT, FALSE);
1104: if (rv == KERN_SUCCESS) {
1.99 castor 1105: rv = suiword((void *)va, MIPS_BREAK_SSTEP);
1.82 thorpej 1106: (void)vm_map_protect(&p->p_vmspace->vm_map,
1107: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1.1 deraadt 1108: }
1.82 thorpej 1109: #endif /* UVM */
1.1 deraadt 1110: }
1.3 glass 1111: #if 0
1.45 christos 1112: printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
1.1 deraadt 1113: p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1.99 castor 1114: p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */
1.3 glass 1115: #endif
1.97 nisimura 1116: return 0;
1.1 deraadt 1117: }
1118:
1.99 castor 1119:
1120: #ifndef DDB_TRACE
1121:
1.73 jonathan 1122: #if defined(DEBUG) || defined(DDB)
1.99 castor 1123: mips_reg_t kdbrpeek __P((vaddr_t));
1124: extern void stacktrace __P((void)); /*XXX*/
1125: extern void logstacktrace __P((void)); /*XXX*/
1126:
1127:
1.22 jonathan 1128: int
1.1 deraadt 1129: kdbpeek(addr)
1.98 nisimura 1130: vaddr_t addr;
1.1 deraadt 1131: {
1.99 castor 1132: int rc;
1.1 deraadt 1133: if (addr & 3) {
1.56 jonathan 1134: printf("kdbpeek: unaligned address %lx\n", addr);
1.99 castor 1135: /* We might have been called from DDB, so do not go there. */
1136: stacktrace();
1137: rc = -1 ;
1138: } else if (addr == NULL) {
1139: printf("kdbpeek: NULL\n");
1140: rc = 0xdeadfeed;
1141: } else {
1142: rc = *(int *)addr;
1143: }
1144: return rc;
1145: }
1146:
1147: mips_reg_t
1148: kdbrpeek(addr)
1149: vaddr_t addr;
1150: {
1151: mips_reg_t rc;
1152: if (addr & (sizeof(mips_reg_t) - 1)) {
1153: printf("kdbrpeek: unaligned address %lx\n", addr);
1154: /* We might have been called from DDB, so do not go there. */
1.69 jonathan 1155: stacktrace();
1.99 castor 1156: rc = -1 ;
1157: } else if (addr == NULL) {
1158: printf("kdbrpeek: NULL\n");
1159: rc = 0xdeadfeed;
1160: } else {
1161: rc = *(mips_reg_t *)addr;
1.1 deraadt 1162: }
1.99 castor 1163: return rc;
1.1 deraadt 1164: }
1165:
1.99 castor 1166: extern char start[], edata[], verylocore[];
1167: extern char mips1_KernGenException[];
1168: extern char mips1_UserGenException[];
1169: extern char mips1_KernIntr[];
1170: extern char mips1_UserIntr[];
1171: extern char mips1_SystemCall[];
1172: extern char mips3_KernGenException[];
1173: extern char mips3_UserGenException[];
1174: extern char mips3_KernIntr[];
1175: extern char mips3_UserIntr[];
1176: extern char mips3_SystemCall[];
1177: extern int main __P((void*));
1178: extern void idle __P((void));
1179: extern void cpu_switch __P((struct proc *));
1180:
1181: /*
1182: * stack trace code, also useful to DDB one day
1183: */
1.1 deraadt 1184:
1.16 jonathan 1185: /* forward */
1186: char *fn_name(unsigned addr);
1.69 jonathan 1187: void stacktrace_subr __P((int a0, int a1, int a2, int a3,
1188: u_int pc, u_int sp, u_int fp, u_int ra,
1189: void (*)(const char*, ...)));
1.16 jonathan 1190:
1.99 castor 1191: #define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
1192: #define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */
1193: #define MIPS_ERET 0x12345678 /* instruction code for eret */
1194:
1.1 deraadt 1195: /*
1.56 jonathan 1196: * Do a stack backtrace.
1197: * (*printfn)() prints the output to either the system log,
1198: * the console, or both.
1.1 deraadt 1199: */
1.16 jonathan 1200: void
1.69 jonathan 1201: stacktrace_subr(a0, a1, a2, a3, pc, sp, fp, ra, printfn)
1.16 jonathan 1202: int a0, a1, a2, a3;
1.69 jonathan 1203: u_int pc, sp, fp, ra;
1.16 jonathan 1204: void (*printfn) __P((const char*, ...));
1205: {
1.69 jonathan 1206: unsigned va, subr;
1.1 deraadt 1207: unsigned instr, mask;
1208: InstFmt i;
1209: int more, stksize;
1.16 jonathan 1210: unsigned int frames = 0;
1.71 jonathan 1211: int foundframesize = 0;
1.1 deraadt 1212:
1.16 jonathan 1213: /* Jump here when done with a frame, to start a new one */
1.1 deraadt 1214: loop:
1.99 castor 1215: /* Jump here after a nonstandard (interrupt handler) frame
1216: specialframe: */
1.16 jonathan 1217: stksize = 0;
1218: subr = 0;
1.99 castor 1219: if (frames++ > 100) {
1.16 jonathan 1220: (*printfn)("\nstackframe count exceeded\n");
1.17 jonathan 1221: /* return breaks stackframe-size heuristics with gcc -O2 */
1222: goto finish; /*XXX*/
1.16 jonathan 1223: }
1224:
1225: /* check for bad SP: could foul up next frame */
1226: if (sp & 3 || sp < 0x80000000) {
1227: (*printfn)("SP 0x%x: not in kernel\n", sp);
1228: ra = 0;
1229: subr = 0;
1230: goto done;
1231: }
1232:
1.99 castor 1233: #if 0 /* special locore arrangements made unnecssary following */
1234:
1.35 jonathan 1235: /*
1236: * check for PC between two entry points
1237: */
1238: # define Between(x, y, z) \
1239: ( ((x) <= (y)) && ((y) < (z)) )
1240: # define pcBetween(a,b) \
1241: Between((unsigned)a, pc, (unsigned)b)
1242:
1.43 jonathan 1243: /* Backtraces should continue through interrupts from kernel mode */
1.42 jonathan 1244: #ifdef MIPS1 /* r2000 family (mips-I cpu) */
1.92 jonathan 1245: if (pcBetween(mips1_KernIntr, mips1_KernIntrEnd)) {
1.1 deraadt 1246: /* NOTE: the offsets depend on the code in locore.s */
1.99 castor 1247: (*printfn)("mips1 KernIntr+%x: (%x, %x ,%x) -------\n",
1.50 jonathan 1248: pc-(unsigned)mips1_KernIntr, a0, a1, a2);
1.57 mhitch 1249: a0 = kdbpeek(sp + 40);
1250: a1 = kdbpeek(sp + 44);
1251: a2 = kdbpeek(sp + 48);
1252: a3 = kdbpeek(sp + 52);
1.99 castor 1253: pc = kdbpeek(sp + 112); /* exc_pc - pc at time of exception */
1254: ra = kdbpeek(sp + 96); /* ra at time of exception */
1255: sp = sp + 116;
1.16 jonathan 1256: goto specialframe;
1.1 deraadt 1257: }
1.92 jonathan 1258: else if (pcBetween(mips1_KernGenException, mips1_KernGenExceptionEnd)) {
1.71 jonathan 1259: /* NOTE: the offsets depend on the code in locore.s */
1260: (*printfn)("------ kernel trap+%x: (%x, %x ,%x) -------\n",
1261: pc-(unsigned)mips1_KernGenException, a0, a1, a2);
1262:
1263: a0 = kdbpeek(sp + 40);
1264: a1 = kdbpeek(sp + 44);
1265: a2 = kdbpeek(sp + 48);
1266: a3 = kdbpeek(sp + 52);
1.99 castor 1267: pc = kdbpeek(sp + 112); /* exc_pc - pc at time of exception */
1268: ra = kdbpeek(sp + 96); /* ra at time of exception */
1269: sp = sp + 116;
1.71 jonathan 1270: goto specialframe;
1271: }
1.42 jonathan 1272: #endif /* MIPS1 */
1.35 jonathan 1273:
1.42 jonathan 1274: #ifdef MIPS3 /* r4000 family (mips-III cpu) */
1.92 jonathan 1275: if (pcBetween(mips3_KernIntr, mips3_KernIntrEnd)) {
1.35 jonathan 1276: /* NOTE: the offsets depend on the code in locore.s */
1.71 jonathan 1277: (*printfn)("------ mips3 KernIntr+%x: (%x, %x ,%x) -------\n",
1.50 jonathan 1278: pc-(unsigned)mips3_KernIntr, a0, a1, a2);
1.99 castor 1279: a0 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 3);
1280: a1 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 4);
1281: a2 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 5);
1282: a3 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 6);
1283: pc = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 21);
1284: ra = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 17);
1285: sp = sp + 4 * 5 + 4 + 4 + 22 * sizeof(mips_reg_t);
1.35 jonathan 1286: goto specialframe;
1287: }
1.92 jonathan 1288: else if (pcBetween(mips3_KernGenException, mips3_KernGenExceptionEnd)) {
1.71 jonathan 1289: /* NOTE: the offsets depend on the code in locore.s */
1290: (*printfn)("------ kernel trap+%x: (%x, %x ,%x) -------\n",
1291: pc-(unsigned)mips3_KernGenException, a0, a1, a2);
1292:
1.99 castor 1293: a0 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 3);
1294: a1 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 4);
1295: a2 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 5);
1296: a3 = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 6);
1297: pc = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 21);
1298: ra = kdbrpeek(sp + 28 + sizeof(mips_reg_t) * 17);
1299: sp = sp + 4 * 5 + 4 + 4 + 22 * sizeof(mips_reg_t);
1.71 jonathan 1300: goto specialframe;
1301: }
1.42 jonathan 1302: #endif /* MIPS3 */
1.1 deraadt 1303:
1.99 castor 1304: #endif
1.47 jonathan 1305:
1306: /* Check for bad PC */
1.1 deraadt 1307: if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
1.37 jonathan 1308: (*printfn)("PC 0x%x: not in kernel space\n", pc);
1309: ra = 0;
1310: goto done;
1311: }
1.1 deraadt 1312:
1313: /*
1314: * Find the beginning of the current subroutine by scanning backwards
1315: * from the current PC for the end of the previous subroutine.
1316: */
1.99 castor 1317: va = pc;
1318: do {
1.1 deraadt 1319: va -= sizeof(int);
1.99 castor 1320: if (va <= (unsigned)verylocore)
1321: goto finish;
1322: instr = kdbpeek(va);
1323: if (instr == MIPS_ERET)
1324: goto mips3_eret;
1325: } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
1326: /* skip back over branch & delay slot */
1327: va += sizeof(int);
1328: mips3_eret:
1329: va += sizeof(int);
1330: /* skip over nulls which might separate .o files */
1331: while ((instr = kdbpeek(va)) == 0)
1332: va += sizeof(int);
1333: subr = va;
1.1 deraadt 1334:
1335: /* scan forwards to find stack size and any saved registers */
1336: stksize = 0;
1337: more = 3;
1338: mask = 0;
1.71 jonathan 1339: foundframesize = 0;
1.16 jonathan 1340: for (va = subr; more; va += sizeof(int),
1.97 nisimura 1341: more = (more == 3) ? 3 : more - 1) {
1.1 deraadt 1342: /* stop if hit our current position */
1343: if (va >= pc)
1344: break;
1345: instr = kdbpeek(va);
1346: i.word = instr;
1347: switch (i.JType.op) {
1348: case OP_SPECIAL:
1349: switch (i.RType.func) {
1350: case OP_JR:
1351: case OP_JALR:
1352: more = 2; /* stop after next instruction */
1353: break;
1354:
1355: case OP_SYSCALL:
1356: case OP_BREAK:
1357: more = 1; /* stop now */
1358: };
1359: break;
1360:
1361: case OP_BCOND:
1362: case OP_J:
1363: case OP_JAL:
1364: case OP_BEQ:
1365: case OP_BNE:
1366: case OP_BLEZ:
1367: case OP_BGTZ:
1368: more = 2; /* stop after next instruction */
1369: break;
1370:
1371: case OP_COP0:
1372: case OP_COP1:
1373: case OP_COP2:
1374: case OP_COP3:
1375: switch (i.RType.rs) {
1376: case OP_BCx:
1377: case OP_BCy:
1378: more = 2; /* stop after next instruction */
1379: };
1380: break;
1381:
1382: case OP_SW:
1383: /* look for saved registers on the stack */
1384: if (i.IType.rs != 29)
1385: break;
1386: /* only restore the first one */
1387: if (mask & (1 << i.IType.rt))
1388: break;
1.16 jonathan 1389: mask |= (1 << i.IType.rt);
1.1 deraadt 1390: switch (i.IType.rt) {
1391: case 4: /* a0 */
1392: a0 = kdbpeek(sp + (short)i.IType.imm);
1393: break;
1394:
1395: case 5: /* a1 */
1396: a1 = kdbpeek(sp + (short)i.IType.imm);
1397: break;
1398:
1399: case 6: /* a2 */
1400: a2 = kdbpeek(sp + (short)i.IType.imm);
1401: break;
1402:
1403: case 7: /* a3 */
1404: a3 = kdbpeek(sp + (short)i.IType.imm);
1405: break;
1406:
1407: case 30: /* fp */
1408: fp = kdbpeek(sp + (short)i.IType.imm);
1409: break;
1410:
1411: case 31: /* ra */
1412: ra = kdbpeek(sp + (short)i.IType.imm);
1413: }
1414: break;
1415:
1416: case OP_ADDI:
1417: case OP_ADDIU:
1418: /* look for stack pointer adjustment */
1419: if (i.IType.rs != 29 || i.IType.rt != 29)
1420: break;
1.71 jonathan 1421: /* don't count pops for mcount */
1422: if (!foundframesize) {
1423: stksize = - ((short)i.IType.imm);
1424: foundframesize = 1;
1425: }
1.1 deraadt 1426: }
1427: }
1428: done:
1.16 jonathan 1429: (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
1430: fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
1.1 deraadt 1431:
1432: if (ra) {
1433: if (pc == ra && stksize == 0)
1.16 jonathan 1434: (*printfn)("stacktrace: loop!\n");
1.1 deraadt 1435: else {
1436: pc = ra;
1.16 jonathan 1437: sp += stksize;
1438: ra = 0;
1.1 deraadt 1439: goto loop;
1440: }
1.16 jonathan 1441: } else {
1.17 jonathan 1442: finish:
1.16 jonathan 1443: if (curproc)
1444: (*printfn)("User-level: pid %d\n", curproc->p_pid);
1445: else
1446: (*printfn)("User-level: curproc NULL\n");
1.1 deraadt 1447: }
1448: }
1.16 jonathan 1449:
1450: /*
1451: * Functions ``special'' enough to print by name
1452: */
1453: #ifdef __STDC__
1454: #define Name(_fn) { (void*)_fn, # _fn }
1455: #else
1456: #define Name(_fn) { _fn, "_fn"}
1457: #endif
1458: static struct { void *addr; char *name;} names[] = {
1.23 jonathan 1459: Name(stacktrace),
1460: Name(stacktrace_subr),
1461: Name(main),
1.16 jonathan 1462: Name(interrupt),
1463: Name(trap),
1.42 jonathan 1464:
1465: #ifdef MIPS1 /* r2000 family (mips-I cpu) */
1.50 jonathan 1466: Name(mips1_KernGenException),
1467: Name(mips1_UserGenException),
1.57 mhitch 1468: Name(mips1_SystemCall),
1.50 jonathan 1469: Name(mips1_KernIntr),
1470: Name(mips1_UserIntr),
1.42 jonathan 1471: #endif /* MIPS1 */
1.35 jonathan 1472:
1.42 jonathan 1473: #ifdef MIPS3 /* r4000 family (mips-III cpu) */
1.50 jonathan 1474: Name(mips3_KernGenException),
1475: Name(mips3_UserGenException),
1.57 mhitch 1476: Name(mips3_SystemCall),
1.50 jonathan 1477: Name(mips3_KernIntr),
1478: Name(mips3_UserIntr),
1.42 jonathan 1479: #endif /* MIPS3 */
1.35 jonathan 1480:
1.16 jonathan 1481: Name(idle),
1482: Name(cpu_switch),
1483: {0, 0}
1484: };
1485:
1486: /*
1487: * Map a function address to a string name, if known; or a hex string.
1488: */
1489: char *
1490: fn_name(unsigned addr)
1491: {
1492: static char buf[17];
1493: int i = 0;
1.77 mhitch 1494: #ifdef DDB
1495: db_expr_t diff;
1496: db_sym_t sym;
1497: char *symname;
1498: #endif
1.16 jonathan 1499:
1.77 mhitch 1500: #ifdef DDB
1501: diff = 0;
1502: symname = NULL;
1503: sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
1504: db_symbol_values(sym, &symname, 0);
1505: if (symname && diff == 0)
1506: return (symname);
1507: #endif
1.16 jonathan 1508: for (i = 0; names[i].name; i++)
1509: if (names[i].addr == (void*)addr)
1510: return (names[i].name);
1.45 christos 1511: sprintf(buf, "%x", addr);
1.16 jonathan 1512: return (buf);
1513: }
1514:
1.1 deraadt 1515: #endif /* DEBUG */
1.57 mhitch 1516:
1.99 castor 1517: #endif /* DDB_TRACE */
CVSweb <webmaster@jp.NetBSD.org>