xref: /netbsd/sys/arch/mips/mips/trap.c (revision 6550d01e)
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