Thu Aug 6 23:07:55 2009 UTC ()
print ra on trap.


(matt)
diff -r1.217 -r1.218 src/sys/arch/mips/mips/trap.c

cvs diff -r1.217 -r1.218 src/sys/arch/mips/mips/trap.c (switch to unified diff)

--- src/sys/arch/mips/mips/trap.c 2008/10/15 06:51:18 1.217
+++ src/sys/arch/mips/mips/trap.c 2009/08/06 23:07:55 1.218
@@ -1,1016 +1,1016 @@ @@ -1,1016 +1,1016 @@
1/* $NetBSD: trap.c,v 1.217 2008/10/15 06:51:18 wrstuden Exp $ */ 1/* $NetBSD: trap.c,v 1.218 2009/08/06 23:07:55 matt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer 8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department and Ralph Campbell. 9 * Science Department and Ralph Campbell.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors 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 20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 33 * SUCH DAMAGE.
34 * 34 *
35 * from: Utah Hdr: trap.c 1.32 91/04/06 35 * from: Utah Hdr: trap.c 1.32 91/04/06
36 * 36 *
37 * @(#)trap.c 8.5 (Berkeley) 1/11/94 37 * @(#)trap.c 8.5 (Berkeley) 1/11/94
38 */ 38 */
39/* 39/*
40 * Copyright (c) 1988 University of Utah. 40 * Copyright (c) 1988 University of Utah.
41 * 41 *
42 * This code is derived from software contributed to Berkeley by 42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer 43 * the Systems Programming Group of the University of Utah Computer
44 * Science Department and Ralph Campbell. 44 * Science Department and Ralph Campbell.
45 * 45 *
46 * Redistribution and use in source and binary forms, with or without 46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions 47 * modification, are permitted provided that the following conditions
48 * are met: 48 * are met:
49 * 1. Redistributions of source code must retain the above copyright 49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer. 50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright 51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the 52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution. 53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software 54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement: 55 * must display the following acknowledgement:
56 * This product includes software developed by the University of 56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors. 57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of 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 59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission. 60 * without specific prior written permission.
61 * 61 *
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * SUCH DAMAGE. 72 * SUCH DAMAGE.
73 * 73 *
74 * from: Utah Hdr: trap.c 1.32 91/04/06 74 * from: Utah Hdr: trap.c 1.32 91/04/06
75 * 75 *
76 * @(#)trap.c 8.5 (Berkeley) 1/11/94 76 * @(#)trap.c 8.5 (Berkeley) 1/11/94
77 */ 77 */
78 78
79#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 79#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
80 80
81__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.217 2008/10/15 06:51:18 wrstuden Exp $"); 81__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.218 2009/08/06 23:07:55 matt Exp $");
82 82
83#include "opt_cputype.h" /* which mips CPU levels do we support? */ 83#include "opt_cputype.h" /* which mips CPU levels do we support? */
84#include "opt_ddb.h" 84#include "opt_ddb.h"
85#include "opt_kgdb.h" 85#include "opt_kgdb.h"
86 86
87#include <sys/param.h> 87#include <sys/param.h>
88#include <sys/systm.h> 88#include <sys/systm.h>
89#include <sys/kernel.h> 89#include <sys/kernel.h>
90#include <sys/proc.h> 90#include <sys/proc.h>
91#include <sys/ras.h> 91#include <sys/ras.h>
92#include <sys/signalvar.h> 92#include <sys/signalvar.h>
93#include <sys/syscall.h> 93#include <sys/syscall.h>
94#include <sys/user.h> 94#include <sys/user.h>
95#include <sys/buf.h> 95#include <sys/buf.h>
96#include <sys/ktrace.h> 96#include <sys/ktrace.h>
97#include <sys/sa.h> 97#include <sys/sa.h>
98#include <sys/savar.h> 98#include <sys/savar.h>
99#include <sys/kauth.h> 99#include <sys/kauth.h>
100#include <sys/cpu.h> 100#include <sys/cpu.h>
101 101
102#include <mips/cache.h> 102#include <mips/cache.h>
103#include <mips/locore.h> 103#include <mips/locore.h>
104#include <mips/mips_opcode.h> 104#include <mips/mips_opcode.h>
105 105
106#include <uvm/uvm_extern.h> 106#include <uvm/uvm_extern.h>
107 107
108#include <machine/cpu.h> 108#include <machine/cpu.h>
109#include <mips/trap.h> 109#include <mips/trap.h>
110#include <mips/reg.h> 110#include <mips/reg.h>
111#include <mips/regnum.h> /* symbolic register indices */ 111#include <mips/regnum.h> /* symbolic register indices */
112#include <mips/pte.h> 112#include <mips/pte.h>
113#include <mips/psl.h> 113#include <mips/psl.h>
114#include <mips/userret.h> 114#include <mips/userret.h>
115 115
116#ifdef DDB 116#ifdef DDB
117#include <machine/db_machdep.h> 117#include <machine/db_machdep.h>
118#include <ddb/db_sym.h> 118#include <ddb/db_sym.h>
119#endif 119#endif
120 120
121#ifdef KGDB 121#ifdef KGDB
122#include <sys/kgdb.h> 122#include <sys/kgdb.h>
123#endif 123#endif
124 124
125const char *trap_type[] = { 125const char *trap_type[] = {
126 "external interrupt", 126 "external interrupt",
127 "TLB modification", 127 "TLB modification",
128 "TLB miss (load or instr. fetch)", 128 "TLB miss (load or instr. fetch)",
129 "TLB miss (store)", 129 "TLB miss (store)",
130 "address error (load or I-fetch)", 130 "address error (load or I-fetch)",
131 "address error (store)", 131 "address error (store)",
132 "bus error (I-fetch)", 132 "bus error (I-fetch)",
133 "bus error (load or store)", 133 "bus error (load or store)",
134 "system call", 134 "system call",
135 "breakpoint", 135 "breakpoint",
136 "reserved instruction", 136 "reserved instruction",
137 "coprocessor unusable", 137 "coprocessor unusable",
138 "arithmetic overflow", 138 "arithmetic overflow",
139 "r4k trap/r3k reserved 13", 139 "r4k trap/r3k reserved 13",
140 "r4k virtual coherency instruction/r3k reserved 14", 140 "r4k virtual coherency instruction/r3k reserved 14",
141 "r4k floating point/ r3k reserved 15", 141 "r4k floating point/ r3k reserved 15",
142 "reserved 16", 142 "reserved 16",
143 "reserved 17", 143 "reserved 17",
144 "mipsNN cp2 exception", 144 "mipsNN cp2 exception",
145 "reserved 19", 145 "reserved 19",
146 "reserved 20", 146 "reserved 20",
147 "reserved 21", 147 "reserved 21",
148 "mips64 MDMX", 148 "mips64 MDMX",
149 "r4k watch", 149 "r4k watch",
150 "mipsNN machine check", 150 "mipsNN machine check",
151 "reserved 25", 151 "reserved 25",
152 "reserved 26", 152 "reserved 26",
153 "reserved 27", 153 "reserved 27",
154 "reserved 28", 154 "reserved 28",
155 "reserved 29", 155 "reserved 29",
156 "mipsNN cache error", 156 "mipsNN cache error",
157 "r4000 virtual coherency data", 157 "r4000 virtual coherency data",
158}; 158};
159 159
160void trap(unsigned int, unsigned int, vaddr_t, vaddr_t, struct trapframe *); 160void trap(unsigned int, unsigned int, vaddr_t, vaddr_t, struct trapframe *);
161void ast(unsigned int); 161void ast(unsigned int);
162 162
163vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned int, int); /* XXX */ 163vaddr_t MachEmulateBranch(struct frame *, vaddr_t, unsigned int, int); /* XXX */
164void MachEmulateInst(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */ 164void MachEmulateInst(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */
165void MachFPTrap(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */ 165void MachFPTrap(u_int32_t, u_int32_t, vaddr_t, struct frame *); /* XXX */
166 166
167#define DELAYBRANCH(x) ((int)(x)<0) 167#define DELAYBRANCH(x) ((int)(x)<0)
168 168
169/* 169/*
170 * fork syscall returns directly to user process via lwp_trampoline(), 170 * fork syscall returns directly to user process via lwp_trampoline(),
171 * which will be called the very first time when child gets running. 171 * which will be called the very first time when child gets running.
172 */ 172 */
173void 173void
174child_return(void *arg) 174child_return(void *arg)
175{ 175{
176 struct lwp *l = arg; 176 struct lwp *l = arg;
177 struct frame *frame = (struct frame *)l->l_md.md_regs; 177 struct frame *frame = (struct frame *)l->l_md.md_regs;
178 178
179 frame->f_regs[_R_V0] = 0; 179 frame->f_regs[_R_V0] = 0;
180 frame->f_regs[_R_V1] = 1; 180 frame->f_regs[_R_V1] = 1;
181 frame->f_regs[_R_A3] = 0; 181 frame->f_regs[_R_A3] = 0;
182 userret(l); 182 userret(l);
183 ktrsysret(SYS_fork, 0, 0); 183 ktrsysret(SYS_fork, 0, 0);
184} 184}
185 185
186#ifdef MIPS3_PLUS 186#ifdef MIPS3_PLUS
187#define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT) 187#define TRAPTYPE(x) (((x) & MIPS3_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
188#else 188#else
189#define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT) 189#define TRAPTYPE(x) (((x) & MIPS1_CR_EXC_CODE) >> MIPS_CR_EXC_CODE_SHIFT)
190#endif 190#endif
191#define KERNLAND(x) ((intptr_t)(x) < 0) 191#define KERNLAND(x) ((intptr_t)(x) < 0)
192 192
193/* 193/*
194 * Trap is called from locore to handle most types of processor traps. 194 * Trap is called from locore to handle most types of processor traps.
195 * System calls are broken out for efficiency. MIPS can handle software 195 * System calls are broken out for efficiency. MIPS can handle software
196 * interrupts as a part of real interrupt processing. 196 * interrupts as a part of real interrupt processing.
197 */ 197 */
198void 198void
199trap(unsigned int status, unsigned int cause, vaddr_t vaddr, vaddr_t opc, 199trap(unsigned int status, unsigned int cause, vaddr_t vaddr, vaddr_t opc,
200 struct trapframe *frame) 200 struct trapframe *frame)
201{ 201{
202 int type; 202 int type;
203 struct lwp *l = curlwp; 203 struct lwp *l = curlwp;
204 struct proc *p = curproc; 204 struct proc *p = curproc;
205 vm_prot_t ftype; 205 vm_prot_t ftype;
206 ksiginfo_t ksi; 206 ksiginfo_t ksi;
207 struct frame *fp; 207 struct frame *fp;
208 extern void fswintrberr(void); 208 extern void fswintrberr(void);
209 KSI_INIT_TRAP(&ksi); 209 KSI_INIT_TRAP(&ksi);
210 210
211 uvmexp.traps++; 211 uvmexp.traps++;
212 type = TRAPTYPE(cause); 212 type = TRAPTYPE(cause);
213 if (USERMODE(status)) { 213 if (USERMODE(status)) {
214 type |= T_USER; 214 type |= T_USER;
215 LWP_CACHE_CREDS(l, p); 215 LWP_CACHE_CREDS(l, p);
216 } 216 }
217 217
218 if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV)) { 218 if (status & ((CPUISMIPS3) ? MIPS_SR_INT_IE : MIPS1_SR_INT_ENA_PREV)) {
219 if (type != T_BREAK) { 219 if (type != T_BREAK) {
220#ifdef IPL_ICU_MASK 220#ifdef IPL_ICU_MASK
221 spllowersofthigh(); 221 spllowersofthigh();
222#else 222#else
223 _splset((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE); 223 _splset((status & MIPS_HARD_INT_MASK) | MIPS_SR_INT_IE);
224#endif 224#endif
225 } 225 }
226 } 226 }
227 227
228 switch (type) { 228 switch (type) {
229 default: 229 default:
230 dopanic: 230 dopanic:
231 (void)splhigh(); 231 (void)splhigh();
232 printf("trap: %s in %s mode\n", 232 printf("trap: %s in %s mode\n",
233 trap_type[TRAPTYPE(cause)], 233 trap_type[TRAPTYPE(cause)],
234 USERMODE(status) ? "user" : "kernel"); 234 USERMODE(status) ? "user" : "kernel");
235 printf("status=0x%x, cause=0x%x, epc=%#lx, vaddr=%#lx\n", 235 printf("status=0x%x, cause=0x%x, epc=%#lx, vaddr=%#lx\n",
236 status, cause, opc, vaddr); 236 status, cause, opc, vaddr);
237 if (curlwp != NULL) { 237 if (curlwp != NULL) {
238 fp = (struct frame *)l->l_md.md_regs; 238 fp = (struct frame *)l->l_md.md_regs;
239 printf("pid=%d cmd=%s usp=0x%x ", 239 printf("pid=%d cmd=%s usp=0x%x ",
240 p->p_pid, p->p_comm, (int)fp->f_regs[_R_SP]); 240 p->p_pid, p->p_comm, (int)fp->f_regs[_R_SP]);
241 } else 241 } else
242 printf("curlwp == NULL "); 242 printf("curlwp == NULL ");
243 printf("ksp=%p\n", &status); 243 printf("ksp=%p ra=%#x\n", &status, (int)frame->tf_regs[TF_RA]);
244#if defined(DDB) 244#if defined(DDB)
245 kdb_trap(type, (mips_reg_t *) frame); 245 kdb_trap(type, (mips_reg_t *) frame);
246 /* XXX force halt XXX */ 246 /* XXX force halt XXX */
247#elif defined(KGDB) 247#elif defined(KGDB)
248 { 248 {
249 struct frame *f = (struct frame *)&ddb_regs; 249 struct frame *f = (struct frame *)&ddb_regs;
250 extern mips_reg_t kgdb_cause, kgdb_vaddr; 250 extern mips_reg_t kgdb_cause, kgdb_vaddr;
251 kgdb_cause = cause; 251 kgdb_cause = cause;
252 kgdb_vaddr = vaddr; 252 kgdb_vaddr = vaddr;
253 253
254 /* 254 /*
255 * init global ddb_regs, used in db_interface.c routines 255 * init global ddb_regs, used in db_interface.c routines
256 * shared between ddb and gdb. Send ddb_regs to gdb so 256 * shared between ddb and gdb. Send ddb_regs to gdb so
257 * that db_machdep.h macros will work with it, and 257 * that db_machdep.h macros will work with it, and
258 * allow gdb to alter the PC. 258 * allow gdb to alter the PC.
259 */ 259 */
260 db_set_ddb_regs(type, (mips_reg_t *) frame); 260 db_set_ddb_regs(type, (mips_reg_t *) frame);
261 PC_BREAK_ADVANCE(f); 261 PC_BREAK_ADVANCE(f);
262 if (kgdb_trap(type, &ddb_regs)) { 262 if (kgdb_trap(type, &ddb_regs)) {
263 ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC]; 263 ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC];
264 return; 264 return;
265 } 265 }
266 } 266 }
267#else 267#else
268 panic("trap"); 268 panic("trap");
269#endif 269#endif
270 /*NOTREACHED*/ 270 /*NOTREACHED*/
271 case T_TLB_MOD: 271 case T_TLB_MOD:
272 if (KERNLAND(vaddr)) { 272 if (KERNLAND(vaddr)) {
273 pt_entry_t *pte; 273 pt_entry_t *pte;
274 unsigned entry; 274 unsigned entry;
275 paddr_t pa; 275 paddr_t pa;
276 276
277 pte = kvtopte(vaddr); 277 pte = kvtopte(vaddr);
278 entry = pte->pt_entry; 278 entry = pte->pt_entry;
279 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { 279 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
280 panic("ktlbmod: invalid pte"); 280 panic("ktlbmod: invalid pte");
281 } 281 }
282 if (entry & mips_pg_ro_bit()) { 282 if (entry & mips_pg_ro_bit()) {
283 /* write to read only page in the kernel */ 283 /* write to read only page in the kernel */
284 ftype = VM_PROT_WRITE; 284 ftype = VM_PROT_WRITE;
285 goto kernelfault; 285 goto kernelfault;
286 } 286 }
287 entry |= mips_pg_m_bit(); 287 entry |= mips_pg_m_bit();
288 pte->pt_entry = entry; 288 pte->pt_entry = entry;
289 vaddr &= ~PGOFSET; 289 vaddr &= ~PGOFSET;
290 MachTLBUpdate(vaddr, entry); 290 MachTLBUpdate(vaddr, entry);
291 pa = mips_tlbpfn_to_paddr(entry); 291 pa = mips_tlbpfn_to_paddr(entry);
292 if (!IS_VM_PHYSADDR(pa)) { 292 if (!IS_VM_PHYSADDR(pa)) {
293 printf("ktlbmod: va %#lx pa %#llx\n", 293 printf("ktlbmod: va %#lx pa %#llx\n",
294 vaddr, (long long)pa); 294 vaddr, (long long)pa);
295 panic("ktlbmod: unmanaged page"); 295 panic("ktlbmod: unmanaged page");
296 } 296 }
297 pmap_set_modified(pa); 297 pmap_set_modified(pa);
298 return; /* KERN */ 298 return; /* KERN */
299 } 299 }
300 /*FALLTHROUGH*/ 300 /*FALLTHROUGH*/
301 case T_TLB_MOD+T_USER: 301 case T_TLB_MOD+T_USER:
302 { 302 {
303 pt_entry_t *pte; 303 pt_entry_t *pte;
304 unsigned entry; 304 unsigned entry;
305 paddr_t pa; 305 paddr_t pa;
306 pmap_t pmap; 306 pmap_t pmap;
307 307
308 pmap = p->p_vmspace->vm_map.pmap; 308 pmap = p->p_vmspace->vm_map.pmap;
309 if (!(pte = pmap_segmap(pmap, vaddr))) 309 if (!(pte = pmap_segmap(pmap, vaddr)))
310 panic("utlbmod: invalid segmap"); 310 panic("utlbmod: invalid segmap");
311 pte += (vaddr >> PGSHIFT) & (NPTEPG - 1); 311 pte += (vaddr >> PGSHIFT) & (NPTEPG - 1);
312 entry = pte->pt_entry; 312 entry = pte->pt_entry;
313 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) 313 if (!mips_pg_v(entry) || (entry & mips_pg_m_bit()))
314 panic("utlbmod: invalid pte"); 314 panic("utlbmod: invalid pte");
315 315
316 if (entry & mips_pg_ro_bit()) { 316 if (entry & mips_pg_ro_bit()) {
317 /* write to read only page */ 317 /* write to read only page */
318 ftype = VM_PROT_WRITE; 318 ftype = VM_PROT_WRITE;
319 goto pagefault; 319 goto pagefault;
320 } 320 }
321 entry |= mips_pg_m_bit(); 321 entry |= mips_pg_m_bit();
322 pte->pt_entry = entry; 322 pte->pt_entry = entry;
323 vaddr = (vaddr & ~PGOFSET) | 323 vaddr = (vaddr & ~PGOFSET) |
324 (pmap->pm_asid << MIPS_TLB_PID_SHIFT); 324 (pmap->pm_asid << MIPS_TLB_PID_SHIFT);
325 MachTLBUpdate(vaddr, entry); 325 MachTLBUpdate(vaddr, entry);
326 pa = mips_tlbpfn_to_paddr(entry); 326 pa = mips_tlbpfn_to_paddr(entry);
327 if (!IS_VM_PHYSADDR(pa)) { 327 if (!IS_VM_PHYSADDR(pa)) {
328 printf("utlbmod: va %#lx pa %#llx\n", 328 printf("utlbmod: va %#lx pa %#llx\n",
329 vaddr, (long long)pa); 329 vaddr, (long long)pa);
330 panic("utlbmod: unmanaged page"); 330 panic("utlbmod: unmanaged page");
331 } 331 }
332 pmap_set_modified(pa); 332 pmap_set_modified(pa);
333 if (type & T_USER) 333 if (type & T_USER)
334 userret(l); 334 userret(l);
335 return; /* GEN */ 335 return; /* GEN */
336 } 336 }
337 case T_TLB_LD_MISS: 337 case T_TLB_LD_MISS:
338 case T_TLB_ST_MISS: 338 case T_TLB_ST_MISS:
339 ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE; 339 ftype = (type == T_TLB_LD_MISS) ? VM_PROT_READ : VM_PROT_WRITE;
340 if (KERNLAND(vaddr)) 340 if (KERNLAND(vaddr))
341 goto kernelfault; 341 goto kernelfault;
342 /* 342 /*
343 * It is an error for the kernel to access user space except 343 * It is an error for the kernel to access user space except
344 * through the copyin/copyout routines. 344 * through the copyin/copyout routines.
345 */ 345 */
346 if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL) 346 if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
347 goto dopanic; 347 goto dopanic;
348 /* check for fuswintr() or suswintr() getting a page fault */ 348 /* check for fuswintr() or suswintr() getting a page fault */
349 if (l->l_addr->u_pcb.pcb_onfault == (void *)fswintrberr) { 349 if (l->l_addr->u_pcb.pcb_onfault == (void *)fswintrberr) {
350 frame->tf_regs[TF_EPC] = (int)fswintrberr; 350 frame->tf_regs[TF_EPC] = (int)fswintrberr;
351 return; /* KERN */ 351 return; /* KERN */
352 } 352 }
353 goto pagefault; 353 goto pagefault;
354 case T_TLB_LD_MISS+T_USER: 354 case T_TLB_LD_MISS+T_USER:
355 ftype = VM_PROT_READ; 355 ftype = VM_PROT_READ;
356 goto pagefault; 356 goto pagefault;
357 case T_TLB_ST_MISS+T_USER: 357 case T_TLB_ST_MISS+T_USER:
358 ftype = VM_PROT_WRITE; 358 ftype = VM_PROT_WRITE;
359 pagefault: ; 359 pagefault: ;
360 { 360 {
361 vaddr_t va; 361 vaddr_t va;
362 struct vmspace *vm; 362 struct vmspace *vm;
363 struct vm_map *map; 363 struct vm_map *map;
364 int rv; 364 int rv;
365 365
366 vm = p->p_vmspace; 366 vm = p->p_vmspace;
367 map = &vm->vm_map; 367 map = &vm->vm_map;
368 va = trunc_page(vaddr); 368 va = trunc_page(vaddr);
369 369
370 if ((l->l_flag & LW_SA) && (~l->l_pflag & LP_SA_NOBLOCK)) { 370 if ((l->l_flag & LW_SA) && (~l->l_pflag & LP_SA_NOBLOCK)) {
371 l->l_savp->savp_faultaddr = (vaddr_t)vaddr; 371 l->l_savp->savp_faultaddr = (vaddr_t)vaddr;
372 l->l_pflag |= LP_SA_PAGEFAULT; 372 l->l_pflag |= LP_SA_PAGEFAULT;
373 } 373 }
374 374
375 if (p->p_emul->e_fault) 375 if (p->p_emul->e_fault)
376 rv = (*p->p_emul->e_fault)(p, va, ftype); 376 rv = (*p->p_emul->e_fault)(p, va, ftype);
377 else 377 else
378 rv = uvm_fault(map, va, ftype); 378 rv = uvm_fault(map, va, ftype);
379#ifdef VMFAULT_TRACE 379#ifdef VMFAULT_TRACE
380 printf( 380 printf(
381 "uvm_fault(%p (pmap %p), %lx (0x%x), %d) -> %d at pc %p\n", 381 "uvm_fault(%p (pmap %p), %lx (0x%x), %d) -> %d at pc %p\n",
382 map, vm->vm_map.pmap, va, vaddr, ftype, rv, (void*)opc); 382 map, vm->vm_map.pmap, va, vaddr, ftype, rv, (void*)opc);
383#endif 383#endif
384 /* 384 /*
385 * If this was a stack access we keep track of the maximum 385 * If this was a stack access we keep track of the maximum
386 * accessed stack size. Also, if vm_fault gets a protection 386 * accessed stack size. Also, if vm_fault gets a protection
387 * failure it is due to accessing the stack region outside 387 * failure it is due to accessing the stack region outside
388 * the current limit and we need to reflect that as an access 388 * the current limit and we need to reflect that as an access
389 * error. 389 * error.
390 */ 390 */
391 if ((void *)va >= vm->vm_maxsaddr) { 391 if ((void *)va >= vm->vm_maxsaddr) {
392 if (rv == 0) 392 if (rv == 0)
393 uvm_grow(p, va); 393 uvm_grow(p, va);
394 else if (rv == EACCES) 394 else if (rv == EACCES)
395 rv = EFAULT; 395 rv = EFAULT;
396 } 396 }
397 l->l_pflag &= ~LP_SA_PAGEFAULT; 397 l->l_pflag &= ~LP_SA_PAGEFAULT;
398 if (rv == 0) { 398 if (rv == 0) {
399 if (type & T_USER) { 399 if (type & T_USER) {
400 userret(l); 400 userret(l);
401 } 401 }
402 return; /* GEN */ 402 return; /* GEN */
403 } 403 }
404 if ((type & T_USER) == 0) 404 if ((type & T_USER) == 0)
405 goto copyfault; 405 goto copyfault;
406 if (rv == ENOMEM) { 406 if (rv == ENOMEM) {
407 printf("UVM: pid %d (%s), uid %d killed: out of swap\n", 407 printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
408 p->p_pid, p->p_comm, 408 p->p_pid, p->p_comm,
409 l->l_cred ? 409 l->l_cred ?
410 kauth_cred_geteuid(l->l_cred) : (uid_t) -1); 410 kauth_cred_geteuid(l->l_cred) : (uid_t) -1);
411 ksi.ksi_signo = SIGKILL; 411 ksi.ksi_signo = SIGKILL;
412 ksi.ksi_code = 0; 412 ksi.ksi_code = 0;
413 } else { 413 } else {
414 if (rv == EACCES) { 414 if (rv == EACCES) {
415 ksi.ksi_signo = SIGBUS; 415 ksi.ksi_signo = SIGBUS;
416 ksi.ksi_code = BUS_OBJERR; 416 ksi.ksi_code = BUS_OBJERR;
417 } else { 417 } else {
418 ksi.ksi_signo = SIGSEGV; 418 ksi.ksi_signo = SIGSEGV;
419 ksi.ksi_code = SEGV_MAPERR; 419 ksi.ksi_code = SEGV_MAPERR;
420 } 420 }
421 } 421 }
422 ksi.ksi_trap = type & ~T_USER; 422 ksi.ksi_trap = type & ~T_USER;
423 ksi.ksi_addr = (void *)vaddr; 423 ksi.ksi_addr = (void *)vaddr;
424 break; /* SIGNAL */ 424 break; /* SIGNAL */
425 } 425 }
426 kernelfault: ; 426 kernelfault: ;
427 { 427 {
428 vaddr_t va; 428 vaddr_t va;
429 int rv; 429 int rv;
430 430
431 va = trunc_page(vaddr); 431 va = trunc_page(vaddr);
432 rv = uvm_fault(kernel_map, va, ftype); 432 rv = uvm_fault(kernel_map, va, ftype);
433 if (rv == 0) 433 if (rv == 0)
434 return; /* KERN */ 434 return; /* KERN */
435 /*FALLTHROUGH*/ 435 /*FALLTHROUGH*/
436 } 436 }
437 case T_ADDR_ERR_LD: /* misaligned access */ 437 case T_ADDR_ERR_LD: /* misaligned access */
438 case T_ADDR_ERR_ST: /* misaligned access */ 438 case T_ADDR_ERR_ST: /* misaligned access */
439 case T_BUS_ERR_LD_ST: /* BERR asserted to CPU */ 439 case T_BUS_ERR_LD_ST: /* BERR asserted to CPU */
440 copyfault: 440 copyfault:
441 if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL) 441 if (l == NULL || l->l_addr->u_pcb.pcb_onfault == NULL)
442 goto dopanic; 442 goto dopanic;
443 frame->tf_regs[TF_EPC] = (intptr_t)l->l_addr->u_pcb.pcb_onfault; 443 frame->tf_regs[TF_EPC] = (intptr_t)l->l_addr->u_pcb.pcb_onfault;
444 return; /* KERN */ 444 return; /* KERN */
445 445
446 case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ 446 case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */
447 case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ 447 case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */
448 case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to CPU */ 448 case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to CPU */
449 case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to CPU */ 449 case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to CPU */
450 ksi.ksi_trap = type & ~T_USER; 450 ksi.ksi_trap = type & ~T_USER;
451 ksi.ksi_signo = SIGSEGV; /* XXX */ 451 ksi.ksi_signo = SIGSEGV; /* XXX */
452 ksi.ksi_addr = (void *)vaddr; 452 ksi.ksi_addr = (void *)vaddr;
453 ksi.ksi_code = SEGV_MAPERR; /* XXX */ 453 ksi.ksi_code = SEGV_MAPERR; /* XXX */
454 break; /* SIGNAL */ 454 break; /* SIGNAL */
455 455
456 case T_BREAK: 456 case T_BREAK:
457#if defined(DDB) 457#if defined(DDB)
458 kdb_trap(type, (mips_reg_t *) frame); 458 kdb_trap(type, (mips_reg_t *) frame);
459 return; /* KERN */ 459 return; /* KERN */
460#elif defined(KGDB) 460#elif defined(KGDB)
461 { 461 {
462 struct frame *f = (struct frame *)&ddb_regs; 462 struct frame *f = (struct frame *)&ddb_regs;
463 extern mips_reg_t kgdb_cause, kgdb_vaddr; 463 extern mips_reg_t kgdb_cause, kgdb_vaddr;
464 kgdb_cause = cause; 464 kgdb_cause = cause;
465 kgdb_vaddr = vaddr; 465 kgdb_vaddr = vaddr;
466 466
467 /* 467 /*
468 * init global ddb_regs, used in db_interface.c routines 468 * init global ddb_regs, used in db_interface.c routines
469 * shared between ddb and gdb. Send ddb_regs to gdb so 469 * shared between ddb and gdb. Send ddb_regs to gdb so
470 * that db_machdep.h macros will work with it, and 470 * that db_machdep.h macros will work with it, and
471 * allow gdb to alter the PC. 471 * allow gdb to alter the PC.
472 */ 472 */
473 db_set_ddb_regs(type, (mips_reg_t *) frame); 473 db_set_ddb_regs(type, (mips_reg_t *) frame);
474 PC_BREAK_ADVANCE(f); 474 PC_BREAK_ADVANCE(f);
475 if (!kgdb_trap(type, &ddb_regs)) 475 if (!kgdb_trap(type, &ddb_regs))
476 printf("kgdb: ignored %s\n", 476 printf("kgdb: ignored %s\n",
477 trap_type[TRAPTYPE(cause)]); 477 trap_type[TRAPTYPE(cause)]);
478 else 478 else
479 ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC]; 479 ((mips_reg_t *)frame)[21] = f->f_regs[_R_PC];
480 480
481 return; 481 return;
482 } 482 }
483#else 483#else
484 goto dopanic; 484 goto dopanic;
485#endif 485#endif
486 case T_BREAK+T_USER: 486 case T_BREAK+T_USER:
487 { 487 {
488 vaddr_t va; 488 vaddr_t va;
489 uint32_t instr; 489 uint32_t instr;
490 int rv; 490 int rv;
491 491
492 /* compute address of break instruction */ 492 /* compute address of break instruction */
493 va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc; 493 va = (DELAYBRANCH(cause)) ? opc + sizeof(int) : opc;
494 494
495 /* read break instruction */ 495 /* read break instruction */
496 instr = fuiword((void *)va); 496 instr = fuiword((void *)va);
497 497
498 if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) { 498 if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
499 ksi.ksi_trap = type & ~T_USER; 499 ksi.ksi_trap = type & ~T_USER;
500 ksi.ksi_signo = SIGTRAP; 500 ksi.ksi_signo = SIGTRAP;
501 ksi.ksi_addr = (void *)va; 501 ksi.ksi_addr = (void *)va;
502 ksi.ksi_code = TRAP_TRACE; 502 ksi.ksi_code = TRAP_TRACE;
503 break; 503 break;
504 } 504 }
505 /* 505 /*
506 * Restore original instruction and clear BP 506 * Restore original instruction and clear BP
507 */ 507 */
508 rv = suiword((void *)va, l->l_md.md_ss_instr); 508 rv = suiword((void *)va, l->l_md.md_ss_instr);
509 if (rv < 0) { 509 if (rv < 0) {
510 vaddr_t sa, ea; 510 vaddr_t sa, ea;
511 sa = trunc_page(va); 511 sa = trunc_page(va);
512 ea = round_page(va + sizeof(int) - 1); 512 ea = round_page(va + sizeof(int) - 1);
513 rv = uvm_map_protect(&p->p_vmspace->vm_map, 513 rv = uvm_map_protect(&p->p_vmspace->vm_map,
514 sa, ea, VM_PROT_ALL, false); 514 sa, ea, VM_PROT_ALL, false);
515 if (rv == 0) { 515 if (rv == 0) {
516 rv = suiword((void *)va, l->l_md.md_ss_instr); 516 rv = suiword((void *)va, l->l_md.md_ss_instr);
517 (void)uvm_map_protect(&p->p_vmspace->vm_map, 517 (void)uvm_map_protect(&p->p_vmspace->vm_map,
518 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false); 518 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
519 } 519 }
520 } 520 }
521 mips_icache_sync_all(); /* XXXJRT -- necessary? */ 521 mips_icache_sync_all(); /* XXXJRT -- necessary? */
522 mips_dcache_wbinv_all(); /* XXXJRT -- necessary? */ 522 mips_dcache_wbinv_all(); /* XXXJRT -- necessary? */
523 523
524 if (rv < 0) 524 if (rv < 0)
525 printf("Warning: can't restore instruction at 0x%lx: 0x%x\n", 525 printf("Warning: can't restore instruction at 0x%lx: 0x%x\n",
526 l->l_md.md_ss_addr, l->l_md.md_ss_instr); 526 l->l_md.md_ss_addr, l->l_md.md_ss_instr);
527 l->l_md.md_ss_addr = 0; 527 l->l_md.md_ss_addr = 0;
528 ksi.ksi_trap = type & ~T_USER; 528 ksi.ksi_trap = type & ~T_USER;
529 ksi.ksi_signo = SIGTRAP; 529 ksi.ksi_signo = SIGTRAP;
530 ksi.ksi_addr = (void *)va; 530 ksi.ksi_addr = (void *)va;
531 ksi.ksi_code = TRAP_BRKPT; 531 ksi.ksi_code = TRAP_BRKPT;
532 break; /* SIGNAL */ 532 break; /* SIGNAL */
533 } 533 }
534 case T_RES_INST+T_USER: 534 case T_RES_INST+T_USER:
535 case T_COP_UNUSABLE+T_USER: 535 case T_COP_UNUSABLE+T_USER:
536#if !defined(SOFTFLOAT) && !defined(NOFPU) 536#if !defined(SOFTFLOAT) && !defined(NOFPU)
537 if ((cause & MIPS_CR_COP_ERR) == 0x10000000) { 537 if ((cause & MIPS_CR_COP_ERR) == 0x10000000) {
538 struct frame *f; 538 struct frame *f;
539 539
540 f = (struct frame *)l->l_md.md_regs; 540 f = (struct frame *)l->l_md.md_regs;
541 savefpregs(fpcurlwp); /* yield FPA */ 541 savefpregs(fpcurlwp); /* yield FPA */
542 loadfpregs(l); /* load FPA */ 542 loadfpregs(l); /* load FPA */
543 fpcurlwp = l; 543 fpcurlwp = l;
544 l->l_md.md_flags |= MDP_FPUSED; 544 l->l_md.md_flags |= MDP_FPUSED;
545 f->f_regs[_R_SR] |= MIPS_SR_COP_1_BIT; 545 f->f_regs[_R_SR] |= MIPS_SR_COP_1_BIT;
546 } else 546 } else
547#endif 547#endif
548 { 548 {
549 MachEmulateInst(status, cause, opc, l->l_md.md_regs); 549 MachEmulateInst(status, cause, opc, l->l_md.md_regs);
550 } 550 }
551 userret(l); 551 userret(l);
552 return; /* GEN */ 552 return; /* GEN */
553 case T_FPE+T_USER: 553 case T_FPE+T_USER:
554#if defined(SOFTFLOAT) 554#if defined(SOFTFLOAT)
555 MachEmulateInst(status, cause, opc, l->l_md.md_regs); 555 MachEmulateInst(status, cause, opc, l->l_md.md_regs);
556#elif !defined(NOFPU) 556#elif !defined(NOFPU)
557 MachFPTrap(status, cause, opc, l->l_md.md_regs); 557 MachFPTrap(status, cause, opc, l->l_md.md_regs);
558#endif 558#endif
559 userret(l); 559 userret(l);
560 return; /* GEN */ 560 return; /* GEN */
561 case T_OVFLOW+T_USER: 561 case T_OVFLOW+T_USER:
562 case T_TRAP+T_USER: 562 case T_TRAP+T_USER:
563 ksi.ksi_trap = type & ~T_USER; 563 ksi.ksi_trap = type & ~T_USER;
564 ksi.ksi_signo = SIGFPE; 564 ksi.ksi_signo = SIGFPE;
565 fp = (struct frame *)l->l_md.md_regs; 565 fp = (struct frame *)l->l_md.md_regs;
566 ksi.ksi_addr = (void *)fp->f_regs[_R_PC]; 566 ksi.ksi_addr = (void *)fp->f_regs[_R_PC];
567 ksi.ksi_code = FPE_FLTOVF; /* XXX */ 567 ksi.ksi_code = FPE_FLTOVF; /* XXX */
568 break; /* SIGNAL */ 568 break; /* SIGNAL */
569 } 569 }
570 fp = (struct frame *)l->l_md.md_regs; 570 fp = (struct frame *)l->l_md.md_regs;
571 fp->f_regs[_R_CAUSE] = cause; 571 fp->f_regs[_R_CAUSE] = cause;
572 fp->f_regs[_R_BADVADDR] = vaddr; 572 fp->f_regs[_R_BADVADDR] = vaddr;
573 (*p->p_emul->e_trapsignal)(l, &ksi); 573 (*p->p_emul->e_trapsignal)(l, &ksi);
574 if ((type & T_USER) == 0) 574 if ((type & T_USER) == 0)
575 panic("trapsignal"); 575 panic("trapsignal");
576 userret(l); 576 userret(l);
577 return; 577 return;
578} 578}
579 579
580/* 580/*
581 * Handle asynchronous software traps. 581 * Handle asynchronous software traps.
582 * This is called from MachUserIntr() either to deliver signals or 582 * This is called from MachUserIntr() either to deliver signals or
583 * to make involuntary context switch (preemption). 583 * to make involuntary context switch (preemption).
584 */ 584 */
585void 585void
586ast(unsigned pc) /* pc is program counter where to continue */ 586ast(unsigned pc) /* pc is program counter where to continue */
587{ 587{
588 struct lwp *l = curlwp; 588 struct lwp *l = curlwp;
589 589
590 while (l->l_md.md_astpending) { 590 while (l->l_md.md_astpending) {
591 uvmexp.softs++; 591 uvmexp.softs++;
592 l->l_md.md_astpending = 0; 592 l->l_md.md_astpending = 0;
593 593
594 if (l->l_pflag & LP_OWEUPC) { 594 if (l->l_pflag & LP_OWEUPC) {
595 l->l_pflag &= ~LP_OWEUPC; 595 l->l_pflag &= ~LP_OWEUPC;
596 ADDUPROF(l); 596 ADDUPROF(l);
597 } 597 }
598 598
599 userret(l); 599 userret(l);
600 600
601 if (curcpu()->ci_want_resched) { 601 if (curcpu()->ci_want_resched) {
602 /* 602 /*
603 * We are being preempted. 603 * We are being preempted.
604 */ 604 */
605 preempt(); 605 preempt();
606 } 606 }
607 } 607 }
608} 608}
609 609
610 610
611/* XXX need to rewrite acient comment XXX 611/* XXX need to rewrite acient comment XXX
612 * This routine is called by procxmt() to single step one instruction. 612 * This routine is called by procxmt() to single step one instruction.
613 * We do this by storing a break instruction after the current instruction, 613 * We do this by storing a break instruction after the current instruction,
614 * resuming execution, and then restoring the old instruction. 614 * resuming execution, and then restoring the old instruction.
615 */ 615 */
616int 616int
617mips_singlestep(struct lwp *l) 617mips_singlestep(struct lwp *l)
618{ 618{
619 struct frame *f = (struct frame *)l->l_md.md_regs; 619 struct frame *f = (struct frame *)l->l_md.md_regs;
620 struct proc *p = l->l_proc; 620 struct proc *p = l->l_proc;
621 vaddr_t pc, va; 621 vaddr_t pc, va;
622 int rv; 622 int rv;
623 623
624 if (l->l_md.md_ss_addr) { 624 if (l->l_md.md_ss_addr) {
625 printf("SS %s (%d): breakpoint already set at %lx\n", 625 printf("SS %s (%d): breakpoint already set at %lx\n",
626 p->p_comm, p->p_pid, l->l_md.md_ss_addr); 626 p->p_comm, p->p_pid, l->l_md.md_ss_addr);
627 return EFAULT; 627 return EFAULT;
628 } 628 }
629 pc = (vaddr_t)f->f_regs[_R_PC]; 629 pc = (vaddr_t)f->f_regs[_R_PC];
630 if (fuiword((void *)pc) != 0) /* not a NOP instruction */ 630 if (fuiword((void *)pc) != 0) /* not a NOP instruction */
631 va = MachEmulateBranch(f, pc, PCB_FSR(&l->l_addr->u_pcb), 1); 631 va = MachEmulateBranch(f, pc, PCB_FSR(&l->l_addr->u_pcb), 1);
632 else 632 else
633 va = pc + sizeof(int); 633 va = pc + sizeof(int);
634 634
635 /* 635 /*
636 * We can't single-step into a RAS. Check if we're in 636 * We can't single-step into a RAS. Check if we're in
637 * a RAS, and set the breakpoint just past it. 637 * a RAS, and set the breakpoint just past it.
638 */ 638 */
639 if (p->p_raslist != NULL) { 639 if (p->p_raslist != NULL) {
640 while (ras_lookup(p, (void *)va) != (void *)-1) 640 while (ras_lookup(p, (void *)va) != (void *)-1)
641 va += sizeof(int); 641 va += sizeof(int);
642 } 642 }
643 643
644 l->l_md.md_ss_addr = va; 644 l->l_md.md_ss_addr = va;
645 l->l_md.md_ss_instr = fuiword((void *)va); 645 l->l_md.md_ss_instr = fuiword((void *)va);
646 rv = suiword((void *)va, MIPS_BREAK_SSTEP); 646 rv = suiword((void *)va, MIPS_BREAK_SSTEP);
647 if (rv < 0) { 647 if (rv < 0) {
648 vaddr_t sa, ea; 648 vaddr_t sa, ea;
649 sa = trunc_page(va); 649 sa = trunc_page(va);
650 ea = round_page(va + sizeof(int) - 1); 650 ea = round_page(va + sizeof(int) - 1);
651 rv = uvm_map_protect(&p->p_vmspace->vm_map, 651 rv = uvm_map_protect(&p->p_vmspace->vm_map,
652 sa, ea, VM_PROT_ALL, false); 652 sa, ea, VM_PROT_ALL, false);
653 if (rv == 0) { 653 if (rv == 0) {
654 rv = suiword((void *)va, MIPS_BREAK_SSTEP); 654 rv = suiword((void *)va, MIPS_BREAK_SSTEP);
655 (void)uvm_map_protect(&p->p_vmspace->vm_map, 655 (void)uvm_map_protect(&p->p_vmspace->vm_map,
656 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false); 656 sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, false);
657 } 657 }
658 } 658 }
659#if 0 659#if 0
660 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", 660 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
661 p->p_comm, p->p_pid, p->p_md.md_ss_addr, 661 p->p_comm, p->p_pid, p->p_md.md_ss_addr,
662 p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */ 662 p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */
663#endif 663#endif
664 return 0; 664 return 0;
665} 665}
666 666
667 667
668#ifndef DDB_TRACE 668#ifndef DDB_TRACE
669 669
670#if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo) 670#if defined(DEBUG) || defined(DDB) || defined(KGDB) || defined(geo)
671mips_reg_t kdbrpeek(vaddr_t); 671mips_reg_t kdbrpeek(vaddr_t);
672 672
673int 673int
674kdbpeek(vaddr_t addr) 674kdbpeek(vaddr_t addr)
675{ 675{
676 int rc; 676 int rc;
677 677
678 if (addr & 3) { 678 if (addr & 3) {
679 printf("kdbpeek: unaligned address %lx\n", addr); 679 printf("kdbpeek: unaligned address %lx\n", addr);
680 /* We might have been called from DDB, so do not go there. */ 680 /* We might have been called from DDB, so do not go there. */
681 stacktrace(); 681 stacktrace();
682 rc = -1 ; 682 rc = -1 ;
683 } else if (addr == 0) { 683 } else if (addr == 0) {
684 printf("kdbpeek: NULL\n"); 684 printf("kdbpeek: NULL\n");
685 rc = 0xdeadfeed; 685 rc = 0xdeadfeed;
686 } else { 686 } else {
687 rc = *(int *)addr; 687 rc = *(int *)addr;
688 } 688 }
689 return rc; 689 return rc;
690} 690}
691 691
692mips_reg_t 692mips_reg_t
693kdbrpeek(vaddr_t addr) 693kdbrpeek(vaddr_t addr)
694{ 694{
695 mips_reg_t rc; 695 mips_reg_t rc;
696 696
697 if (addr & (sizeof(mips_reg_t) - 1)) { 697 if (addr & (sizeof(mips_reg_t) - 1)) {
698 printf("kdbrpeek: unaligned address %lx\n", addr); 698 printf("kdbrpeek: unaligned address %lx\n", addr);
699 /* We might have been called from DDB, so do not go there. */ 699 /* We might have been called from DDB, so do not go there. */
700 stacktrace(); 700 stacktrace();
701 rc = -1 ; 701 rc = -1 ;
702 } else if (addr == 0) { 702 } else if (addr == 0) {
703 printf("kdbrpeek: NULL\n"); 703 printf("kdbrpeek: NULL\n");
704 rc = 0xdeadfeed; 704 rc = 0xdeadfeed;
705 } else { 705 } else {
706 rc = *(mips_reg_t *)addr; 706 rc = *(mips_reg_t *)addr;
707 } 707 }
708 return rc; 708 return rc;
709} 709}
710 710
711extern char start[], edata[], verylocore[]; 711extern char start[], edata[], verylocore[];
712extern char mips1_KernGenException[]; 712extern char mips1_KernGenException[];
713extern char mips1_UserGenException[]; 713extern char mips1_UserGenException[];
714extern char mips1_KernIntr[]; 714extern char mips1_KernIntr[];
715extern char mips1_UserIntr[]; 715extern char mips1_UserIntr[];
716extern char mips1_SystemCall[]; 716extern char mips1_SystemCall[];
717extern char mips3_KernGenException[]; 717extern char mips3_KernGenException[];
718extern char mips3_UserGenException[]; 718extern char mips3_UserGenException[];
719extern char mips3_KernIntr[]; 719extern char mips3_KernIntr[];
720extern char mips3_UserIntr[]; 720extern char mips3_UserIntr[];
721extern char mips3_SystemCall[]; 721extern char mips3_SystemCall[];
722int main(void *); /* XXX */ 722int main(void *); /* XXX */
723 723
724/* 724/*
725 * stack trace code, also useful to DDB one day 725 * stack trace code, also useful to DDB one day
726 */ 726 */
727 727
728/* forward */ 728/* forward */
729const char *fn_name(vaddr_t addr); 729const char *fn_name(vaddr_t addr);
730void stacktrace_subr(int, int, int, int, u_int, u_int, u_int, u_int, 730void stacktrace_subr(int, int, int, int, u_int, u_int, u_int, u_int,
731 void (*)(const char*, ...)); 731 void (*)(const char*, ...));
732 732
733#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */ 733#define MIPS_JR_RA 0x03e00008 /* instruction code for jr ra */
734#define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */ 734#define MIPS_JR_K0 0x03400008 /* instruction code for jr k0 */
735#define MIPS_ERET 0x42000018 /* instruction code for eret */ 735#define MIPS_ERET 0x42000018 /* instruction code for eret */
736 736
737/* 737/*
738 * Do a stack backtrace. 738 * Do a stack backtrace.
739 * (*printfn)() prints the output to either the system log, 739 * (*printfn)() prints the output to either the system log,
740 * the console, or both. 740 * the console, or both.
741 */ 741 */
742void 742void
743stacktrace_subr(int a0, int a1, int a2, int a3, 743stacktrace_subr(int a0, int a1, int a2, int a3,
744 u_int pc, u_int sp, u_int fp, u_int ra, 744 u_int pc, u_int sp, u_int fp, u_int ra,
745 void (*printfn)(const char*, ...)) 745 void (*printfn)(const char*, ...))
746{ 746{
747 vaddr_t va, subr; 747 vaddr_t va, subr;
748 unsigned instr, mask; 748 unsigned instr, mask;
749 InstFmt i; 749 InstFmt i;
750 int more, stksize; 750 int more, stksize;
751 unsigned int frames = 0; 751 unsigned int frames = 0;
752 int foundframesize = 0; 752 int foundframesize = 0;
753#ifdef DDB 753#ifdef DDB
754 db_expr_t diff; 754 db_expr_t diff;
755 db_sym_t sym; 755 db_sym_t sym;
756#endif 756#endif
757 757
758/* Jump here when done with a frame, to start a new one */ 758/* Jump here when done with a frame, to start a new one */
759loop: 759loop:
760 stksize = 0; 760 stksize = 0;
761 subr = 0; 761 subr = 0;
762 if (frames++ > 100) { 762 if (frames++ > 100) {
763 (*printfn)("\nstackframe count exceeded\n"); 763 (*printfn)("\nstackframe count exceeded\n");
764 /* return breaks stackframe-size heuristics with gcc -O2 */ 764 /* return breaks stackframe-size heuristics with gcc -O2 */
765 goto finish; /*XXX*/ 765 goto finish; /*XXX*/
766 } 766 }
767 767
768 /* check for bad SP: could foul up next frame */ 768 /* check for bad SP: could foul up next frame */
769 if (sp & 3 || sp < 0x80000000) { 769 if (sp & 3 || sp < 0x80000000) {
770 (*printfn)("SP 0x%x: not in kernel\n", sp); 770 (*printfn)("SP 0x%x: not in kernel\n", sp);
771 ra = 0; 771 ra = 0;
772 subr = 0; 772 subr = 0;
773 goto done; 773 goto done;
774 } 774 }
775 775
776 /* Check for bad PC */ 776 /* Check for bad PC */
777 if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) { 777 if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
778 (*printfn)("PC 0x%x: not in kernel space\n", pc); 778 (*printfn)("PC 0x%x: not in kernel space\n", pc);
779 ra = 0; 779 ra = 0;
780 goto done; 780 goto done;
781 } 781 }
782 782
783#ifdef DDB 783#ifdef DDB
784 /* 784 /*
785 * Check the kernel symbol table to see the beginning of 785 * Check the kernel symbol table to see the beginning of
786 * the current subroutine. 786 * the current subroutine.
787 */ 787 */
788 diff = 0; 788 diff = 0;
789 sym = db_search_symbol(pc, DB_STGY_ANY, &diff); 789 sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
790 if (sym != DB_SYM_NULL && diff == 0) { 790 if (sym != DB_SYM_NULL && diff == 0) {
791 /* check func(foo) __attribute__((__noreturn__)) case */ 791 /* check func(foo) __attribute__((__noreturn__)) case */
792 instr = kdbpeek(pc - 2 * sizeof(int)); 792 instr = kdbpeek(pc - 2 * sizeof(int));
793 i.word = instr; 793 i.word = instr;
794 if (i.JType.op == OP_JAL) { 794 if (i.JType.op == OP_JAL) {
795 sym = db_search_symbol(pc - sizeof(int), 795 sym = db_search_symbol(pc - sizeof(int),
796 DB_STGY_ANY, &diff); 796 DB_STGY_ANY, &diff);
797 if (sym != DB_SYM_NULL && diff != 0) 797 if (sym != DB_SYM_NULL && diff != 0)
798 diff += sizeof(int); 798 diff += sizeof(int);
799 } 799 }
800 } 800 }
801 if (sym == DB_SYM_NULL) { 801 if (sym == DB_SYM_NULL) {
802 ra = 0; 802 ra = 0;
803 goto done; 803 goto done;
804 } 804 }
805 va = pc - diff; 805 va = pc - diff;
806#else 806#else
807 /* 807 /*
808 * Find the beginning of the current subroutine by scanning backwards 808 * Find the beginning of the current subroutine by scanning backwards
809 * from the current PC for the end of the previous subroutine. 809 * from the current PC for the end of the previous subroutine.
810 *  810 *
811 * XXX This won't work well because nowadays gcc is so aggressive 811 * XXX This won't work well because nowadays gcc is so aggressive
812 * as to reorder instruction blocks for branch-predict. 812 * as to reorder instruction blocks for branch-predict.
813 * (i.e. 'jr ra' wouldn't indicate the end of subroutine) 813 * (i.e. 'jr ra' wouldn't indicate the end of subroutine)
814 */ 814 */
815 va = pc; 815 va = pc;
816 do { 816 do {
817 va -= sizeof(int); 817 va -= sizeof(int);
818 if (va <= (unsigned)verylocore) 818 if (va <= (unsigned)verylocore)
819 goto finish; 819 goto finish;
820 instr = kdbpeek(va); 820 instr = kdbpeek(va);
821 if (instr == MIPS_ERET) 821 if (instr == MIPS_ERET)
822 goto mips3_eret; 822 goto mips3_eret;
823 } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0); 823 } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
824 /* skip back over branch & delay slot */ 824 /* skip back over branch & delay slot */
825 va += sizeof(int); 825 va += sizeof(int);
826mips3_eret: 826mips3_eret:
827 va += sizeof(int); 827 va += sizeof(int);
828 /* skip over nulls which might separate .o files */ 828 /* skip over nulls which might separate .o files */
829 while ((instr = kdbpeek(va)) == 0) 829 while ((instr = kdbpeek(va)) == 0)
830 va += sizeof(int); 830 va += sizeof(int);
831#endif 831#endif
832 subr = va; 832 subr = va;
833 833
834 /* scan forwards to find stack size and any saved registers */ 834 /* scan forwards to find stack size and any saved registers */
835 stksize = 0; 835 stksize = 0;
836 more = 3; 836 more = 3;
837 mask = 0; 837 mask = 0;
838 foundframesize = 0; 838 foundframesize = 0;
839 for (va = subr; more; va += sizeof(int), 839 for (va = subr; more; va += sizeof(int),
840 more = (more == 3) ? 3 : more - 1) { 840 more = (more == 3) ? 3 : more - 1) {
841 /* stop if hit our current position */ 841 /* stop if hit our current position */
842 if (va >= pc) 842 if (va >= pc)
843 break; 843 break;
844 instr = kdbpeek(va); 844 instr = kdbpeek(va);
845 i.word = instr; 845 i.word = instr;
846 switch (i.JType.op) { 846 switch (i.JType.op) {
847 case OP_SPECIAL: 847 case OP_SPECIAL:
848 switch (i.RType.func) { 848 switch (i.RType.func) {
849 case OP_JR: 849 case OP_JR:
850 case OP_JALR: 850 case OP_JALR:
851 more = 2; /* stop after next instruction */ 851 more = 2; /* stop after next instruction */
852 break; 852 break;
853 853
854 case OP_SYSCALL: 854 case OP_SYSCALL:
855 case OP_BREAK: 855 case OP_BREAK:
856 more = 1; /* stop now */ 856 more = 1; /* stop now */
857 }; 857 };
858 break; 858 break;
859 859
860 case OP_BCOND: 860 case OP_BCOND:
861 case OP_J: 861 case OP_J:
862 case OP_JAL: 862 case OP_JAL:
863 case OP_BEQ: 863 case OP_BEQ:
864 case OP_BNE: 864 case OP_BNE:
865 case OP_BLEZ: 865 case OP_BLEZ:
866 case OP_BGTZ: 866 case OP_BGTZ:
867 more = 2; /* stop after next instruction */ 867 more = 2; /* stop after next instruction */
868 break; 868 break;
869 869
870 case OP_COP0: 870 case OP_COP0:
871 case OP_COP1: 871 case OP_COP1:
872 case OP_COP2: 872 case OP_COP2:
873 case OP_COP3: 873 case OP_COP3:
874 switch (i.RType.rs) { 874 switch (i.RType.rs) {
875 case OP_BCx: 875 case OP_BCx:
876 case OP_BCy: 876 case OP_BCy:
877 more = 2; /* stop after next instruction */ 877 more = 2; /* stop after next instruction */
878 }; 878 };
879 break; 879 break;
880 880
881 case OP_SW: 881 case OP_SW:
882 /* look for saved registers on the stack */ 882 /* look for saved registers on the stack */
883 if (i.IType.rs != 29) 883 if (i.IType.rs != 29)
884 break; 884 break;
885 /* only restore the first one */ 885 /* only restore the first one */
886 if (mask & (1 << i.IType.rt)) 886 if (mask & (1 << i.IType.rt))
887 break; 887 break;
888 mask |= (1 << i.IType.rt); 888 mask |= (1 << i.IType.rt);
889 switch (i.IType.rt) { 889 switch (i.IType.rt) {
890 case 4: /* a0 */ 890 case 4: /* a0 */
891 a0 = kdbpeek(sp + (short)i.IType.imm); 891 a0 = kdbpeek(sp + (short)i.IType.imm);
892 break; 892 break;
893 893
894 case 5: /* a1 */ 894 case 5: /* a1 */
895 a1 = kdbpeek(sp + (short)i.IType.imm); 895 a1 = kdbpeek(sp + (short)i.IType.imm);
896 break; 896 break;
897 897
898 case 6: /* a2 */ 898 case 6: /* a2 */
899 a2 = kdbpeek(sp + (short)i.IType.imm); 899 a2 = kdbpeek(sp + (short)i.IType.imm);
900 break; 900 break;
901 901
902 case 7: /* a3 */ 902 case 7: /* a3 */
903 a3 = kdbpeek(sp + (short)i.IType.imm); 903 a3 = kdbpeek(sp + (short)i.IType.imm);
904 break; 904 break;
905 905
906 case 30: /* fp */ 906 case 30: /* fp */
907 fp = kdbpeek(sp + (short)i.IType.imm); 907 fp = kdbpeek(sp + (short)i.IType.imm);
908 break; 908 break;
909 909
910 case 31: /* ra */ 910 case 31: /* ra */
911 ra = kdbpeek(sp + (short)i.IType.imm); 911 ra = kdbpeek(sp + (short)i.IType.imm);
912 } 912 }
913 break; 913 break;
914 914
915 case OP_ADDI: 915 case OP_ADDI:
916 case OP_ADDIU: 916 case OP_ADDIU:
917 /* look for stack pointer adjustment */ 917 /* look for stack pointer adjustment */
918 if (i.IType.rs != 29 || i.IType.rt != 29) 918 if (i.IType.rs != 29 || i.IType.rt != 29)
919 break; 919 break;
920 /* don't count pops for mcount */ 920 /* don't count pops for mcount */
921 if (!foundframesize) { 921 if (!foundframesize) {
922 stksize = - ((short)i.IType.imm); 922 stksize = - ((short)i.IType.imm);
923 foundframesize = 1; 923 foundframesize = 1;
924 } 924 }
925 } 925 }
926 } 926 }
927done: 927done:
928 (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n", 928 (*printfn)("%s+%x (%x,%x,%x,%x) ra %x sz %d\n",
929 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize); 929 fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
930 930
931 if (ra) { 931 if (ra) {
932 if (pc == ra && stksize == 0) 932 if (pc == ra && stksize == 0)
933 (*printfn)("stacktrace: loop!\n"); 933 (*printfn)("stacktrace: loop!\n");
934 else { 934 else {
935 pc = ra; 935 pc = ra;
936 sp += stksize; 936 sp += stksize;
937 ra = 0; 937 ra = 0;
938 goto loop; 938 goto loop;
939 } 939 }
940 } else { 940 } else {
941finish: 941finish:
942 if (curlwp) 942 if (curlwp)
943 (*printfn)("User-level: pid %d.%d\n",  943 (*printfn)("User-level: pid %d.%d\n",
944 curlwp->l_proc->p_pid, curlwp->l_lid); 944 curlwp->l_proc->p_pid, curlwp->l_lid);
945 else 945 else
946 (*printfn)("User-level: curlwp NULL\n"); 946 (*printfn)("User-level: curlwp NULL\n");
947 } 947 }
948} 948}
949 949
950/* 950/*
951 * Functions ``special'' enough to print by name 951 * Functions ``special'' enough to print by name
952 */ 952 */
953#ifdef __STDC__ 953#ifdef __STDC__
954#define Name(_fn) { (void*)_fn, # _fn } 954#define Name(_fn) { (void*)_fn, # _fn }
955#else 955#else
956#define Name(_fn) { _fn, "_fn"} 956#define Name(_fn) { _fn, "_fn"}
957#endif 957#endif
958static struct { void *addr; const char *name;} names[] = { 958static struct { void *addr; const char *name;} names[] = {
959 Name(stacktrace), 959 Name(stacktrace),
960 Name(stacktrace_subr), 960 Name(stacktrace_subr),
961 Name(main), 961 Name(main),
962 Name(trap), 962 Name(trap),
963 963
964#ifdef MIPS1 /* r2000 family (mips-I CPU) */ 964#ifdef MIPS1 /* r2000 family (mips-I CPU) */
965 Name(mips1_KernGenException), 965 Name(mips1_KernGenException),
966 Name(mips1_UserGenException), 966 Name(mips1_UserGenException),
967 Name(mips1_SystemCall), 967 Name(mips1_SystemCall),
968 Name(mips1_KernIntr), 968 Name(mips1_KernIntr),
969 Name(mips1_UserIntr), 969 Name(mips1_UserIntr),
970#endif /* MIPS1 */ 970#endif /* MIPS1 */
971 971
972/* XXX simonb: need mips32 and mips64 checks here too */ 972/* XXX simonb: need mips32 and mips64 checks here too */
973#if defined(MIPS3) && !defined(MIPS3_5900) /* r4000 family (mips-III CPU) */ 973#if defined(MIPS3) && !defined(MIPS3_5900) /* r4000 family (mips-III CPU) */
974 Name(mips3_KernGenException), 974 Name(mips3_KernGenException),
975 Name(mips3_UserGenException), 975 Name(mips3_UserGenException),
976 Name(mips3_SystemCall), 976 Name(mips3_SystemCall),
977 Name(mips3_KernIntr), 977 Name(mips3_KernIntr),
978 Name(mips3_UserIntr), 978 Name(mips3_UserIntr),
979#endif /* MIPS3 && !MIPS3_5900 */ 979#endif /* MIPS3 && !MIPS3_5900 */
980 980
981 Name(cpu_idle), 981 Name(cpu_idle),
982 Name(cpu_switchto), 982 Name(cpu_switchto),
983 {0, 0} 983 {0, 0}
984}; 984};
985 985
986/* 986/*
987 * Map a function address to a string name, if known; or a hex string. 987 * Map a function address to a string name, if known; or a hex string.
988 */ 988 */
989const char * 989const char *
990fn_name(vaddr_t addr) 990fn_name(vaddr_t addr)
991{ 991{
992 static char buf[17]; 992 static char buf[17];
993 int i = 0; 993 int i = 0;
994#ifdef DDB 994#ifdef DDB
995 db_expr_t diff; 995 db_expr_t diff;
996 db_sym_t sym; 996 db_sym_t sym;
997 const char *symname; 997 const char *symname;
998#endif 998#endif
999 999
1000#ifdef DDB 1000#ifdef DDB
1001 diff = 0; 1001 diff = 0;
1002 symname = NULL; 1002 symname = NULL;
1003 sym = db_search_symbol(addr, DB_STGY_ANY, &diff); 1003 sym = db_search_symbol(addr, DB_STGY_ANY, &diff);
1004 db_symbol_values(sym, &symname, 0); 1004 db_symbol_values(sym, &symname, 0);
1005 if (symname && diff == 0) 1005 if (symname && diff == 0)
1006 return (symname); 1006 return (symname);
1007#endif 1007#endif
1008 for (i = 0; names[i].name; i++) 1008 for (i = 0; names[i].name; i++)
1009 if (names[i].addr == (void*)addr) 1009 if (names[i].addr == (void*)addr)
1010 return (names[i].name); 1010 return (names[i].name);
1011 sprintf(buf, "%lx", addr); 1011 sprintf(buf, "%lx", addr);
1012 return (buf); 1012 return (buf);
1013} 1013}
1014 1014
1015#endif /* DEBUG */ 1015#endif /* DEBUG */
1016#endif /* DDB_TRACE */ 1016#endif /* DDB_TRACE */