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