Home | History | Annotate | Line # | Download | only in sparc64
kgdb_machdep.c revision 1.3
      1 /*	$NetBSD: kgdb_machdep.c,v 1.3 2003/07/15 03:36:09 lukem 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 <sys/cdefs.h>
     91 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.3 2003/07/15 03:36:09 lukem Exp $");
     92 
     93 #include "opt_kgdb.h"
     94 #include "opt_multiprocessor.h"
     95 #include "opt_sparc_arch.h"
     96 
     97 #ifdef KGDB
     98 
     99 #include <sys/param.h>
    100 #include <sys/systm.h>
    101 #include <sys/buf.h>
    102 #include <sys/kgdb.h>
    103 
    104 #include <machine/ctlreg.h>
    105 #include <machine/psl.h>
    106 #include <machine/reg.h>
    107 #include <machine/trap.h>
    108 #include <machine/cpu.h>
    109 
    110 #include <sparc/sparc/asm.h>
    111 
    112 extern int64_t pseg_get __P((struct pmap *, vaddr_t));
    113 
    114 static __inline void kgdb_copy __P((char *, char *, int));
    115 static __inline void kgdb_zero __P((char *, int));
    116 
    117 /*
    118  * This little routine exists simply so that bcopy() can be debugged.
    119  */
    120 static __inline void
    121 kgdb_copy(src, dst, len)
    122 	register char *src, *dst;
    123 	register int len;
    124 {
    125 
    126 	while (--len >= 0)
    127 		*dst++ = *src++;
    128 }
    129 
    130 /* ditto for bzero */
    131 static __inline void
    132 kgdb_zero(ptr, len)
    133 	register char *ptr;
    134 	register int len;
    135 {
    136 	while (--len >= 0)
    137 		*ptr++ = (char) 0;
    138 }
    139 
    140 /*
    141  * Deal with KGDB in a MP environment. XXX need to have "mach cpu" equiv.
    142  */
    143 #ifdef MULTIPROCESSOR
    144 
    145 #define NOCPU -1
    146 
    147 static int kgdb_suspend_others(void);
    148 static void kgdb_resume_others(void);
    149 static void kgdb_suspend(void);
    150 
    151 __cpu_simple_lock_t kgdb_lock;
    152 int kgdb_cpu = NOCPU;
    153 
    154 static int
    155 kgdb_suspend_others(void)
    156 {
    157 	int cpu_me = cpu_number();
    158 	int win;
    159 
    160 	if (cpus == NULL)
    161 		return 1;
    162 
    163 	__cpu_simple_lock(&kgdb_lock);
    164 	if (kgdb_cpu == NOCPU)
    165 		kgdb_cpu = cpu_me;
    166 	win = (kgdb_cpu == cpu_me);
    167 	__cpu_simple_unlock(&kgdb_lock);
    168 
    169 	if (win)
    170 		mp_pause_cpus();
    171 
    172 	return win;
    173 }
    174 
    175 static void
    176 kgdb_resume_others(void)
    177 {
    178 
    179 	mp_resume_cpus();
    180 
    181 	__cpu_simple_lock(&kgdb_lock);
    182 	kgdb_cpu = NOCPU;
    183 	__cpu_simple_unlock(&kgdb_lock);
    184 }
    185 
    186 static void
    187 kgdb_suspend()
    188 {
    189 
    190 	while (cpuinfo.flags & CPUFLG_PAUSED)
    191 		cpuinfo.cache_flush((caddr_t)&cpuinfo.flags, sizeof(cpuinfo.flags));
    192 }
    193 #endif
    194 
    195 /*
    196  * Trap into kgdb to wait for debugger to connect,
    197  * noting on the console why nothing else is going on.
    198  */
    199 void
    200 kgdb_connect(verbose)
    201 	int verbose;
    202 {
    203 
    204 	if (kgdb_dev < 0)
    205 		return;
    206 #if NFB > 0
    207 	fb_unblank();
    208 #endif
    209 #ifdef MULTIPROCESSOR
    210 	/* While we're in the debugger, pause all other CPUs */
    211 	if (!kgdb_suspend_others()) {
    212 		kgdb_suspend();
    213 	} else {
    214 #endif
    215 		if (verbose)
    216 			printf("kgdb waiting...");
    217 		__asm("ta %0" :: "n" (T_KGDB_EXEC));	/* trap into kgdb */
    218 
    219 		kgdb_debug_panic = 1;
    220 
    221 #ifdef MULTIPROCESSOR
    222 		/* Other CPUs can continue now */
    223 		kgdb_resume_others();
    224 	}
    225 #endif
    226 }
    227 
    228 /*
    229  * Decide what to do on panic.
    230  */
    231 void
    232 kgdb_panic()
    233 {
    234 
    235 	if (kgdb_dev >= 0 && kgdb_debug_panic)
    236 		kgdb_connect(kgdb_active == 0);
    237 }
    238 
    239 /*
    240  * Translate a trap number into a unix compatible signal value.
    241  * (gdb only understands unix signal numbers).
    242  * XXX should this be done at the other end?
    243  */
    244 int
    245 kgdb_signal(type)
    246 	int type;
    247 {
    248 	int sigval;
    249 
    250 	switch (type) {
    251 
    252 	case T_AST:
    253 		sigval = SIGINT;
    254 		break;
    255 
    256 	case T_TEXTFAULT:
    257 	case T_DATAFAULT:
    258 		sigval = SIGSEGV;
    259 		break;
    260 
    261 	case T_ALIGN:
    262 		sigval = SIGBUS;
    263 		break;
    264 
    265 	case T_ILLINST:
    266 	case T_PRIVINST:
    267 	case T_DIV0:
    268 		sigval = SIGILL;
    269 		break;
    270 
    271 	case T_FP_IEEE_754:
    272 	case T_FP_OTHER:
    273 		sigval = SIGFPE;
    274 		break;
    275 
    276 	case T_BREAKPOINT:
    277 		sigval = SIGTRAP;
    278 		break;
    279 
    280 	case T_KGDB_EXEC:
    281 		sigval = SIGIOT;
    282 		break;
    283 
    284 	default:
    285 		sigval = SIGEMT;
    286 		break;
    287 	}
    288 	return (sigval);
    289 }
    290 
    291 /*
    292  * Definitions exported from gdb (& then made prettier).
    293  * (see gnu/dist/toolchain/gdb/config/sparc/tm-sp64.h)
    294  */
    295 #define	GDB_G0		0
    296 #define	GDB_O0		8
    297 #define	GDB_L0		16
    298 #define	GDB_I0		24
    299 #define	GDB_FP0		32
    300 #define GDB_PC		80
    301 #define GDB_NPC		81
    302 #define GDB_CCR		82
    303 #define	GDB_FSR		83
    304 #define	GDB_FPRS	84
    305 #define	GDB_Y		85
    306 #define	GDB_ASI		86
    307 
    308 #define REGISTER_BYTES		(KGDB_NUMREGS * 8)
    309 #define REGISTER_BYTE(n)	((n) * 8)
    310 
    311 /*
    312  * Translate the values stored in the kernel regs struct to the format
    313  * understood by gdb.
    314  */
    315 void
    316 kgdb_getregs(regs, gdb_regs)
    317 	db_regs_t *regs;
    318 	kgdb_reg_t *gdb_regs;
    319 {
    320 	struct trapframe64 *tf = &regs->ddb_tf;
    321 
    322 	/* %g0..%g7 and %o0..%o7: from trapframe */
    323 	gdb_regs[0] = 0;
    324 	kgdb_copy((caddr_t)&tf->tf_global[1], (caddr_t)&gdb_regs[1], 15 * 8);
    325 
    326 	/* %l0..%l7 and %i0..%i7: from stack */
    327 	kgdb_copy((caddr_t)(long)tf->tf_out[6], (caddr_t)&gdb_regs[GDB_L0], 16 * 8);
    328 
    329 	/* %f0..%f31 -- fake, kernel does not use FP */
    330 	kgdb_zero((caddr_t)&gdb_regs[GDB_FP0], 32 * 8);
    331 
    332 	/* %y, %psr, %wim, %tbr, %pc, %npc, %fsr, %csr */
    333 	gdb_regs[GDB_PC] = tf->tf_pc;
    334 	gdb_regs[GDB_NPC] = tf->tf_npc;
    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 trapframe64 *tf = &regs->ddb_tf;
    346 
    347 	kgdb_copy((caddr_t)&gdb_regs[1], (caddr_t)&tf->tf_global[1], 15 * 8);
    348 	kgdb_copy((caddr_t)&gdb_regs[GDB_L0], (caddr_t)(long)tf->tf_out[6], 16 * 8);
    349 	tf->tf_pc = gdb_regs[GDB_PC];
    350 	tf->tf_npc = gdb_regs[GDB_NPC];
    351 }
    352 
    353 /*
    354  * Determine if memory at [va..(va+len)] is valid.
    355  */
    356 int
    357 kgdb_acc(va, len)
    358 	vaddr_t va;
    359 	size_t len;
    360 {
    361 	int64_t data;
    362 	vaddr_t eva;
    363 	struct pmap *pm = &kernel_pmap_;
    364 
    365 	eva = round_page(va + len);
    366 	va = trunc_page(va);
    367 
    368 	simple_lock(&pm->pm_lock);
    369 	for (; va < eva; va += PAGE_SIZE) {
    370 		data = pseg_get(pm, va);
    371 		if ((data & TLB_V) == 0) {
    372 			simple_unlock(&pm->pm_lock);
    373 			return 0;
    374 		}
    375 	}
    376 	simple_unlock(&pm->pm_lock);
    377 
    378 	return (1);
    379 }
    380 #endif
    381