xref: /netbsd/sys/arch/mips/mips/kgdb_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: kgdb_machdep.c,v 1.4 2001/07/07 14:20:59 simonb Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1996 Matthias Pfaller.
42  * All rights reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *	This product includes software developed by Matthias Pfaller.
55  * 4. The name of the author may not be used to endorse or promote products
56  *    derived from this software without specific prior written permission
57  *
58  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68  */
69 
70 #include "opt_ddb.h"
71 
72 #if defined(DDB)
73 #error "Can't build DDB and KGDB together."
74 #endif
75 
76 /*
77  * Machine-dependent functions for remote KGDB.  Originally written
78  * for NetBSD/pc532 by Matthias Pfaller.  Modified for NetBSD/i386
79  * by Jason R. Thorpe.  Modified for NetBSD/mips by Ethan Solomita
80  */
81 
82 #include "opt_cputype.h"	/* which mips CPUs do we support? */
83 
84 #include <sys/types.h>
85 #include <sys/systm.h>
86 #include <sys/param.h>
87 #include <sys/proc.h>
88 #include <sys/user.h>
89 #include <sys/reboot.h>
90 #include <sys/kgdb.h>
91 
92 #include <uvm/uvm_extern.h>
93 
94 #include <mips/pte.h>
95 #include <mips/cpu.h>
96 #include <mips/locore.h>
97 #include <mips/mips_opcode.h>
98 #include <mips/reg.h>
99 #include <mips/trap.h>
100 #include <dev/cons.h>
101 
102 #include <machine/db_machdep.h>
103 #include <ddb/db_access.h>
104 
105 /*
106  * Is kva a valid address to access?  This is used by KGDB.
107  */
108 static int
109 kvacc(vaddr_t kva)
110 {
111 	pt_entry_t *pte;
112 
113 	if (kva < MIPS_KSEG0_START)
114 		return 0;
115 
116 	if (kva < MIPS_KSEG2_START)
117 		return 1;
118 
119 	if (kva >= VM_MAX_KERNEL_ADDRESS)
120 		return 0;
121 
122 	pte = kvtopte(kva);
123 	if ((pte - Sysmap) > Sysmapsize)
124 		return 0;
125 	if (!mips_pg_v(pte->pt_entry))
126 		return 0;
127 
128 	return 1;
129 }
130 
131 /*
132  * Determine if the memory at va..(va+len) is valid.
133  */
134 int
135 kgdb_acc(va, len)
136 	vaddr_t va;
137 	size_t len;
138 {
139 	vaddr_t last_va;
140 
141 	last_va = va + len + NBPG - 1;
142 	va  &= ~PGOFSET;
143 	last_va &= ~PGOFSET;
144 
145 	for (; va < last_va; va += NBPG) {
146 		if (kvacc(va) == 0)
147 			return 0;
148 	}
149 
150 	return (1);
151 }
152 
153 /*
154  * Translate a trap number into a unix compatible signal value.
155  * (gdb only understands unix signal numbers).
156  */
157 int
158 kgdb_signal(type)
159 	int type;
160 {
161 	switch (type) {
162 	case T_TLB_MOD:
163 	case T_TLB_MOD+T_USER:
164 	case T_TLB_LD_MISS:
165 	case T_TLB_ST_MISS:
166 	case T_TLB_LD_MISS+T_USER:
167 	case T_TLB_ST_MISS+T_USER:
168 	case T_ADDR_ERR_LD:	/* misaligned access */
169 	case T_ADDR_ERR_ST:	/* misaligned access */
170 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
171 	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
172 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
173 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
174 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
175 		return (SIGSEGV);
176 
177 	case T_BREAK:
178 	case T_BREAK+T_USER:
179 		return (SIGTRAP);
180 
181 	case T_RES_INST+T_USER:
182 	case T_COP_UNUSABLE+T_USER:
183 		return (SIGILL);
184 
185 	case T_FPE+T_USER:
186 	case T_OVFLOW+T_USER:
187 		return (SIGFPE);
188 
189 	default:
190 		return (SIGEMT);
191 	}
192 }
193 
194 mips_reg_t kgdb_cause, kgdb_vaddr; /* set by trap() */
195 
196 /*
197  * Translate the values stored in the db_regs_t struct to the format
198  * understood by gdb.
199  */
200 void
201 kgdb_getregs(regs, gdb_regs)
202 	db_regs_t *regs;
203 	kgdb_reg_t *gdb_regs;
204 {
205 	struct frame *f = (struct frame *)regs;
206 
207 	memset(gdb_regs, 0, KGDB_NUMREGS * sizeof(kgdb_reg_t));
208 	gdb_regs[ 1] = f->f_regs[AST];     /* AT */
209 	gdb_regs[ 2] = f->f_regs[V0];      /* V0 */
210 	gdb_regs[ 3] = f->f_regs[V1];      /* V1 */
211 	gdb_regs[ 4] = f->f_regs[A0];      /* A0 */
212 	gdb_regs[ 5] = f->f_regs[A1];      /* A1 */
213 	gdb_regs[ 6] = f->f_regs[A2];      /* A2 */
214 	gdb_regs[ 7] = f->f_regs[A3];      /* A3 */
215 	gdb_regs[ 8] = f->f_regs[T0];      /* T0 */
216 	gdb_regs[ 9] = f->f_regs[T1];      /* T1 */
217 	gdb_regs[10] = f->f_regs[T2];      /* T2 */
218 	gdb_regs[11] = f->f_regs[T3];	   /* T3 */
219 	gdb_regs[12] = f->f_regs[T4];	   /* T4 */
220 	gdb_regs[13] = f->f_regs[T5];	   /* T5 */
221 	gdb_regs[14] = f->f_regs[T6];	   /* T6 */
222 	gdb_regs[15] = f->f_regs[T7];	   /* T7 */
223 	gdb_regs[16] = f->f_regs[S0];      /* S0 */
224 	gdb_regs[17] = f->f_regs[S1];      /* S1 */
225 	gdb_regs[18] = f->f_regs[S2];      /* S2 */
226 	gdb_regs[19] = f->f_regs[S3];      /* S3 */
227 	gdb_regs[20] = f->f_regs[S4];      /* S4 */
228 	gdb_regs[21] = f->f_regs[S5];      /* S5 */
229 	gdb_regs[22] = f->f_regs[S6];      /* S6 */
230 	gdb_regs[23] = f->f_regs[S7];      /* S7 */
231 	gdb_regs[24] = f->f_regs[T8];	   /* T8 */
232 	gdb_regs[25] = f->f_regs[T9];	   /* T9 */
233 	gdb_regs[28] = f->f_regs[GP];      /* GP */
234 	gdb_regs[29] = f->f_regs[SP];      /* SP */
235 	gdb_regs[30] = f->f_regs[S8];      /* S8 */
236 	gdb_regs[31] = f->f_regs[RA];	   /* RA */
237 	gdb_regs[32] = f->f_regs[SR];	   /* SR */
238 	gdb_regs[33] = f->f_regs[MULLO];   /* MULLO */
239 	gdb_regs[34] = f->f_regs[MULHI];   /* MULHI */
240 	gdb_regs[35] = kgdb_vaddr;         /* BAD VADDR */
241 	gdb_regs[36] = kgdb_cause;         /* CAUSE */
242 	gdb_regs[37] = f->f_regs[PC];	   /* PC */
243 }
244 
245 /*
246  * Reverse the above.
247  */
248 void
249 kgdb_setregs(regs, gdb_regs)
250 	db_regs_t *regs;
251 	kgdb_reg_t *gdb_regs;
252 {
253 	struct frame *f = (struct frame *)regs;
254 
255 	f->f_regs[PC] = gdb_regs[37];   /* PC */
256 }
257 
258 /*
259  * Trap into kgdb to wait for debugger to connect,
260  * noting on the console why nothing else is going on.
261  */
262 void
263 kgdb_connect(verbose)
264 	int verbose;
265 {
266 	verbose = 1; /* ETHAN !!! */
267 	if (kgdb_dev < 0)
268 		return;
269 
270 	if (verbose)
271 		printf("kgdb waiting...");
272 
273 	asm("break");
274 
275 	if (verbose)
276 		printf("connected.\n");
277 
278 	kgdb_debug_panic = 1;
279 }
280 
281 /*
282  * Decide what to do on panic.
283  * (This is called by panic, like Debugger())
284  */
285 void
286 kgdb_panic()
287 {
288 	if (kgdb_dev >= 0 && kgdb_debug_panic) {
289 		printf("entering kgdb\n");
290 		kgdb_connect(kgdb_active == 0);
291 	}
292 }
293