Annotation of src/sys/arch/mips/mips/trap.c, Revision 1.256
1.256 ! mrg 1: /* $NetBSD: trap.c,v 1.255 2020/07/13 09:00:40 simonb Exp $ */
1.8 cgd 2:
1.1 deraadt 3: /*
1.226 rmind 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.
1.181 agc 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: */
1.125 nisimura 40:
1.226 rmind 41: #include <sys/cdefs.h>
1.256 ! mrg 42: __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.255 2020/07/13 09:00:40 simonb Exp $");
1.82 thorpej 43:
1.85 jonathan 44: #include "opt_cputype.h" /* which mips CPU levels do we support? */
45: #include "opt_ddb.h"
1.162 lukem 46: #include "opt_kgdb.h"
1.227 matt 47: #include "opt_multiprocessor.h"
1.78 jonathan 48:
1.1 deraadt 49: #include <sys/param.h>
50: #include <sys/systm.h>
1.125 nisimura 51: #include <sys/kernel.h>
1.231 matt 52: #include <sys/cpu.h>
1.1 deraadt 53: #include <sys/proc.h>
1.171 gmcgarry 54: #include <sys/ras.h>
1.1 deraadt 55: #include <sys/signalvar.h>
56: #include <sys/syscall.h>
57: #include <sys/buf.h>
58: #include <sys/ktrace.h>
1.203 yamt 59: #include <sys/kauth.h>
1.227 matt 60: #include <sys/atomic.h>
1.46 jonathan 61:
1.165 thorpej 62: #include <mips/cache.h>
1.58 jonathan 63: #include <mips/locore.h>
64: #include <mips/mips_opcode.h>
1.78 jonathan 65:
1.223 uebayasi 66: #include <uvm/uvm.h>
1.82 thorpej 67:
1.70 jonathan 68: #include <mips/trap.h>
69: #include <mips/reg.h>
70: #include <mips/regnum.h> /* symbolic register indices */
1.225 tsutsui 71: #include <mips/pcb.h>
1.70 jonathan 72: #include <mips/pte.h>
1.129 nisimura 73: #include <mips/psl.h>
1.154 thorpej 74: #include <mips/userret.h>
1.1 deraadt 75:
1.125 nisimura 76: #ifdef DDB
77: #include <machine/db_machdep.h>
78: #include <ddb/db_sym.h>
79: #endif
1.23 jonathan 80:
1.144 jeffs 81: #ifdef KGDB
82: #include <sys/kgdb.h>
83: #endif
84:
1.227 matt 85: const char * const trap_names[] = {
1.1 deraadt 86: "external interrupt",
87: "TLB modification",
88: "TLB miss (load or instr. fetch)",
89: "TLB miss (store)",
90: "address error (load or I-fetch)",
91: "address error (store)",
92: "bus error (I-fetch)",
93: "bus error (load or store)",
94: "system call",
95: "breakpoint",
96: "reserved instruction",
97: "coprocessor unusable",
98: "arithmetic overflow",
1.32 jonathan 99: "r4k trap/r3k reserved 13",
100: "r4k virtual coherency instruction/r3k reserved 14",
101: "r4k floating point/ r3k reserved 15",
1.237 matt 102: "mips NMI",
1.32 jonathan 103: "reserved 17",
1.168 simonb 104: "mipsNN cp2 exception",
1.237 matt 105: "mipsNN TLBRI",
106: "mipsNN TLBXI",
1.32 jonathan 107: "reserved 21",
1.168 simonb 108: "mips64 MDMX",
109: "r4k watch",
110: "mipsNN machine check",
1.237 matt 111: "mipsNN thread",
1.232 matt 112: "DSP exception",
1.32 jonathan 113: "reserved 27",
114: "reserved 28",
115: "reserved 29",
1.168 simonb 116: "mipsNN cache error",
1.46 jonathan 117: "r4000 virtual coherency data",
1.99 castor 118: };
119:
1.227 matt 120: void trap(uint32_t, uint32_t, vaddr_t, vaddr_t, struct trapframe *);
121: void ast(void);
1.57 mhitch 122:
123: /*
1.211 tsutsui 124: * fork syscall returns directly to user process via lwp_trampoline(),
1.57 mhitch 125: * which will be called the very first time when child gets running.
126: */
127: void
1.249 kamil 128: md_child_return(struct lwp *l)
1.57 mhitch 129: {
1.227 matt 130: struct trapframe *utf = l->l_md.md_utf;
1.57 mhitch 131:
1.227 matt 132: utf->tf_regs[_R_V0] = 0;
133: utf->tf_regs[_R_V1] = 1;
134: utf->tf_regs[_R_A3] = 0;
1.176 thorpej 135: userret(l);
1.57 mhitch 136: }
137:
1.168 simonb 138: #ifdef MIPS3_PLUS
1.65 jonathan 139: #define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 140: #else
1.65 jonathan 141: #define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
1.57 mhitch 142: #endif
1.240 matt 143: #define KERNLAND_P(x) ((intptr_t)(x) < 0)
1.57 mhitch 144:
145: /*
146: * Trap is called from locore to handle most types of processor traps.
147: * System calls are broken out for efficiency. MIPS can handle software
148: * interrupts as a part of real interrupt processing.
149: */
150: void
1.227 matt 151: trap(uint32_t status, uint32_t cause, vaddr_t vaddr, vaddr_t pc,
152: struct trapframe *tf)
1.57 mhitch 153: {
1.227 matt 154: int type;
155: struct lwp * const l = curlwp;
156: struct proc * const p = curproc;
157: struct trapframe * const utf = l->l_md.md_utf;
158: struct pcb * const pcb = lwp_getpcb(l);
1.1 deraadt 159: vm_prot_t ftype;
1.184 christos 160: ksiginfo_t ksi;
1.168 simonb 161: extern void fswintrberr(void);
1.227 matt 162: void *onfault;
163: int rv;
164:
1.184 christos 165: KSI_INIT_TRAP(&ksi);
1.1 deraadt 166:
1.228 matt 167: curcpu()->ci_data.cpu_ntrap++;
1.239 tnn 168: if (CPUISMIPS3 && (status & MIPS3_SR_NMI)) {
1.237 matt 169: type = T_NMI;
170: } else {
171: type = TRAPTYPE(cause);
172: }
1.204 ad 173: if (USERMODE(status)) {
1.227 matt 174: tf = utf;
1.1 deraadt 175: type |= T_USER;
1.204 ad 176: LWP_CACHE_CREDS(l, p);
177: }
1.1 deraadt 178:
179: switch (type) {
1.57 mhitch 180: default:
181: dopanic:
1.150 jeffs 182: (void)splhigh();
1.227 matt 183:
184: /*
185: * use snprintf to allow a single, idempotent, readable printf
186: */
187: char strbuf[256], *str = strbuf;
188: int n, sz = sizeof(strbuf);
189:
190: n = snprintf(str, sz, "pid %d(%s): ", p->p_pid, p->p_comm);
1.241 skrll 191: sz -= n;
1.227 matt 192: str += n;
193: n = snprintf(str, sz, "trap: cpu%d, %s in %s mode\n",
1.228 matt 194: cpu_number(), trap_names[TRAPTYPE(cause)],
1.97 nisimura 195: USERMODE(status) ? "user" : "kernel");
1.241 skrll 196: sz -= n;
1.227 matt 197: str += n;
1.237 matt 198: n = snprintf(str, sz, "status=%#x, cause=%#x, epc=%#"
1.227 matt 199: PRIxVADDR ", vaddr=%#" PRIxVADDR "\n",
200: status, cause, pc, vaddr);
1.241 skrll 201: sz -= n;
1.227 matt 202: str += n;
1.221 matt 203: if (USERMODE(status)) {
1.227 matt 204: KASSERT(tf == utf);
205: n = snprintf(str, sz, "frame=%p usp=%#" PRIxREGISTER
1.221 matt 206: " ra=%#" PRIxREGISTER "\n",
1.227 matt 207: tf, tf->tf_regs[_R_SP], tf->tf_regs[_R_RA]);
1.241 skrll 208: sz -= n;
1.227 matt 209: str += n;
1.221 matt 210: } else {
1.227 matt 211: n = snprintf(str, sz, "tf=%p ksp=%p ra=%#"
1.237 matt 212: PRIxREGISTER " ppl=%#x\n", tf,
213: type == T_NMI
214: ? (void*)(uintptr_t)tf->tf_regs[_R_SP]
215: : tf+1,
216: tf->tf_regs[_R_RA], tf->tf_ppl);
1.241 skrll 217: sz -= n;
1.227 matt 218: str += n;
1.221 matt 219: }
1.227 matt 220: printf("%s", strbuf);
221:
1.237 matt 222: if (type == T_BUS_ERR_IFETCH || type == T_BUS_ERR_LD_ST)
1.227 matt 223: (void)(*mips_locoresw.lsw_bus_error)(cause);
224:
1.144 jeffs 225: #if defined(DDB)
1.227 matt 226: kdb_trap(type, &tf->tf_registers);
1.99 castor 227: /* XXX force halt XXX */
1.144 jeffs 228: #elif defined(KGDB)
229: {
230: extern mips_reg_t kgdb_cause, kgdb_vaddr;
1.227 matt 231: struct reg *regs = &ddb_regs;
1.144 jeffs 232: kgdb_cause = cause;
233: kgdb_vaddr = vaddr;
234:
235: /*
236: * init global ddb_regs, used in db_interface.c routines
237: * shared between ddb and gdb. Send ddb_regs to gdb so
238: * that db_machdep.h macros will work with it, and
239: * allow gdb to alter the PC.
240: */
1.227 matt 241: db_set_ddb_regs(type, tf);
242: PC_BREAK_ADVANCE(regs);
243: if (kgdb_trap(type, regs)) {
244: tf->tf_regs[TF_EPC] = regs->r_regs[_R_PC];
1.144 jeffs 245: return;
246: }
247: }
1.99 castor 248: #else
1.57 mhitch 249: panic("trap");
1.99 castor 250: #endif
1.57 mhitch 251: /*NOTREACHED*/
1.1 deraadt 252: case T_TLB_MOD:
1.240 matt 253: case T_TLB_MOD+T_USER: {
254: const bool user_p = (type & T_USER) || !KERNLAND_P(vaddr);
255: pmap_t pmap = user_p
256: ? p->p_vmspace->vm_map.pmap
257: : pmap_kernel();
1.1 deraadt 258:
1.240 matt 259: kpreempt_disable();
1.227 matt 260:
1.240 matt 261: pt_entry_t * const ptep = pmap_pte_lookup(pmap, vaddr);
1.241 skrll 262: if (!ptep)
1.240 matt 263: panic("%ctlbmod: %#"PRIxVADDR": no pte",
264: user_p ? 'u' : 'k', vaddr);
265: pt_entry_t pte = *ptep;
266: if (!pte_valid_p(pte)) {
267: panic("%ctlbmod: %#"PRIxVADDR": invalid pte %#"PRIx32
268: " @ ptep %p", user_p ? 'u' : 'k', vaddr,
269: pte_value(pte), ptep);
1.1 deraadt 270: }
1.240 matt 271: if (pte_readonly_p(pte)) {
1.3 glass 272: /* write to read only page */
1.1 deraadt 273: ftype = VM_PROT_WRITE;
1.227 matt 274: kpreempt_enable();
1.240 matt 275: if (user_p) {
276: goto pagefault;
277: } else {
278: goto kernelfault;
279: }
1.1 deraadt 280: }
1.240 matt 281: UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist);
1.252 skrll 282: UVMHIST_LOG(maphist, "%ctlbmod(va=%#lx, pc=%#lx, tf=%#jx)",
283: user_p ? 'u' : 'k', vaddr, pc, (uintptr_t)tf);
1.240 matt 284: if (!pte_modified_p(pte)) {
285: pte |= mips_pg_m_bit();
1.227 matt 286: #ifdef MULTIPROCESSOR
1.240 matt 287: atomic_or_32(ptep, mips_pg_m_bit());
1.227 matt 288: #else
1.240 matt 289: *ptep = pte;
1.227 matt 290: #endif
291: }
1.240 matt 292: // We got a TLB MOD exception so we must have a valid ASID
293: // and there must be a matching entry in the TLB. So when
294: // we try to update it, we better have done it.
295: KASSERTMSG(pte_valid_p(pte), "%#"PRIx32, pte_value(pte));
296: vaddr = trunc_page(vaddr);
297: int ok = pmap_tlb_update_addr(pmap, vaddr, pte, 0);
1.227 matt 298: kpreempt_enable();
1.251 thorpej 299: if (ok != 1) {
300: #if 0 /* PMAP_FAULTINFO? */
301: /*
302: * Since we don't block interrupts here,
303: * this can legitimately happen if we get
304: * a TLB miss that's serviced in an interrupt
305: * hander that happens to randomly evict the
306: * TLB entry we're concerned about.
307: */
1.240 matt 308: printf("pmap_tlb_update_addr(%p,%#"
1.250 thorpej 309: PRIxVADDR",%#"PRIxPTE", 0) returned %d\n",
1.240 matt 310: pmap, vaddr, pte_value(pte), ok);
1.251 thorpej 311: #endif
312: }
1.240 matt 313: paddr_t pa = pte_to_paddr(pte);
314: KASSERTMSG(uvm_pageismanaged(pa),
315: "%#"PRIxVADDR" pa %#"PRIxPADDR, vaddr, pa);
1.96 mhitch 316: pmap_set_modified(pa);
1.57 mhitch 317: if (type & T_USER)
1.176 thorpej 318: userret(l);
1.240 matt 319: UVMHIST_LOG(maphist, " <-- done", 0, 0, 0, 0);
1.57 mhitch 320: return; /* GEN */
1.230 matt 321: }
1.1 deraadt 322: case T_TLB_LD_MISS:
323: case T_TLB_ST_MISS:
1.57 mhitch 324: ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
1.240 matt 325: if (KERNLAND_P(vaddr))
1.57 mhitch 326: goto kernelfault;
1.1 deraadt 327: /*
328: * It is an error for the kernel to access user space except
329: * through the copyin/copyout routines.
330: */
1.220 rmind 331: if (pcb->pcb_onfault == NULL) {
332: goto dopanic;
333: }
1.57 mhitch 334: goto pagefault;
1.1 deraadt 335: case T_TLB_LD_MISS+T_USER:
336: ftype = VM_PROT_READ;
1.57 mhitch 337: goto pagefault;
1.1 deraadt 338: case T_TLB_ST_MISS+T_USER:
339: ftype = VM_PROT_WRITE;
1.230 matt 340: pagefault: {
1.227 matt 341: const vaddr_t va = trunc_page(vaddr);
342: struct vmspace * const vm = p->p_vmspace;
343: struct vm_map * const map = &vm->vm_map;
344: #ifdef PMAP_FAULTINFO
345: struct pcb_faultinfo * const pfi = &pcb->pcb_faultinfo;
346: #endif
1.1 deraadt 347:
1.227 matt 348: kpreempt_disable();
349: #ifdef _LP64
350: /*
351: * If the pmap has been activated and we allocated the segtab
352: * for the low 4GB, seg0tab may still be NULL. We can't
353: * really fix this in pmap_enter (we can only update the local
354: * cpu's cpu_info but not other cpu's) so we need to detect
355: * and fix this here.
356: */
1.228 matt 357: struct cpu_info * const ci = curcpu();
1.227 matt 358: if ((va >> XSEGSHIFT) == 0 &&
1.238 matt 359: __predict_false(ci->ci_pmap_user_seg0tab == NULL
360: && ci->ci_pmap_user_segtab->seg_seg[0] != NULL)) {
361: ci->ci_pmap_user_seg0tab =
362: ci->ci_pmap_user_segtab->seg_seg[0];
1.227 matt 363: kpreempt_enable();
364: if (type & T_USER) {
365: userret(l);
366: }
367: return; /* GEN */
368: }
369: #endif
1.240 matt 370: KASSERT(KERNLAND_P(va) || curcpu()->ci_pmap_asid_cur != 0);
1.227 matt 371: pmap_tlb_asid_check();
372: kpreempt_enable();
373:
374: #ifdef PMAP_FAULTINFO
375: if (p->p_pid == pfi->pfi_lastpid && va == pfi->pfi_faultaddr) {
1.240 matt 376: if (++pfi->pfi_repeats > 4) {
377: tlb_asid_t asid = tlb_get_asid();
378: pt_entry_t *ptep = pfi->pfi_faultpte;
1.253 skrll 379: printf("trap: fault #%u (%s/%s) for %#"
380: PRIxVADDR" (%#"PRIxVADDR") at pc %#"
381: PRIxVADDR" curpid=%u/%u ptep@%p=%#"
382: PRIxPTE")\n", pfi->pfi_repeats,
383: trap_names[TRAPTYPE(cause)],
384: trap_names[pfi->pfi_faulttype], va,
385: vaddr, pc, map->pmap->pm_pai[0].pai_asid,
386: asid, ptep, ptep ? pte_value(*ptep) : 0);
1.227 matt 387: if (pfi->pfi_repeats >= 4) {
388: cpu_Debugger();
389: } else {
1.240 matt 390: pfi->pfi_faulttype = TRAPTYPE(cause);
1.227 matt 391: }
392: }
393: } else {
394: pfi->pfi_lastpid = p->p_pid;
395: pfi->pfi_faultaddr = va;
396: pfi->pfi_repeats = 0;
397: pfi->pfi_faultpte = NULL;
398: pfi->pfi_faulttype = TRAPTYPE(cause);
399: }
400: #endif /* PMAP_FAULTINFO */
1.172 manu 401:
1.227 matt 402: onfault = pcb->pcb_onfault;
1.222 chs 403: pcb->pcb_onfault = NULL;
1.245 maya 404: rv = uvm_fault(map, va, ftype);
1.222 chs 405: pcb->pcb_onfault = onfault;
406:
1.240 matt 407: #if defined(VMFAULT_TRACE)
408: if (!KERNLAND_P(va))
409: printf(
410: "uvm_fault(%p (pmap %p), %#"PRIxVADDR
411: " (%"PRIxVADDR"), %d) -> %d at pc %#"PRIxVADDR"\n",
412: map, vm->vm_map.pmap, va, vaddr, ftype, rv, pc);
1.82 thorpej 413: #endif
1.1 deraadt 414: /*
415: * If this was a stack access we keep track of the maximum
416: * accessed stack size. Also, if vm_fault gets a protection
417: * failure it is due to accessing the stack region outside
418: * the current limit and we need to reflect that as an access
419: * error.
420: */
1.209 christos 421: if ((void *)va >= vm->vm_maxsaddr) {
1.194 jdolecek 422: if (rv == 0)
423: uvm_grow(p, va);
1.161 chs 424: else if (rv == EACCES)
425: rv = EFAULT;
1.1 deraadt 426: }
1.161 chs 427: if (rv == 0) {
1.227 matt 428: #ifdef PMAP_FAULTINFO
429: if (pfi->pfi_repeats == 0) {
430: pfi->pfi_faultpte =
431: pmap_pte_lookup(map->pmap, va);
432: }
1.240 matt 433: KASSERT(*(pt_entry_t *)pfi->pfi_faultpte);
1.227 matt 434: #endif
1.99 castor 435: if (type & T_USER) {
1.176 thorpej 436: userret(l);
1.99 castor 437: }
1.57 mhitch 438: return; /* GEN */
439: }
1.108 simonb 440: if ((type & T_USER) == 0)
1.57 mhitch 441: goto copyfault;
1.242 skrll 442:
443: KSI_INIT_TRAP(&ksi);
444: switch (rv) {
445: case EINVAL:
446: ksi.ksi_signo = SIGBUS;
447: ksi.ksi_code = BUS_ADRERR;
448: break;
449: case EACCES:
450: ksi.ksi_signo = SIGSEGV;
451: ksi.ksi_code = SEGV_ACCERR;
452: break;
453: case ENOMEM:
1.184 christos 454: ksi.ksi_signo = SIGKILL;
1.242 skrll 455: printf("UVM: pid %d.%d (%s), uid %d killed: "
456: "out of swap\n", p->p_pid, l->l_lid, p->p_comm,
457: l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1);
458: break;
459: default:
460: ksi.ksi_signo = SIGSEGV;
461: ksi.ksi_code = SEGV_MAPERR;
462: break;
1.105 chs 463: }
1.184 christos 464: ksi.ksi_trap = type & ~T_USER;
465: ksi.ksi_addr = (void *)vaddr;
1.108 simonb 466: break; /* SIGNAL */
1.230 matt 467: }
1.227 matt 468: kernelfault: {
1.222 chs 469: onfault = pcb->pcb_onfault;
1.57 mhitch 470:
1.222 chs 471: pcb->pcb_onfault = NULL;
1.227 matt 472: rv = uvm_fault(kernel_map, trunc_page(vaddr), ftype);
1.222 chs 473: pcb->pcb_onfault = onfault;
1.161 chs 474: if (rv == 0)
1.57 mhitch 475: return; /* KERN */
1.222 chs 476: goto copyfault;
1.227 matt 477: }
1.57 mhitch 478: case T_ADDR_ERR_LD: /* misaligned access */
479: case T_ADDR_ERR_ST: /* misaligned access */
1.191 wiz 480: case T_BUS_ERR_LD_ST: /* BERR asserted to CPU */
1.222 chs 481: onfault = pcb->pcb_onfault;
482: rv = EFAULT;
1.57 mhitch 483: copyfault:
1.222 chs 484: if (onfault == NULL) {
1.220 rmind 485: goto dopanic;
486: }
1.227 matt 487: tf->tf_regs[_R_PC] = (intptr_t)onfault;
488: tf->tf_regs[_R_V0] = rv;
1.57 mhitch 489: return; /* KERN */
1.1 deraadt 490:
491: case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
492: case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
1.191 wiz 493: case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to CPU */
494: case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to CPU */
1.184 christos 495: ksi.ksi_trap = type & ~T_USER;
496: ksi.ksi_addr = (void *)vaddr;
1.240 matt 497: if (KERNLAND_P(vaddr)) {
1.227 matt 498: ksi.ksi_signo = SIGSEGV;
499: ksi.ksi_code = SEGV_MAPERR;
500: } else {
501: ksi.ksi_signo = SIGBUS;
502: if (type == T_BUS_ERR_IFETCH+T_USER
503: || type == T_BUS_ERR_LD_ST+T_USER)
504: ksi.ksi_code = BUS_OBJERR;
505: else
506: ksi.ksi_code = BUS_ADRALN;
507: }
1.57 mhitch 508: break; /* SIGNAL */
1.69 jonathan 509:
1.227 matt 510: case T_WATCH:
1.69 jonathan 511: case T_BREAK:
1.144 jeffs 512: #if defined(DDB)
1.227 matt 513: kdb_trap(type, &tf->tf_registers);
1.69 jonathan 514: return; /* KERN */
1.144 jeffs 515: #elif defined(KGDB)
516: {
517: extern mips_reg_t kgdb_cause, kgdb_vaddr;
1.227 matt 518: struct reg *regs = &ddb_regs;
1.144 jeffs 519: kgdb_cause = cause;
520: kgdb_vaddr = vaddr;
521:
522: /*
523: * init global ddb_regs, used in db_interface.c routines
524: * shared between ddb and gdb. Send ddb_regs to gdb so
525: * that db_machdep.h macros will work with it, and
526: * allow gdb to alter the PC.
527: */
1.227 matt 528: db_set_ddb_regs(type, &tf->tf_registers);
529: PC_BREAK_ADVANCE(regs);
530: if (!kgdb_trap(type, regs))
1.144 jeffs 531: printf("kgdb: ignored %s\n",
1.227 matt 532: trap_names[TRAPTYPE(cause)]);
1.144 jeffs 533: else
1.227 matt 534: tf->tf_regs[_R_PC] = regs->r_regs[_R_PC];
1.144 jeffs 535:
536: return;
537: }
1.69 jonathan 538: #else
539: goto dopanic;
540: #endif
1.230 matt 541: case T_BREAK+T_USER: {
1.206 matt 542: uint32_t instr;
1.1 deraadt 543:
544: /* compute address of break instruction */
1.227 matt 545: vaddr_t va = pc + (cause & MIPS_CR_BR_DELAY ? sizeof(int) : 0);
1.1 deraadt 546:
547: /* read break instruction */
1.248 thorpej 548: instr = mips_ufetch32((void *)va);
1.57 mhitch 549:
1.176 thorpej 550: if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
1.184 christos 551: ksi.ksi_trap = type & ~T_USER;
552: ksi.ksi_signo = SIGTRAP;
553: ksi.ksi_addr = (void *)va;
554: ksi.ksi_code = TRAP_TRACE;
1.244 christos 555: /* we broke, skip it to avoid infinite loop */
556: if (instr == MIPS_BREAK_INSTR)
557: tf->tf_regs[_R_PC] += 4;
1.1 deraadt 558: break;
559: }
1.97 nisimura 560: /*
1.57 mhitch 561: * Restore original instruction and clear BP
1.97 nisimura 562: */
1.248 thorpej 563: rv = mips_ustore32_isync((void *)va, l->l_md.md_ss_instr);
564: if (rv != 0) {
1.98 nisimura 565: vaddr_t sa, ea;
566: sa = trunc_page(va);
567: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 568: rv = uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 569: sa, ea, VM_PROT_ALL, false);
1.161 chs 570: if (rv == 0) {
1.248 thorpej 571: rv = mips_ustore32_isync((void *)va,
572: l->l_md.md_ss_instr);
1.82 thorpej 573: (void)uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 574: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
1.82 thorpej 575: }
1.97 nisimura 576: }
1.165 thorpej 577: mips_icache_sync_all(); /* XXXJRT -- necessary? */
578: mips_dcache_wbinv_all(); /* XXXJRT -- necessary? */
1.69 jonathan 579:
1.248 thorpej 580: if (rv != 0)
1.221 matt 581: printf("Warning: can't restore instruction"
582: " at %#"PRIxVADDR": 0x%x\n",
583: l->l_md.md_ss_addr, l->l_md.md_ss_instr);
1.176 thorpej 584: l->l_md.md_ss_addr = 0;
1.184 christos 585: ksi.ksi_trap = type & ~T_USER;
586: ksi.ksi_signo = SIGTRAP;
587: ksi.ksi_addr = (void *)va;
588: ksi.ksi_code = TRAP_BRKPT;
1.57 mhitch 589: break; /* SIGNAL */
1.230 matt 590: }
1.232 matt 591: case T_DSP+T_USER:
592: #if (MIPS32R2 + MIPS64R2) > 0
593: if (MIPS_HAS_DSP) {
594: dsp_load();
595: userret(l);
596: return; /* GEN */
597: }
598: #endif /* (MIPS32R3 + MIPS64R2) > 0 */
599: /* FALLTHROUGH */
1.1 deraadt 600: case T_RES_INST+T_USER:
601: case T_COP_UNUSABLE+T_USER:
1.227 matt 602: #if !defined(FPEMUL) && !defined(NOFPU)
1.255 simonb 603: if (__SHIFTOUT(cause, MIPS_CR_COP_ERR) == MIPS_CR_COP_ERR_CU1) {
1.227 matt 604: fpu_load(); /* load FPA */
1.170 gmcgarry 605: } else
1.118 shin 606: #endif
1.133 nisimura 607: {
1.227 matt 608: mips_emul_inst(status, cause, pc, utf);
1.133 nisimura 609: }
1.176 thorpej 610: userret(l);
1.57 mhitch 611: return; /* GEN */
1.32 jonathan 612: case T_FPE+T_USER:
1.227 matt 613: #if defined(FPEMUL)
614: mips_emul_inst(status, cause, pc, utf);
1.170 gmcgarry 615: #elif !defined(NOFPU)
1.229 tsutsui 616: utf->tf_regs[_R_CAUSE] = cause;
1.227 matt 617: mips_fpu_trap(pc, utf);
1.118 shin 618: #endif
1.176 thorpej 619: userret(l);
1.108 simonb 620: return; /* GEN */
1.1 deraadt 621: case T_OVFLOW+T_USER:
1.146 jeffs 622: case T_TRAP+T_USER:
1.184 christos 623: ksi.ksi_trap = type & ~T_USER;
624: ksi.ksi_signo = SIGFPE;
1.227 matt 625: ksi.ksi_addr = (void *)(intptr_t)pc /*utf->tf_regs[_R_PC]*/;
1.184 christos 626: ksi.ksi_code = FPE_FLTOVF; /* XXX */
1.108 simonb 627: break; /* SIGNAL */
1.97 nisimura 628: }
1.227 matt 629: utf->tf_regs[_R_CAUSE] = cause;
630: utf->tf_regs[_R_BADVADDR] = vaddr;
1.221 matt 631: #if defined(DEBUG)
632: printf("trap: pid %d(%s): sig %d: cause=%#x epc=%#"PRIxREGISTER
633: " va=%#"PRIxVADDR"\n",
634: p->p_pid, p->p_comm, ksi.ksi_signo, cause,
1.227 matt 635: utf->tf_regs[_R_PC], vaddr);
1.221 matt 636: printf("registers:\n");
637: for (size_t i = 0; i < 32; i += 4) {
638: printf(
639: "[%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER
640: " [%2zu]=%08"PRIxREGISTER" [%2zu]=%08"PRIxREGISTER "\n",
1.227 matt 641: i+0, utf->tf_regs[i+0], i+1, utf->tf_regs[i+1],
642: i+2, utf->tf_regs[i+2], i+3, utf->tf_regs[i+3]);
1.221 matt 643: }
644: #endif
1.184 christos 645: (*p->p_emul->e_trapsignal)(l, &ksi);
1.221 matt 646: if ((type & T_USER) == 0) {
647: #ifdef DDB
648: Debugger();
649: #endif
1.57 mhitch 650: panic("trapsignal");
1.221 matt 651: }
1.176 thorpej 652: userret(l);
1.108 simonb 653: return;
1.57 mhitch 654: }
1.1 deraadt 655:
1.127 soda 656: /*
1.57 mhitch 657: * Handle asynchronous software traps.
658: * This is called from MachUserIntr() either to deliver signals or
659: * to make involuntary context switch (preemption).
1.1 deraadt 660: */
1.22 jonathan 661: void
1.227 matt 662: ast(void)
1.1 deraadt 663: {
1.227 matt 664: struct lwp * const l = curlwp;
665: u_int astpending;
1.1 deraadt 666:
1.227 matt 667: while ((astpending = l->l_md.md_astpending) != 0) {
1.224 matt 668: //curcpu()->ci_data.cpu_nast++;
1.207 ad 669: l->l_md.md_astpending = 0;
1.153 thorpej 670:
1.227 matt 671: #ifdef MULTIPROCESSOR
1.228 matt 672: {
673: kpreempt_disable();
674: struct cpu_info * const ci = l->l_cpu;
675: if (ci->ci_tlb_info->ti_synci_page_bitmap != 0)
676: pmap_tlb_syncicache_ast(ci);
677: kpreempt_enable();
678: }
1.227 matt 679: #endif
680:
1.207 ad 681: if (l->l_pflag & LP_OWEUPC) {
682: l->l_pflag &= ~LP_OWEUPC;
683: ADDUPROF(l);
1.155 thorpej 684: }
685:
1.207 ad 686: userret(l);
1.155 thorpej 687:
1.228 matt 688: if (l->l_cpu->ci_want_resched) {
1.155 thorpej 689: /*
690: * We are being preempted.
691: */
1.207 ad 692: preempt();
1.155 thorpej 693: }
1.153 thorpej 694: }
1.57 mhitch 695: }
1.1 deraadt 696:
697:
1.254 simonb 698: /* XXX need to rewrite ancient comment XXX
1.1 deraadt 699: * This routine is called by procxmt() to single step one instruction.
700: * We do this by storing a break instruction after the current instruction,
701: * resuming execution, and then restoring the old instruction.
702: */
1.22 jonathan 703: int
1.190 simonb 704: mips_singlestep(struct lwp *l)
1.1 deraadt 705: {
1.227 matt 706: struct trapframe * const tf = l->l_md.md_utf;
707: struct proc * const p = l->l_proc;
1.98 nisimura 708: vaddr_t pc, va;
1.108 simonb 709: int rv;
1.1 deraadt 710:
1.176 thorpej 711: if (l->l_md.md_ss_addr) {
1.221 matt 712: printf("SS %s (%d): breakpoint already set at %#"PRIxVADDR"\n",
1.176 thorpej 713: p->p_comm, p->p_pid, l->l_md.md_ss_addr);
1.97 nisimura 714: return EFAULT;
1.1 deraadt 715: }
1.227 matt 716: pc = (vaddr_t)tf->tf_regs[_R_PC];
1.248 thorpej 717: if (mips_ufetch32((void *)pc) != 0) { /* not a NOP instruction */
1.227 matt 718: struct pcb * const pcb = lwp_getpcb(l);
719: va = mips_emul_branch(tf, pc, PCB_FSR(pcb), true);
720: } else {
1.99 castor 721: va = pc + sizeof(int);
1.227 matt 722: }
1.171 gmcgarry 723:
724: /*
725: * We can't single-step into a RAS. Check if we're in
726: * a RAS, and set the breakpoint just past it.
727: */
1.215 ad 728: if (p->p_raslist != NULL) {
1.209 christos 729: while (ras_lookup(p, (void *)va) != (void *)-1)
1.171 gmcgarry 730: va += sizeof(int);
731: }
732:
1.176 thorpej 733: l->l_md.md_ss_addr = va;
1.248 thorpej 734: l->l_md.md_ss_instr = mips_ufetch32((void *)va);
735: rv = mips_ustore32_isync((void *)va, MIPS_BREAK_SSTEP);
736: if (rv != 0) {
1.98 nisimura 737: vaddr_t sa, ea;
738: sa = trunc_page(va);
739: ea = round_page(va + sizeof(int) - 1);
1.82 thorpej 740: rv = uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 741: sa, ea, VM_PROT_ALL, false);
1.161 chs 742: if (rv == 0) {
1.248 thorpej 743: rv = mips_ustore32_isync((void *)va,
744: MIPS_BREAK_SSTEP);
1.82 thorpej 745: (void)uvm_map_protect(&p->p_vmspace->vm_map,
1.208 thorpej 746: sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
1.82 thorpej 747: }
1.1 deraadt 748: }
1.3 glass 749: #if 0
1.45 christos 750: printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
1.1 deraadt 751: p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1.248 thorpej 752: p->p_md.md_ss_instr, pc, mips_ufetch32((void *)va)); /* XXX */
1.3 glass 753: #endif
1.97 nisimura 754: return 0;
1.1 deraadt 755: }
CVSweb <webmaster@jp.NetBSD.org>