1/*	$NetBSD: trap.c,v 1.265 2023/10/24 18:08:16 andvar Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1992, 1993
6 *	The Regents of the University of California.  All rights reserved.
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. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah Hdr: trap.c 1.32 91/04/06
37 *
38 *	@(#)trap.c	8.5 (Berkeley) 1/11/94
39 */
40
41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.265 2023/10/24 18:08:16 andvar Exp $");
43
44#include "opt_cputype.h"	/* which mips CPU levels do we support? */
45#include "opt_ddb.h"
46#include "opt_dtrace.h"
47#include "opt_kgdb.h"
48#include "opt_multiprocessor.h"
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/kernel.h>
53#include <sys/cpu.h>
54#include <sys/proc.h>
55#include <sys/ras.h>
56#include <sys/signalvar.h>
57#include <sys/syscall.h>
58#include <sys/buf.h>
59#include <sys/ktrace.h>
60#include <sys/kauth.h>
61#include <sys/atomic.h>
62
63#include <mips/cache.h>
64#include <mips/locore.h>
65#include <mips/mips_opcode.h>
66
67#include <uvm/uvm.h>
68
69#include <mips/trap.h>
70#include <mips/reg.h>
71#include <mips/regnum.h>			/* symbolic register indices */
72#include <mips/pcb.h>
73#include <mips/pte.h>
74#include <mips/psl.h>
75#include <mips/userret.h>
76
77#ifdef DDB
78#include <machine/db_machdep.h>
79#include <ddb/db_sym.h>
80#endif
81
82#ifdef KGDB
83#include <sys/kgdb.h>
84#endif
85
86#ifdef KDTRACE_HOOKS
87#include <sys/dtrace_bsd.h>
88
89/* Not used for now, but needed for dtrace/fbt modules */
90dtrace_doubletrap_func_t	dtrace_doubletrap_func = NULL;
91dtrace_trap_func_t		dtrace_trap_func = NULL;
92
93int				(* dtrace_invop_jump_addr)(struct trapframe *);
94#endif /* KDTRACE_HOOKS */
95
96const char * const trap_names[] = {
97	"external interrupt",
98	"TLB modification",
99	"TLB miss (load or instr. fetch)",
100	"TLB miss (store)",
101	"address error (load or I-fetch)",
102	"address error (store)",
103	"bus error (I-fetch)",
104	"bus error (load or store)",
105	"system call",
106	"breakpoint",
107	"reserved instruction",
108	"coprocessor unusable",
109	"arithmetic overflow",
110	"r4k trap/r3k reserved 13",
111	"r4k virtual coherency instruction/r3k reserved 14",
112	"r4k floating point/ r3k reserved 15",
113	"mips NMI",
114	"reserved 17",
115	"mipsNN cp2 exception",
116	"mipsNN TLBRI",
117	"mipsNN TLBXI",
118	"reserved 21",
119	"mips64 MDMX",
120	"r4k watch",
121	"mipsNN machine check",
122	"mipsNN thread",
123	"DSP exception",
124	"reserved 27",
125	"reserved 28",
126	"reserved 29",
127	"mipsNN cache error",
128	"r4000 virtual coherency data",
129};
130
131void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *);
132void ast(void);
133
134#ifdef TRAP_SIGDEBUG
135static void sigdebug(const struct trapframe *, const ksiginfo_t *, int,
136    vaddr_t);
137#define SIGDEBUG(a, b, c, d) sigdebug(a, b, c, d)
138#else
139#define SIGDEBUG(a, b, c, d)
140#endif
141
142/*
143 * fork syscall returns directly to user process via lwp_trampoline(),
144 * which will be called the very first time when child gets running.
145 */
146void
147md_child_return(struct lwp *l)
148{
149	struct trapframe *utf = l->l_md.md_utf;
150
151	utf->tf_regs[_R_V0] = 0;
152	utf->tf_regs[_R_V1] = 1;
153	utf->tf_regs[_R_A3] = 0;
154	userret(l);
155}
156
157#ifdef MIPS3_PLUS
158#define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
159#else
160#define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
161#endif
162#define KERNLAND_P(x) ((intptr_t)(x) < 0)
163
164/*
165 * Trap is called from locore to handle most types of processor traps.
166 * System calls are broken out for efficiency.  MIPS can handle software
167 * interrupts as a part of real interrupt processing.
168 */
169void
170trap(uint32_t status, uint32_t cause, vaddr_t vaddr, vaddr_t pc,
171    struct trapframe *tf)
172{
173	struct lwp * const l = curlwp;
174	struct proc * const p = curproc;
175	struct trapframe * const utf = l->l_md.md_utf;
176	struct pcb * const pcb = lwp_getpcb(l);
177	vm_prot_t ftype;
178	ksiginfo_t ksi;
179	extern void fswintrberr(void);
180	void *onfault;
181	InstFmt insn;
182	uint32_t instr;
183	int type;
184	int rv = 0;
185
186	KSI_INIT_TRAP(&ksi);
187
188	curcpu()->ci_data.cpu_ntrap++;
189	if (CPUISMIPS3 && (status & MIPS3_SR_NMI)) {
190		type = T_NMI;
191	} else {
192		type = TRAPTYPE(cause);
193	}
194	if (USERMODE(status)) {
195		tf = utf;
196		type |= T_USER;
197	}
198
199#ifdef KDTRACE_HOOKS
200	/*
201	 * A trap can occur while DTrace executes a probe. Before
202	 * executing the probe, DTrace blocks re-scheduling and sets
203	 * a flag in its per-cpu flags to indicate that it doesn't
204	 * want to fault. On returning from the probe, the no-fault
205	 * flag is cleared and finally re-scheduling is enabled.
206	 *
207	 * If the DTrace kernel module has registered a trap handler,
208	 * call it and if it returns non-zero, assume that it has
209	 * handled the trap and modified the trap frame so that this
210	 * function can return normally.
211	 */
212	/*
213	 * XXXDTRACE: add pid probe handler here (if ever)
214	 */
215	if (!USERMODE(status)) {
216		if ((dtrace_trap_func != NULL) &&
217		    ((*dtrace_trap_func)(tf, type) != 0)) {
218			return;
219		}
220	}
221#endif /* KDTRACE_HOOKS */
222
223	switch (type) {
224	default:
225	dopanic:
226		(void)splhigh();
227
228		/*
229		 * use snprintf to allow a single, idempotent, readable printf
230		 */
231		char strbuf[256], *str = strbuf;
232		int n, sz = sizeof(strbuf);
233
234		n = snprintf(str, sz, "pid %d(%s): ", p->p_pid, p->p_comm);
235		sz -= n;
236		str += n;
237		n = snprintf(str, sz, "trap: cpu%d, %s in %s mode\n",
238			cpu_number(), trap_names[TRAPTYPE(cause)],
239			USERMODE(status) ? "user" : "kernel");
240		sz -= n;
241		str += n;
242		n = snprintf(str, sz, "status=%#x, cause=%#x, epc=%#"
243			PRIxVADDR ", vaddr=%#" PRIxVADDR "\n",
244			status, cause, pc, vaddr);
245		sz -= n;
246		str += n;
247		if (USERMODE(status)) {
248			KASSERT(tf == utf);
249			n = snprintf(str, sz, "frame=%p usp=%#" PRIxREGISTER
250			    " ra=%#" PRIxREGISTER "\n",
251			    tf, tf->tf_regs[_R_SP], tf->tf_regs[_R_RA]);
252			sz -= n;
253			str += n;
254		} else {
255			n = snprintf(str, sz, "tf=%p ksp=%p ra=%#"
256			    PRIxREGISTER " ppl=%#x\n", tf,
257			    type == T_NMI
258				? (void*)(uintptr_t)tf->tf_regs[_R_SP]
259				: tf+1,
260			    tf->tf_regs[_R_RA], tf->tf_ppl);
261			sz -= n;
262			str += n;
263		}
264		printf("%s", strbuf);
265
266		if (type == T_BUS_ERR_IFETCH || type == T_BUS_ERR_LD_ST)
267			(void)(*mips_locoresw.lsw_bus_error)(cause);
268
269#if defined(DDB)
270		kdb_trap(type, &tf->tf_registers);
271		/* XXX force halt XXX */
272#elif defined(KGDB)
273		{
274			extern mips_reg_t kgdb_cause, kgdb_vaddr;
275			struct reg *regs = &ddb_regs;
276			kgdb_cause = cause;
277			kgdb_vaddr = vaddr;
278
279			/*
280			 * init global ddb_regs, used in db_interface.c routines
281			 * shared between ddb and gdb. Send ddb_regs to gdb so
282			 * that db_machdep.h macros will work with it, and
283			 * allow gdb to alter the PC.
284			 */
285			db_set_ddb_regs(type, &tf->tf_registers);
286			PC_BREAK_ADVANCE(regs);
287			if (kgdb_trap(type, regs)) {
288				tf->tf_regs[_R_PC] = regs->r_regs[_R_PC];
289				return;
290			}
291		}
292#else
293		panic("trap");
294#endif
295		/*NOTREACHED*/
296	case T_TLB_MOD:
297	case T_TLB_MOD+T_USER: {
298		const bool user_p = (type & T_USER) || !KERNLAND_P(vaddr);
299		pmap_t pmap = user_p
300		    ? p->p_vmspace->vm_map.pmap
301		    : pmap_kernel();
302
303		kpreempt_disable();
304
305		pt_entry_t * const ptep = pmap_pte_lookup(pmap, vaddr);
306		if (!ptep)
307			panic("%ctlbmod: %#"PRIxVADDR": no pte",
308			    user_p ? 'u' : 'k', vaddr);
309		pt_entry_t pte = *ptep;
310		if (!pte_valid_p(pte)) {
311			panic("%ctlbmod: %#"PRIxVADDR": invalid pte %#"PRIx32
312			    " @ ptep %p", user_p ? 'u' : 'k', vaddr,
313			    pte_value(pte), ptep);
314		}
315		if (pte_readonly_p(pte)) {
316			/* write to read only page */
317			ftype = VM_PROT_WRITE;
318			kpreempt_enable();
319			if (user_p) {
320				goto pagefault;
321			} else {
322				goto kernelfault;
323			}
324		}
325		UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist);
326		UVMHIST_LOG(maphist, "%ctlbmod(va=%#lx, pc=%#lx, tf=%#jx)",
327		    user_p ? 'u' : 'k', vaddr, pc, (uintptr_t)tf);
328		if (!pte_modified_p(pte)) {
329			pte |= mips_pg_m_bit();
330#ifdef MULTIPROCESSOR
331			atomic_or_32(ptep, mips_pg_m_bit());
332#else
333			*ptep = pte;
334#endif
335		}
336		// We got a TLB MOD exception so we must have a valid ASID
337		// and there must be a matching entry in the TLB.  So when
338		// we try to update it, we better have done it.
339		KASSERTMSG(pte_valid_p(pte), "%#"PRIx32, pte_value(pte));
340		vaddr = trunc_page(vaddr);
341		int ok = pmap_tlb_update_addr(pmap, vaddr, pte, 0);
342		kpreempt_enable();
343		if (ok != 1) {
344#if 0 /* PMAP_FAULTINFO? */
345			/*
346			 * Since we don't block interrupts here,
347			 * this can legitimately happen if we get
348			 * a TLB miss that's serviced in an interrupt
349			 * handler that happens to randomly evict the
350			 * TLB entry we're concerned about.
351			 */
352			printf("pmap_tlb_update_addr(%p,%#"
353			    PRIxVADDR",%#"PRIxPTE", 0) returned %d\n",
354			    pmap, vaddr, pte_value(pte), ok);
355#endif
356		}
357		paddr_t pa = pte_to_paddr(pte);
358		KASSERTMSG(uvm_pageismanaged(pa),
359		    "%#"PRIxVADDR" pa %#"PRIxPADDR, vaddr, pa);
360		pmap_set_modified(pa);
361		if (type & T_USER)
362			userret(l);
363		UVMHIST_LOG(maphist, " <-- done", 0, 0, 0, 0);
364		return; /* GEN */
365	}
366	case T_TLB_LD_MISS:
367	case T_TLB_ST_MISS:
368		ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
369		if (KERNLAND_P(vaddr))
370			goto kernelfault;
371		/*
372		 * It is an error for the kernel to access user space except
373		 * through the copyin/copyout routines.
374		 */
375		if (pcb->pcb_onfault == NULL) {
376			goto dopanic;
377		}
378		goto pagefault;
379	case T_TLB_LD_MISS+T_USER:
380		ftype = VM_PROT_READ;
381		goto pagefault;
382	case T_TLB_ST_MISS+T_USER:
383		ftype = VM_PROT_WRITE;
384	pagefault: {
385		const vaddr_t va = trunc_page(vaddr);
386		struct vmspace * const vm = p->p_vmspace;
387		struct vm_map * const map = &vm->vm_map;
388#ifdef PMAP_FAULTINFO
389		struct pcb_faultinfo * const pfi = &pcb->pcb_faultinfo;
390#endif
391
392		kpreempt_disable();
393#ifdef _LP64
394		/*
395		 * If the pmap has been activated and we allocated the segtab
396		 * for the low 4GB, seg0tab may still be NULL.  We can't
397		 * really fix this in pmap_enter (we can only update the local
398		 * cpu's cpu_info but not other cpu's) so we need to detect
399		 * and fix this here.
400		 */
401		struct cpu_info * const ci = curcpu();
402		if ((va >> XSEGSHIFT) == 0 &&
403		    __predict_false(ci->ci_pmap_user_seg0tab == NULL
404				&& ci->ci_pmap_user_segtab->seg_seg[0] != NULL)) {
405			ci->ci_pmap_user_seg0tab =
406			    ci->ci_pmap_user_segtab->seg_seg[0];
407			kpreempt_enable();
408			if (type & T_USER) {
409				userret(l);
410			}
411			return; /* GEN */
412		}
413#endif
414		KASSERT(KERNLAND_P(va) || curcpu()->ci_pmap_asid_cur != 0);
415		pmap_tlb_asid_check();
416		kpreempt_enable();
417
418#ifdef PMAP_FAULTINFO
419		if (p->p_pid == pfi->pfi_lastpid && va == pfi->pfi_faultaddr) {
420			if (++pfi->pfi_repeats > 4) {
421				tlb_asid_t asid = tlb_get_asid();
422				pt_entry_t *ptep = pfi->pfi_faultptep;
423				printf("trap: fault #%u (%s/%s) for %#"
424				    PRIxVADDR" (%#"PRIxVADDR") at pc %#"
425				    PRIxVADDR" curpid=%u/%u ptep@%p=%#"
426				    PRIxPTE")\n", pfi->pfi_repeats,
427				    trap_names[TRAPTYPE(cause)],
428				    trap_names[pfi->pfi_faulttype], va,
429				    vaddr, pc, map->pmap->pm_pai[0].pai_asid,
430				    asid, ptep, ptep ? pte_value(*ptep) : 0);
431				if (pfi->pfi_repeats >= 4) {
432					cpu_Debugger();
433				} else {
434					pfi->pfi_faulttype = TRAPTYPE(cause);
435				}
436			}
437		} else {
438			pfi->pfi_lastpid = p->p_pid;
439			pfi->pfi_faultaddr = va;
440			pfi->pfi_repeats = 0;
441			pfi->pfi_faultptep = NULL;
442			pfi->pfi_faulttype = TRAPTYPE(cause);
443		}
444#endif /* PMAP_FAULTINFO */
445
446		onfault = pcb->pcb_onfault;
447		pcb->pcb_onfault = NULL;
448		rv = uvm_fault(map, va, ftype);
449		pcb->pcb_onfault = onfault;
450
451#if defined(VMFAULT_TRACE)
452		if (!KERNLAND_P(va))
453			printf(
454			    "uvm_fault(%p (pmap %p), %#"PRIxVADDR
455			    " (%"PRIxVADDR"), %d) -> %d at pc %#"PRIxVADDR"\n",
456			    map, vm->vm_map.pmap, va, vaddr, ftype, rv, pc);
457#endif
458		/*
459		 * If this was a stack access we keep track of the maximum
460		 * accessed stack size.  Also, if vm_fault gets a protection
461		 * failure it is due to accessing the stack region outside
462		 * the current limit and we need to reflect that as an access
463		 * error.
464		 */
465		if ((void *)va >= vm->vm_maxsaddr) {
466			if (rv == 0)
467				uvm_grow(p, va);
468			else if (rv == EACCES)
469				rv = EFAULT;
470		}
471		if (rv == 0) {
472#ifdef PMAP_FAULTINFO
473			if (pfi->pfi_repeats == 0) {
474				pfi->pfi_faultptep =
475				    pmap_pte_lookup(map->pmap, va);
476			}
477			KASSERT(*(pt_entry_t *)pfi->pfi_faultptep);
478#endif
479			if (type & T_USER) {
480				userret(l);
481			}
482			return; /* GEN */
483		}
484		if ((type & T_USER) == 0)
485			goto copyfault;
486
487		KSI_INIT_TRAP(&ksi);
488		switch (rv) {
489		case EINVAL:
490			ksi.ksi_signo = SIGBUS;
491			ksi.ksi_code = BUS_ADRERR;
492			break;
493		case EACCES:
494			ksi.ksi_signo = SIGSEGV;
495			ksi.ksi_code = SEGV_ACCERR;
496			break;
497		case ENOMEM:
498			ksi.ksi_signo = SIGKILL;
499			printf("UVM: pid %d.%d (%s), uid %d killed: "
500			    "out of swap\n", p->p_pid, l->l_lid, p->p_comm,
501			    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1);
502			break;
503		default:
504			ksi.ksi_signo = SIGSEGV;
505			ksi.ksi_code = SEGV_MAPERR;
506			break;
507		}
508		ksi.ksi_trap = type & ~T_USER;
509		ksi.ksi_addr = (void *)vaddr;
510		break; /* SIGNAL */
511	}
512	kernelfault: {
513		onfault = pcb->pcb_onfault;
514
515		pcb->pcb_onfault = NULL;
516		rv = uvm_fault(kernel_map, trunc_page(vaddr), ftype);
517		pcb->pcb_onfault = onfault;
518		if (rv == 0)
519			return; /* KERN */
520		goto copyfault;
521	}
522	case T_ADDR_ERR_LD:	/* misaligned access */
523	case T_ADDR_ERR_ST:	/* misaligned access */
524	case T_BUS_ERR_LD_ST:	/* BERR asserted to CPU */
525		onfault = pcb->pcb_onfault;
526		rv = EFAULT;
527	copyfault:
528		if (onfault == NULL) {
529			goto dopanic;
530		}
531		tf->tf_regs[_R_PC] = (intptr_t)onfault;
532		tf->tf_regs[_R_V0] = rv;
533		return; /* KERN */
534
535	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
536	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
537	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to CPU */
538	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to CPU */
539		ksi.ksi_trap = type & ~T_USER;
540		ksi.ksi_addr = (void *)vaddr;
541		if (KERNLAND_P(vaddr)) {
542			ksi.ksi_signo = SIGSEGV;
543			ksi.ksi_code = SEGV_MAPERR;
544		} else {
545			ksi.ksi_signo = SIGBUS;
546			if (type == T_BUS_ERR_IFETCH+T_USER
547			    || type == T_BUS_ERR_LD_ST+T_USER)
548				ksi.ksi_code = BUS_OBJERR;
549			else
550				ksi.ksi_code = BUS_ADRALN;
551		}
552		break; /* SIGNAL */
553
554	case T_BREAK:
555#ifdef KDTRACE_HOOKS
556		if ((dtrace_invop_jump_addr != NULL) &&
557		    (dtrace_invop_jump_addr(tf) == 0)) {
558			return;
559		}
560#endif /* KDTRACE_HOOKS */
561		/* FALLTHROUGH */
562	case T_WATCH:
563#if defined(DDB)
564		kdb_trap(type, &tf->tf_registers);
565		return;	/* KERN */
566#elif defined(KGDB)
567		{
568			extern mips_reg_t kgdb_cause, kgdb_vaddr;
569			struct reg *regs = &ddb_regs;
570			kgdb_cause = cause;
571			kgdb_vaddr = vaddr;
572
573			/*
574			 * init global ddb_regs, used in db_interface.c routines
575			 * shared between ddb and gdb. Send ddb_regs to gdb so
576			 * that db_machdep.h macros will work with it, and
577			 * allow gdb to alter the PC.
578			 */
579			db_set_ddb_regs(type, &tf->tf_registers);
580			PC_BREAK_ADVANCE(regs);
581			if (!kgdb_trap(type, regs))
582				printf("kgdb: ignored %s\n",
583				       trap_names[TRAPTYPE(cause)]);
584			else
585				tf->tf_regs[_R_PC] = regs->r_regs[_R_PC];
586
587			return;
588		}
589#else
590		goto dopanic;
591#endif
592	case T_BREAK+T_USER: {
593		/* compute address of break instruction */
594		vaddr_t va = pc + (cause & MIPS_CR_BR_DELAY ? sizeof(int) : 0);
595
596		/* read break instruction */
597		instr = mips_ufetch32((void *)va);
598		insn.word = instr;
599
600		if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
601			bool advance_pc = false;
602
603			ksi.ksi_trap = type & ~T_USER;
604			ksi.ksi_signo = SIGTRAP;
605			ksi.ksi_addr = (void *)va;
606			ksi.ksi_code = TRAP_BRKPT;
607
608			if ((insn.JType.op == OP_SPECIAL) &&
609			    (insn.RType.func == OP_BREAK)) {
610				int code = (insn.RType.rs << 5) | insn.RType.rt;
611				switch (code) {
612				case 0:
613					/* we broke, skip it to avoid infinite loop */
614					advance_pc = true;
615					break;
616				case MIPS_BREAK_INTOVERFLOW:
617					ksi.ksi_signo = SIGFPE;
618					ksi.ksi_code = FPE_INTOVF;
619					advance_pc = true;
620					break;
621				case MIPS_BREAK_INTDIVZERO:
622					ksi.ksi_signo = SIGFPE;
623					ksi.ksi_code = FPE_INTDIV;
624					advance_pc = true;
625					break;
626				default:
627					/* do nothing */
628					break;
629				}
630			}
631
632			if (advance_pc)
633				tf->tf_regs[_R_PC] += 4;
634			break;
635		}
636		/*
637		 * Restore original instruction and clear BP
638		 */
639		rv = mips_ustore32_isync((void *)va, l->l_md.md_ss_instr);
640		if (rv != 0) {
641			vaddr_t sa, ea;
642			sa = trunc_page(va);
643			ea = round_page(va + sizeof(int) - 1);
644			rv = uvm_map_protect(&p->p_vmspace->vm_map,
645				sa, ea, VM_PROT_ALL, false);
646			if (rv == 0) {
647				rv = mips_ustore32_isync((void *)va,
648				    l->l_md.md_ss_instr);
649				(void)uvm_map_protect(&p->p_vmspace->vm_map,
650				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
651			}
652		}
653		mips_icache_sync_all();		/* XXXJRT -- necessary? */
654		mips_dcache_wbinv_all();	/* XXXJRT -- necessary? */
655
656		if (rv != 0)
657			printf("Warning: can't restore instruction"
658			    " at %#"PRIxVADDR": 0x%x\n",
659			    l->l_md.md_ss_addr, l->l_md.md_ss_instr);
660		l->l_md.md_ss_addr = 0;
661		ksi.ksi_trap = type & ~T_USER;
662		ksi.ksi_signo = SIGTRAP;
663		ksi.ksi_addr = (void *)va;
664		ksi.ksi_code = TRAP_TRACE;
665		break; /* SIGNAL */
666	}
667	case T_DSP+T_USER:
668#if (MIPS32R2 + MIPS64R2) > 0
669		if (MIPS_HAS_DSP) {
670			dsp_load();
671			userret(l);
672			return; /* GEN */
673		}
674#endif /* (MIPS32R3 + MIPS64R2) > 0 */
675		/* FALLTHROUGH */
676	case T_RES_INST+T_USER:
677	case T_COP_UNUSABLE+T_USER:
678#if !defined(FPEMUL) && !defined(NOFPU)
679		if (__SHIFTOUT(cause, MIPS_CR_COP_ERR) == MIPS_CR_COP_ERR_CU1) {
680			fpu_load();          	/* load FPA */
681		} else
682#endif
683		{
684			mips_emul_inst(status, cause, pc, utf);
685		}
686		userret(l);
687		return; /* GEN */
688	case T_FPE+T_USER:
689#if defined(FPEMUL)
690		mips_emul_inst(status, cause, pc, utf);
691#elif !defined(NOFPU)
692		utf->tf_regs[_R_CAUSE] = cause;
693		mips_fpu_trap(pc, utf);
694#endif
695		userret(l);
696		return; /* GEN */
697	case T_OVFLOW+T_USER:
698	case T_TRAP+T_USER: {
699		/* compute address of trap/faulting instruction */
700		vaddr_t va = pc + (cause & MIPS_CR_BR_DELAY ? sizeof(int) : 0);
701		bool advance_pc = false;
702
703		/* read break instruction */
704		instr = mips_ufetch32((void *)va);
705		insn.word = instr;
706
707		ksi.ksi_trap = type & ~T_USER;
708		ksi.ksi_signo = SIGFPE;
709		ksi.ksi_addr = (void *)(intptr_t)pc /*utf->tf_regs[_R_PC]*/;
710		ksi.ksi_code = FPE_FLTOVF; /* XXX */
711
712		if ((insn.JType.op == OP_SPECIAL) &&
713		    (insn.RType.func == OP_TEQ)) {
714			int code = (insn.RType.rd << 5) | insn.RType.shamt;
715			switch (code) {
716			case MIPS_BREAK_INTOVERFLOW:
717				ksi.ksi_code = FPE_INTOVF;
718				advance_pc = true;
719				break;
720			case MIPS_BREAK_INTDIVZERO:
721				ksi.ksi_code = FPE_INTDIV;
722				advance_pc = true;
723				break;
724			}
725		}
726
727		/* XXX when else do we advance the PC? */
728		if (advance_pc)
729			tf->tf_regs[_R_PC] += 4;
730		break; /* SIGNAL */
731	 }
732	}
733	utf->tf_regs[_R_CAUSE] = cause;
734	utf->tf_regs[_R_BADVADDR] = vaddr;
735	SIGDEBUG(utf, &ksi, rv, pc);
736	(*p->p_emul->e_trapsignal)(l, &ksi);
737	if ((type & T_USER) == 0) {
738#ifdef DDB
739		Debugger();
740#endif
741		panic("trapsignal");
742	}
743	userret(l);
744	return;
745}
746
747/*
748 * Handle asynchronous software traps.
749 * This is called from MachUserIntr() either to deliver signals or
750 * to make involuntary context switch (preemption).
751 */
752void
753ast(void)
754{
755	struct lwp * const l = curlwp;
756	u_int astpending;
757
758	while ((astpending = l->l_md.md_astpending) != 0) {
759		//curcpu()->ci_data.cpu_nast++;
760		l->l_md.md_astpending = 0;
761
762#ifdef MULTIPROCESSOR
763		{
764			kpreempt_disable();
765			struct cpu_info * const ci = l->l_cpu;
766			if (ci->ci_tlb_info->ti_synci_page_bitmap != 0)
767				pmap_tlb_syncicache_ast(ci);
768			kpreempt_enable();
769		}
770#endif
771
772		if (l->l_pflag & LP_OWEUPC) {
773			l->l_pflag &= ~LP_OWEUPC;
774			ADDUPROF(l);
775		}
776
777		userret(l);
778
779		if (l->l_cpu->ci_want_resched) {
780			/*
781			 * We are being preempted.
782			 */
783			preempt();
784		}
785	}
786}
787
788
789/* XXX need to rewrite ancient comment XXX
790 * This routine is called by procxmt() to single step one instruction.
791 * We do this by storing a break instruction after the current instruction,
792 * resuming execution, and then restoring the old instruction.
793 */
794int
795mips_singlestep(struct lwp *l)
796{
797	struct trapframe * const tf = l->l_md.md_utf;
798	struct proc * const p = l->l_proc;
799	vaddr_t pc, va;
800	int rv;
801
802	if (l->l_md.md_ss_addr) {
803		printf("SS %s (%d): breakpoint already set at %#"PRIxVADDR"\n",
804			p->p_comm, p->p_pid, l->l_md.md_ss_addr);
805		return EFAULT;
806	}
807	pc = (vaddr_t)tf->tf_regs[_R_PC];
808	if (mips_ufetch32((void *)pc) != 0) { /* not a NOP instruction */
809		struct pcb * const pcb = lwp_getpcb(l);
810		va = mips_emul_branch(tf, pc, PCB_FSR(pcb), true);
811	} else {
812		va = pc + sizeof(int);
813	}
814
815	/*
816	 * We can't single-step into a RAS.  Check if we're in
817	 * a RAS, and set the breakpoint just past it.
818	 */
819	if (p->p_raslist != NULL) {
820		while (ras_lookup(p, (void *)va) != (void *)-1)
821			va += sizeof(int);
822	}
823
824	l->l_md.md_ss_addr = va;
825	l->l_md.md_ss_instr = mips_ufetch32((void *)va);
826	rv = mips_ustore32_isync((void *)va, MIPS_BREAK_SSTEP);
827	if (rv != 0) {
828		vaddr_t sa, ea;
829		sa = trunc_page(va);
830		ea = round_page(va + sizeof(int) - 1);
831		rv = uvm_map_protect(&p->p_vmspace->vm_map,
832		    sa, ea, VM_PROT_ALL, false);
833		if (rv == 0) {
834			rv = mips_ustore32_isync((void *)va,
835			    MIPS_BREAK_SSTEP);
836			(void)uvm_map_protect(&p->p_vmspace->vm_map,
837			    sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
838		}
839	}
840#if 0
841	printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
842		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
843		p->p_md.md_ss_instr, pc, mips_ufetch32((void *)va)); /* XXX */
844#endif
845	return 0;
846}
847
848#ifdef TRAP_SIGDEBUG
849static void
850frame_dump(const struct trapframe *tf, struct pcb *pcb)
851{
852
853	printf("trapframe %p\n", tf);
854	printf("ast %#018lx   v0 %#018lx   v1 %#018lx\n",
855	    tf->tf_regs[_R_AST], tf->tf_regs[_R_V0], tf->tf_regs[_R_V1]);
856	printf(" a0 %#018lx   a1 %#018lx   a2 %#018lx\n",
857	    tf->tf_regs[_R_A0], tf->tf_regs[_R_A1], tf->tf_regs[_R_A2]);
858#if defined(__mips_n32) || defined(__mips_n64)
859	printf(" a3 %#018lx   a4  %#018lx  a5  %#018lx\n",
860	    tf->tf_regs[_R_A3], tf->tf_regs[_R_A4], tf->tf_regs[_R_A5]);
861	printf(" a6 %#018lx   a7  %#018lx  t0  %#018lx\n",
862	    tf->tf_regs[_R_A6], tf->tf_regs[_R_A7], tf->tf_regs[_R_T0]);
863	printf(" t1 %#018lx   t2  %#018lx  t3  %#018lx\n",
864	    tf->tf_regs[_R_T1], tf->tf_regs[_R_T2], tf->tf_regs[_R_T3]);
865#else
866	printf(" a3 %#018lx   t0  %#018lx  t1  %#018lx\n",
867	    tf->tf_regs[_R_A3], tf->tf_regs[_R_T0], tf->tf_regs[_R_T1]);
868	printf(" t2 %#018lx   t3  %#018lx  t4  %#018lx\n",
869	    tf->tf_regs[_R_T2], tf->tf_regs[_R_T3], tf->tf_regs[_R_T4]);
870	printf(" t5 %#018lx   t6  %#018lx  t7  %#018lx\n",
871	    tf->tf_regs[_R_T5], tf->tf_regs[_R_T6], tf->tf_regs[_R_T7]);
872#endif
873	printf(" s0 %#018lx   s1  %#018lx  s2  %#018lx\n",
874	    tf->tf_regs[_R_S0], tf->tf_regs[_R_S1], tf->tf_regs[_R_S2]);
875	printf(" s3 %#018lx   s4  %#018lx  s5  %#018lx\n",
876	    tf->tf_regs[_R_S3], tf->tf_regs[_R_S4], tf->tf_regs[_R_S5]);
877	printf(" s6 %#018lx   s7  %#018lx  t8  %#018lx\n",
878	    tf->tf_regs[_R_S6], tf->tf_regs[_R_S7], tf->tf_regs[_R_T8]);
879	printf(" t9 %#018lx   k0  %#018lx  k1  %#018lx\n",
880	    tf->tf_regs[_R_T9], tf->tf_regs[_R_K0], tf->tf_regs[_R_K1]);
881	printf(" gp %#018lx   sp  %#018lx  s8  %#018lx\n",
882	    tf->tf_regs[_R_GP], tf->tf_regs[_R_SP], tf->tf_regs[_R_S8]);
883	printf(" ra %#018lx   sr  %#018lx  pc  %#018lx\n",
884	    tf->tf_regs[_R_RA], tf->tf_regs[_R_SR], tf->tf_regs[_R_PC]);
885	printf(" mullo     %#018lx mulhi %#018lx\n",
886	    tf->tf_regs[_R_MULLO], tf->tf_regs[_R_MULHI]);
887	printf(" badvaddr  %#018lx cause %#018lx\n",
888	    tf->tf_regs[_R_BADVADDR], tf->tf_regs[_R_CAUSE]);
889	printf("\n");
890	hexdump(printf, "Stack dump", tf, 256);
891}
892
893static void
894sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi, int e,
895    vaddr_t pc)
896{
897	struct lwp *l = curlwp;
898	struct proc *p = l->l_proc;
899
900	printf("pid %d.%d (%s): signal %d code=%d (trap %#lx) "
901	    "@pc %#lx addr %#lx error=%d\n",
902	    p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_code,
903	    tf->tf_regs[_R_CAUSE], (unsigned long)pc, tf->tf_regs[_R_BADVADDR],
904	    e);
905	frame_dump(tf, lwp_getpcb(l));
906}
907#endif /* TRAP_SIGDEBUG */
908