Home | History | Annotate | Line # | Download | only in sh3
kgdb_machdep.c revision 1.7
      1 /*	$NetBSD: kgdb_machdep.c,v 1.7 2002/04/28 17:10:38 uch Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997, 2002 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  * Modified for NetBSD/sh3 by UCHIYAMA Yasushi.
     81  */
     82 
     83 #include <sys/types.h>
     84 #include <sys/systm.h>
     85 #include <sys/param.h>
     86 #include <sys/proc.h>
     87 #include <sys/user.h>
     88 #include <sys/reboot.h>
     89 #include <sys/kgdb.h>
     90 
     91 #include <uvm/uvm_extern.h>
     92 
     93 #include <sh3/cpu.h>
     94 
     95 #include <machine/db_machdep.h>
     96 #include <ddb/db_access.h>
     97 
     98 /*
     99  * Is kva a valid address to access?  This is used by KGDB.
    100  */
    101 static int
    102 kvacc(vaddr_t kva)
    103 {
    104 	pt_entry_t *pte;
    105 
    106 	if (kva < SH3_P1SEG_BASE)
    107 		return (0);
    108 
    109 	if (kva < SH3_P2SEG_BASE)
    110 		return (1);
    111 
    112 	if (kva >= VM_MAX_KERNEL_ADDRESS)
    113 		return (0);
    114 
    115 	/* check kva is kernel virtual. */
    116 	if ((kva < VM_MIN_KERNEL_ADDRESS) ||
    117 	    (kva >= VM_MAX_KERNEL_ADDRESS))
    118 		return (0);
    119 
    120 	/* check page which related kva is valid. */
    121 	pte = kvtopte(kva);
    122 	if (!(*pte & PG_V))
    123 		return (0);
    124 
    125 	return (1);
    126 }
    127 
    128 /*
    129  * Determine if the memory at va..(va+len) is valid.
    130  */
    131 int
    132 kgdb_acc(vaddr_t va, size_t len)
    133 {
    134 	vaddr_t last_va;
    135 
    136 	last_va = va + len + NBPG - 1;
    137 	va  &= ~PGOFSET;
    138 	last_va &= ~PGOFSET;
    139 
    140 	for (; va < last_va; va += NBPG) {
    141 		if (kvacc(va) == 0)
    142 			return 0;
    143 	}
    144 
    145 	return (1);
    146 }
    147 
    148 /*
    149  * Translate a trap number into a unix compatible signal value.
    150  * (gdb only understands unix signal numbers).
    151  */
    152 int
    153 kgdb_signal(int type)
    154 {
    155 
    156 	switch (type) {
    157 	case T_TLBMISSR:
    158 	case T_TLBMISSW:
    159 	case T_INITPAGEWR:
    160 	case T_TLBPRIVR:
    161 	case T_TLBPRIVW:
    162 	case T_ADDRESSERRR:
    163 	case T_ADDRESSERRW:
    164 	case T_TLBMISSR+T_USER:
    165 	case T_TLBMISSW+T_USER:
    166 	case T_INITPAGEWR+T_USER:
    167 	case T_TLBPRIVR+T_USER:
    168 	case T_TLBPRIVW+T_USER:
    169 	case T_ADDRESSERRR+T_USER:
    170 	case T_ADDRESSERRW+T_USER:
    171 		return (SIGSEGV);
    172 
    173 	case T_TRAP:
    174 	case T_TRAP+T_USER:
    175 	case T_USERBREAK:
    176 	case T_USERBREAK+T_USER:
    177 		return (SIGTRAP);
    178 
    179 	case T_INVALIDISN:
    180 	case T_INVALIDSLOT:
    181 	case T_INVALIDISN+T_USER:
    182 	case T_INVALIDSLOT+T_USER:
    183 		return (SIGILL);
    184 
    185 	default:
    186 		return (SIGEMT);
    187 	}
    188 }
    189 
    190 /*
    191  * Translate the values stored in the db_regs_t struct to the format
    192  * understood by gdb. (gdb-5.1.1/gdb/config/sh/tm-sh.h)
    193  */
    194 void
    195 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    196 {
    197 	u_int32_t r;
    198 
    199 	memset(gdb_regs, 0, KGDB_NUMREGS * sizeof(kgdb_reg_t));
    200 	gdb_regs[ 0] = regs->tf_r0;
    201 	gdb_regs[ 1] = regs->tf_r1;
    202 	gdb_regs[ 2] = regs->tf_r2;
    203 	gdb_regs[ 3] = regs->tf_r3;
    204 	gdb_regs[ 4] = regs->tf_r4;
    205 	gdb_regs[ 5] = regs->tf_r5;
    206 	gdb_regs[ 6] = regs->tf_r6;
    207 	gdb_regs[ 7] = regs->tf_r7;
    208 	gdb_regs[ 8] = regs->tf_r8;
    209 	gdb_regs[ 9] = regs->tf_r9;
    210 	gdb_regs[10] = regs->tf_r10;
    211 	gdb_regs[11] = regs->tf_r11;
    212 	gdb_regs[12] = regs->tf_r12;
    213 	gdb_regs[13] = regs->tf_r13;
    214 	gdb_regs[14] = regs->tf_r14;
    215 	gdb_regs[15] = regs->tf_r15;
    216 	gdb_regs[16] = regs->tf_spc;
    217 	gdb_regs[17] = regs->tf_pr;
    218 	__asm__ __volatile__("stc vbr, %0" : "=r"(r));
    219 	gdb_regs[19] = r;
    220 	gdb_regs[20] = regs->tf_mach;
    221 	gdb_regs[21] = regs->tf_macl;
    222 	gdb_regs[22] = regs->tf_ssr;
    223 
    224 	/* How treat register bank 1 ? */
    225 }
    226 
    227 /*
    228  * Reverse the above.
    229  */
    230 void
    231 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
    232 {
    233 
    234 	regs->tf_r0	= gdb_regs[ 0];
    235 	regs->tf_r1	= gdb_regs[ 1];
    236 	regs->tf_r2	= gdb_regs[ 2];
    237 	regs->tf_r3	= gdb_regs[ 3];
    238 	regs->tf_r4	= gdb_regs[ 4];
    239 	regs->tf_r5	= gdb_regs[ 5];
    240 	regs->tf_r6	= gdb_regs[ 6];
    241 	regs->tf_r7	= gdb_regs[ 7];
    242 	regs->tf_r8	= gdb_regs[ 8];
    243 	regs->tf_r9	= gdb_regs[ 9];
    244 	regs->tf_r10	= gdb_regs[10];
    245 	regs->tf_r11	= gdb_regs[11];
    246 	regs->tf_r12	= gdb_regs[12];
    247 	regs->tf_r13	= gdb_regs[13];
    248 	regs->tf_r14	= gdb_regs[14];
    249 	regs->tf_r15	= gdb_regs[15];
    250 	regs->tf_spc	= gdb_regs[16];
    251 	regs->tf_pr	= gdb_regs[17];
    252 	__asm__ __volatile__("ldc %0, vbr" :: "r"(gdb_regs[19]));
    253 	regs->tf_mach	= gdb_regs[20];
    254 	regs->tf_macl	= gdb_regs[21];
    255 	regs->tf_ssr	= gdb_regs[22];
    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(int verbose)
    264 {
    265 
    266 	if (kgdb_dev < 0) {
    267 		printf("kgdb_dev=%d\n", kgdb_dev);
    268 		return;
    269 	}
    270 
    271 	if (verbose)
    272 		printf("kgdb waiting...");
    273 
    274 	__asm__ __volatile__("trapa #0xc3");
    275 
    276 	if (verbose)
    277 		printf("connected.\n");
    278 
    279 	kgdb_debug_panic = 1;
    280 }
    281 
    282 /*
    283  * Decide what to do on panic.
    284  * (This is called by panic, like Debugger())
    285  */
    286 void
    287 kgdb_panic()
    288 {
    289 
    290 	if (kgdb_dev >= 0 && kgdb_debug_panic) {
    291 		printf("entering kgdb\n");
    292 		kgdb_connect(kgdb_active == 0);
    293 	}
    294 }
    295