xref: /netbsd/sys/arch/sparc/sparc/kgdb_machdep.c (revision c4a72b64)
1 /*	$NetBSD: kgdb_machdep.c,v 1.11 2002/07/17 15:57:12 thorpej Exp $ */
2 /*-
3  * Copyright (c) 1997 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Paul Kranenburg.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *        This product includes software developed by the NetBSD
20  *        Foundation, Inc. and its contributors.
21  * 4. Neither the name of The NetBSD Foundation nor the names of its
22  *    contributors may be used to endorse or promote products derived
23  *    from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * Copyright (c) 1992, 1993
40  *	The Regents of the University of California.  All rights reserved.
41  * Copyright (c) 1995
42  * 	The President and Fellows of Harvard College. All rights reserved.
43  *
44  * This software was developed by the Computer Systems Engineering group
45  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
46  * contributed to Berkeley.
47  *
48  * All advertising materials mentioning features or use of this software
49  * must display the following acknowledgements:
50  *	This product includes software developed by the University of
51  *	California, Lawrence Berkeley Laboratory.
52  *
53  * 	This product includes software developed by Harvard University.
54  *
55  * Redistribution and use in source and binary forms, with or without
56  * modification, are permitted provided that the following conditions
57  * are met:
58  * 1. Redistributions of source code must retain the above copyright
59  *    notice, this list of conditions and the following disclaimer.
60  * 2. Redistributions in binary form must reproduce the above copyright
61  *    notice, this list of conditions and the following disclaimer in the
62  *    documentation and/or other materials provided with the distribution.
63  * 3. All advertising materials mentioning features or use of this software
64  *    must display the following acknowledgement:
65  *	This product includes software developed by the University of
66  *	California, Berkeley and its contributors.
67  * 4. Neither the name of the University nor the names of its contributors
68  *    may be used to endorse or promote products derived from this software
69  *    without specific prior written permission.
70  *
71  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
72  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
75  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
76  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
77  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
78  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
79  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
80  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
81  * SUCH DAMAGE.
82  *
83  *	@(#)kgdb_stub.c	8.1 (Berkeley) 6/11/93
84  */
85 
86 /*
87  * Machine dependent routines needed by kern/kgdb_stub.c
88  */
89 
90 #include "opt_kgdb.h"
91 #include "opt_multiprocessor.h"
92 #include "opt_sparc_arch.h"
93 
94 #ifdef KGDB
95 
96 #include <sys/param.h>
97 #include <sys/systm.h>
98 #include <sys/buf.h>
99 #include <sys/kgdb.h>
100 
101 #include <machine/ctlreg.h>
102 #include <machine/psl.h>
103 #include <machine/reg.h>
104 #include <machine/trap.h>
105 #include <machine/cpu.h>
106 
107 #include <sparc/sparc/asm.h>
108 
109 static __inline void kgdb_copy __P((char *, char *, int));
110 static __inline void kgdb_zero __P((char *, int));
111 
112 /*
113  * This little routine exists simply so that bcopy() can be debugged.
114  */
115 static __inline void
116 kgdb_copy(src, dst, len)
117 	register char *src, *dst;
118 	register int len;
119 {
120 
121 	while (--len >= 0)
122 		*dst++ = *src++;
123 }
124 
125 /* ditto for bzero */
126 static __inline void
127 kgdb_zero(ptr, len)
128 	register char *ptr;
129 	register int len;
130 {
131 	while (--len >= 0)
132 		*ptr++ = (char) 0;
133 }
134 
135 /*
136  * Deal with KGDB in a MP environment. XXX need to have "mach cpu" equiv.
137  */
138 #ifdef MULTIPROCESSOR
139 
140 #define NOCPU -1
141 
142 static int kgdb_suspend_others(void);
143 static void kgdb_resume_others(void);
144 static void kgdb_suspend(void);
145 
146 __cpu_simple_lock_t kgdb_lock;
147 int kgdb_cpu = NOCPU;
148 
149 static int
150 kgdb_suspend_others(void)
151 {
152 	int cpu_me = cpu_number();
153 	int win;
154 
155 	if (cpus == NULL)
156 		return 1;
157 
158 	__cpu_simple_lock(&kgdb_lock);
159 	if (kgdb_cpu == NOCPU)
160 		kgdb_cpu = cpu_me;
161 	win = (kgdb_cpu == cpu_me);
162 	__cpu_simple_unlock(&kgdb_lock);
163 
164 	if (win)
165 		mp_pause_cpus();
166 
167 	return win;
168 }
169 
170 static void
171 kgdb_resume_others(void)
172 {
173 
174 	mp_resume_cpus();
175 
176 	__cpu_simple_lock(&kgdb_lock);
177 	kgdb_cpu = NOCPU;
178 	__cpu_simple_unlock(&kgdb_lock);
179 }
180 
181 static void
182 kgdb_suspend()
183 {
184 
185 	while (cpuinfo.flags & CPUFLG_PAUSED)
186 		cpuinfo.cache_flush((caddr_t)&cpuinfo.flags, sizeof(cpuinfo.flags));
187 }
188 #endif
189 
190 /*
191  * Trap into kgdb to wait for debugger to connect,
192  * noting on the console why nothing else is going on.
193  */
194 void
195 kgdb_connect(verbose)
196 	int verbose;
197 {
198 
199 	if (kgdb_dev < 0)
200 		return;
201 #if NFB > 0
202 	fb_unblank();
203 #endif
204 #ifdef MULTIPROCESSOR
205 	/* While we're in the debugger, pause all other CPUs */
206 	if (!kgdb_suspend_others()) {
207 		kgdb_suspend();
208 	} else {
209 #endif
210 		if (verbose)
211 			printf("kgdb waiting...");
212 		__asm("ta %0" :: "n" (T_KGDB_EXEC));	/* trap into kgdb */
213 
214 		kgdb_debug_panic = 1;
215 
216 #ifdef MULTIPROCESSOR
217 		/* Other CPUs can continue now */
218 		kgdb_resume_others();
219 	}
220 #endif
221 }
222 
223 /*
224  * Decide what to do on panic.
225  */
226 void
227 kgdb_panic()
228 {
229 
230 	if (kgdb_dev >= 0 && kgdb_debug_panic)
231 		kgdb_connect(kgdb_active == 0);
232 }
233 
234 /*
235  * Translate a trap number into a unix compatible signal value.
236  * (gdb only understands unix signal numbers).
237  * XXX should this be done at the other end?
238  */
239 int
240 kgdb_signal(type)
241 	int type;
242 {
243 	int sigval;
244 
245 	switch (type) {
246 
247 	case T_AST:
248 		sigval = SIGINT;
249 		break;
250 
251 	case T_TEXTFAULT:
252 	case T_DATAFAULT:
253 		sigval = SIGSEGV;
254 		break;
255 
256 	case T_ALIGN:
257 		sigval = SIGBUS;
258 		break;
259 
260 	case T_ILLINST:
261 	case T_PRIVINST:
262 	case T_DIV0:
263 		sigval = SIGILL;
264 		break;
265 
266 	case T_FPE:
267 		sigval = SIGFPE;
268 		break;
269 
270 	case T_BREAKPOINT:
271 		sigval = SIGTRAP;
272 		break;
273 
274 	case T_KGDB_EXEC:
275 		sigval = SIGIOT;
276 		break;
277 
278 	default:
279 		sigval = SIGEMT;
280 		break;
281 	}
282 	return (sigval);
283 }
284 
285 /*
286  * Definitions exported from gdb (& then made prettier).
287  */
288 #define	GDB_G0		0
289 #define	GDB_O0		8
290 #define	GDB_L0		16
291 #define	GDB_I0		24
292 #define	GDB_FP0		32
293 #define	GDB_Y		64
294 #define	GDB_PSR		65
295 #define	GDB_WIM		66
296 #define	GDB_TBR		67
297 #define	GDB_PC		68
298 #define	GDB_NPC		69
299 #define	GDB_FSR		70
300 #define	GDB_CSR		71
301 
302 #define REGISTER_BYTES		(KGDB_NUMREGS * 4)
303 #define REGISTER_BYTE(n)	((n) * 4)
304 
305 /*
306  * Translate the values stored in the kernel regs struct to the format
307  * understood by gdb.
308  */
309 void
310 kgdb_getregs(regs, gdb_regs)
311 	db_regs_t *regs;
312 	kgdb_reg_t *gdb_regs;
313 {
314 	struct trapframe *tf = &regs->db_tf;
315 
316 	/* %g0..%g7 and %o0..%o7: from trapframe */
317 	gdb_regs[0] = 0;
318 	kgdb_copy((caddr_t)&tf->tf_global[1], (caddr_t)&gdb_regs[1], 15 * 4);
319 
320 	/* %l0..%l7 and %i0..%i7: from stack */
321 	kgdb_copy((caddr_t)tf->tf_out[6], (caddr_t)&gdb_regs[GDB_L0], 16 * 4);
322 
323 	/* %f0..%f31 -- fake, kernel does not use FP */
324 	kgdb_zero((caddr_t)&gdb_regs[GDB_FP0], 32 * 4);
325 
326 	/* %y, %psr, %wim, %tbr, %pc, %npc, %fsr, %csr */
327 	gdb_regs[GDB_Y] = tf->tf_y;
328 	gdb_regs[GDB_PSR] = tf->tf_psr;
329 	gdb_regs[GDB_WIM] = tf->tf_global[0];	/* input only! */
330 	gdb_regs[GDB_TBR] = 0;			/* fake */
331 	gdb_regs[GDB_PC] = tf->tf_pc;
332 	gdb_regs[GDB_NPC] = tf->tf_npc;
333 	gdb_regs[GDB_FSR] = 0;			/* fake */
334 	gdb_regs[GDB_CSR] = 0;			/* fake */
335 }
336 
337 /*
338  * Reverse the above.
339  */
340 void
341 kgdb_setregs(regs, gdb_regs)
342 	db_regs_t *regs;
343 	kgdb_reg_t *gdb_regs;
344 {
345 	struct trapframe *tf = &regs->db_tf;
346 
347 	kgdb_copy((caddr_t)&gdb_regs[1], (caddr_t)&tf->tf_global[1], 15 * 4);
348 	kgdb_copy((caddr_t)&gdb_regs[GDB_L0], (caddr_t)tf->tf_out[6], 16 * 4);
349 	tf->tf_y = gdb_regs[GDB_Y];
350 	tf->tf_psr = gdb_regs[GDB_PSR];
351 	tf->tf_pc = gdb_regs[GDB_PC];
352 	tf->tf_npc = gdb_regs[GDB_NPC];
353 }
354 
355 /*
356  * Determine if memory at [va..(va+len)] is valid.
357  */
358 int
359 kgdb_acc(va, len)
360 	vaddr_t va;
361 	size_t len;
362 {
363 	int pte;
364 	vaddr_t eva;
365 
366 	eva = round_page(va + len);
367 	va = trunc_page(va);
368 
369 	/* XXX icky: valid address but causes timeout */
370 	if (va >= (vaddr_t)0xfffff000)
371 		return (0);
372 
373 	for (; va < eva; va += NBPG) {
374 #if defined(SUN4M) || defined(SUN4D)
375 		if (CPU_HAS_SRMMU) {
376 			pte = getpte4m(va);
377 			if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE)
378 				return (0);
379 		}
380 #endif
381 #if defined(SUN4) || defined(SUN4C)
382 		if (CPU_ISSUN4C || CPU_ISSUN4) {
383 			pte = getpte4(va);
384 			if ((pte & PG_V) == 0)
385 				return (0);
386 		}
387 #endif
388 	}
389 
390 	return (1);
391 }
392 #endif
393