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