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 */
90 dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL;
91 dtrace_trap_func_t dtrace_trap_func = NULL;
92
93 int (* dtrace_invop_jump_addr)(struct trapframe *);
94 #endif /* KDTRACE_HOOKS */
95
96 const 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
131 void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *);
132 void ast(void);
133
134 #ifdef TRAP_SIGDEBUG
135 static 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 */
146 void
md_child_return(struct lwp * l)147 md_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 */
169 void
trap(uint32_t status,uint32_t cause,vaddr_t vaddr,vaddr_t pc,struct trapframe * tf)170 trap(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 */
752 void
ast(void)753 ast(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 */
794 int
mips_singlestep(struct lwp * l)795 mips_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
849 static void
frame_dump(const struct trapframe * tf,struct pcb * pcb)850 frame_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
893 static void
sigdebug(const struct trapframe * tf,const ksiginfo_t * ksi,int e,vaddr_t pc)894 sigdebug(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