1 /* $NetBSD: kgdb_machdep.c,v 1.4 2001/07/07 14:20:59 simonb Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 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 */ 81 82 #include "opt_cputype.h" /* which mips CPUs do we support? */ 83 84 #include <sys/types.h> 85 #include <sys/systm.h> 86 #include <sys/param.h> 87 #include <sys/proc.h> 88 #include <sys/user.h> 89 #include <sys/reboot.h> 90 #include <sys/kgdb.h> 91 92 #include <uvm/uvm_extern.h> 93 94 #include <mips/pte.h> 95 #include <mips/cpu.h> 96 #include <mips/locore.h> 97 #include <mips/mips_opcode.h> 98 #include <mips/reg.h> 99 #include <mips/trap.h> 100 #include <dev/cons.h> 101 102 #include <machine/db_machdep.h> 103 #include <ddb/db_access.h> 104 105 /* 106 * Is kva a valid address to access? This is used by KGDB. 107 */ 108 static int 109 kvacc(vaddr_t kva) 110 { 111 pt_entry_t *pte; 112 113 if (kva < MIPS_KSEG0_START) 114 return 0; 115 116 if (kva < MIPS_KSEG2_START) 117 return 1; 118 119 if (kva >= VM_MAX_KERNEL_ADDRESS) 120 return 0; 121 122 pte = kvtopte(kva); 123 if ((pte - Sysmap) > Sysmapsize) 124 return 0; 125 if (!mips_pg_v(pte->pt_entry)) 126 return 0; 127 128 return 1; 129 } 130 131 /* 132 * Determine if the memory at va..(va+len) is valid. 133 */ 134 int 135 kgdb_acc(va, len) 136 vaddr_t va; 137 size_t len; 138 { 139 vaddr_t last_va; 140 141 last_va = va + len + NBPG - 1; 142 va &= ~PGOFSET; 143 last_va &= ~PGOFSET; 144 145 for (; va < last_va; va += NBPG) { 146 if (kvacc(va) == 0) 147 return 0; 148 } 149 150 return (1); 151 } 152 153 /* 154 * Translate a trap number into a unix compatible signal value. 155 * (gdb only understands unix signal numbers). 156 */ 157 int 158 kgdb_signal(type) 159 int type; 160 { 161 switch (type) { 162 case T_TLB_MOD: 163 case T_TLB_MOD+T_USER: 164 case T_TLB_LD_MISS: 165 case T_TLB_ST_MISS: 166 case T_TLB_LD_MISS+T_USER: 167 case T_TLB_ST_MISS+T_USER: 168 case T_ADDR_ERR_LD: /* misaligned access */ 169 case T_ADDR_ERR_ST: /* misaligned access */ 170 case T_BUS_ERR_LD_ST: /* BERR asserted to cpu */ 171 case T_ADDR_ERR_LD+T_USER: /* misaligned or kseg access */ 172 case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ 173 case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */ 174 case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */ 175 return (SIGSEGV); 176 177 case T_BREAK: 178 case T_BREAK+T_USER: 179 return (SIGTRAP); 180 181 case T_RES_INST+T_USER: 182 case T_COP_UNUSABLE+T_USER: 183 return (SIGILL); 184 185 case T_FPE+T_USER: 186 case T_OVFLOW+T_USER: 187 return (SIGFPE); 188 189 default: 190 return (SIGEMT); 191 } 192 } 193 194 mips_reg_t kgdb_cause, kgdb_vaddr; /* set by trap() */ 195 196 /* 197 * Translate the values stored in the db_regs_t struct to the format 198 * understood by gdb. 199 */ 200 void 201 kgdb_getregs(regs, gdb_regs) 202 db_regs_t *regs; 203 kgdb_reg_t *gdb_regs; 204 { 205 struct frame *f = (struct frame *)regs; 206 207 memset(gdb_regs, 0, KGDB_NUMREGS * sizeof(kgdb_reg_t)); 208 gdb_regs[ 1] = f->f_regs[AST]; /* AT */ 209 gdb_regs[ 2] = f->f_regs[V0]; /* V0 */ 210 gdb_regs[ 3] = f->f_regs[V1]; /* V1 */ 211 gdb_regs[ 4] = f->f_regs[A0]; /* A0 */ 212 gdb_regs[ 5] = f->f_regs[A1]; /* A1 */ 213 gdb_regs[ 6] = f->f_regs[A2]; /* A2 */ 214 gdb_regs[ 7] = f->f_regs[A3]; /* A3 */ 215 gdb_regs[ 8] = f->f_regs[T0]; /* T0 */ 216 gdb_regs[ 9] = f->f_regs[T1]; /* T1 */ 217 gdb_regs[10] = f->f_regs[T2]; /* T2 */ 218 gdb_regs[11] = f->f_regs[T3]; /* T3 */ 219 gdb_regs[12] = f->f_regs[T4]; /* T4 */ 220 gdb_regs[13] = f->f_regs[T5]; /* T5 */ 221 gdb_regs[14] = f->f_regs[T6]; /* T6 */ 222 gdb_regs[15] = f->f_regs[T7]; /* T7 */ 223 gdb_regs[16] = f->f_regs[S0]; /* S0 */ 224 gdb_regs[17] = f->f_regs[S1]; /* S1 */ 225 gdb_regs[18] = f->f_regs[S2]; /* S2 */ 226 gdb_regs[19] = f->f_regs[S3]; /* S3 */ 227 gdb_regs[20] = f->f_regs[S4]; /* S4 */ 228 gdb_regs[21] = f->f_regs[S5]; /* S5 */ 229 gdb_regs[22] = f->f_regs[S6]; /* S6 */ 230 gdb_regs[23] = f->f_regs[S7]; /* S7 */ 231 gdb_regs[24] = f->f_regs[T8]; /* T8 */ 232 gdb_regs[25] = f->f_regs[T9]; /* T9 */ 233 gdb_regs[28] = f->f_regs[GP]; /* GP */ 234 gdb_regs[29] = f->f_regs[SP]; /* SP */ 235 gdb_regs[30] = f->f_regs[S8]; /* S8 */ 236 gdb_regs[31] = f->f_regs[RA]; /* RA */ 237 gdb_regs[32] = f->f_regs[SR]; /* SR */ 238 gdb_regs[33] = f->f_regs[MULLO]; /* MULLO */ 239 gdb_regs[34] = f->f_regs[MULHI]; /* MULHI */ 240 gdb_regs[35] = kgdb_vaddr; /* BAD VADDR */ 241 gdb_regs[36] = kgdb_cause; /* CAUSE */ 242 gdb_regs[37] = f->f_regs[PC]; /* PC */ 243 } 244 245 /* 246 * Reverse the above. 247 */ 248 void 249 kgdb_setregs(regs, gdb_regs) 250 db_regs_t *regs; 251 kgdb_reg_t *gdb_regs; 252 { 253 struct frame *f = (struct frame *)regs; 254 255 f->f_regs[PC] = gdb_regs[37]; /* PC */ 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(verbose) 264 int verbose; 265 { 266 verbose = 1; /* ETHAN !!! */ 267 if (kgdb_dev < 0) 268 return; 269 270 if (verbose) 271 printf("kgdb waiting..."); 272 273 asm("break"); 274 275 if (verbose) 276 printf("connected.\n"); 277 278 kgdb_debug_panic = 1; 279 } 280 281 /* 282 * Decide what to do on panic. 283 * (This is called by panic, like Debugger()) 284 */ 285 void 286 kgdb_panic() 287 { 288 if (kgdb_dev >= 0 && kgdb_debug_panic) { 289 printf("entering kgdb\n"); 290 kgdb_connect(kgdb_active == 0); 291 } 292 } 293