1 /* $NetBSD: kgdb_machdep.c,v 1.3 2002/01/06 00:35:13 dbj Exp $ */ 2 3 /* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Allen Briggs for Wasabi Systems, Inc. 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 for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * 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 WASABI SYSTEMS, INC 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 #include "opt_ddb.h" 39 40 #if defined(DDB) 41 #error "Can't build DDB and KGDB together." 42 #endif 43 44 /* 45 * Machine-dependent functions for remote KGDB. 46 */ 47 48 #include <sys/param.h> 49 #include <sys/kgdb.h> 50 #include <sys/systm.h> 51 52 #include <uvm/uvm_extern.h> 53 54 #include <machine/bat.h> 55 #include <machine/reg.h> 56 #include <machine/trap.h> 57 #include <machine/pmap.h> 58 59 /* 60 * Determine if the memory at va..(va+len) is valid. 61 */ 62 int 63 kgdb_acc(vaddr_t va, size_t len) 64 { 65 vaddr_t last_va; 66 paddr_t pa; 67 u_int msr; 68 u_int batu; 69 70 /* If translation is off, everything is fair game */ 71 asm volatile ("mfmsr %0" : "=r"(msr)); 72 if ((msr & PSL_DR) == 0) { 73 return 1; 74 } 75 76 /* Now check battable registers */ 77 asm volatile ("mfdbatu %0,0" : "=r"(batu)); 78 if (BAT_VALID_P(batu,msr) && 79 BAT_VA_MATCH_P(batu,va) && 80 (batu & BAT_PP) != BAT_PP_NONE) { 81 return 1; 82 } 83 asm volatile ("mfdbatu %0,1" : "=r"(batu)); 84 if (BAT_VALID_P(batu,msr) && 85 BAT_VA_MATCH_P(batu,va) && 86 (batu & BAT_PP) != BAT_PP_NONE) { 87 return 1; 88 } 89 asm volatile ("mfdbatu %0,2" : "=r"(batu)); 90 if (BAT_VALID_P(batu,msr) && 91 BAT_VA_MATCH_P(batu,va) && 92 (batu & BAT_PP) != BAT_PP_NONE) { 93 return 1; 94 } 95 asm volatile ("mfdbatu %0,3" : "=r"(batu)); 96 if (BAT_VALID_P(batu,msr) && 97 BAT_VA_MATCH_P(batu,va) && 98 (batu & BAT_PP) != BAT_PP_NONE) { 99 return 1; 100 } 101 102 last_va = va + len; 103 va &= ~PGOFSET; 104 last_va &= ~PGOFSET; 105 106 do { 107 /* 108 * I think this should be able to handle 109 * non-pmap_kernel() va's, too. 110 */ 111 if (!pmap_extract(pmap_kernel(), va, &pa)) 112 return 0; 113 va += PAGE_SIZE; 114 } while (va <= last_va); 115 116 return (1); 117 } 118 119 /* 120 * Translate a trap number into a unix compatible signal value. 121 * (gdb only understands unix signal numbers). Some of these are bogus 122 * and should be reviewed. 123 */ 124 int 125 kgdb_signal(type) 126 int type; 127 { 128 switch (type) { 129 #ifdef PPC_IBM4XX 130 case EXC_PIT: /* 40x - Programmable interval timer */ 131 case EXC_FIT: /* 40x - Fixed interval timer */ 132 return SIGALRM 133 134 case EXC_CII: /* 40x - Critical input interrupt */ 135 case EXC_WDOG: /* 40x - Watchdog timer */ 136 case EXC_DEBUG: /* 40x - Debug trap */ 137 return SIGTRAP; 138 139 case EXC_DTMISS: /* 40x - Instruction TLB miss */ 140 case EXC_ITMISS: /* 40x - Data TLB miss */ 141 return SIGSEGV; 142 #endif 143 144 #ifdef PPC_MPC6XX 145 case EXC_PERF: /* 604/750/7400 - Performance monitoring */ 146 case EXC_BPT: /* 604/750/7400 - Instruction breakpoint */ 147 case EXC_SMI: /* 604/750/7400 - System management interrupt */ 148 case EXC_THRM: /* 750/7400 - Thermal management interrupt */ 149 return SIGTRAP; 150 151 case EXC_IMISS: /* 603 - Instruction translation miss */ 152 case EXC_DLMISS: /* 603 - Data load translation miss */ 153 case EXC_DSMISS: /* 603 - Data store translation miss */ 154 return SIGSEGV; 155 156 case EXC_RST: /* All but IBM 4xx - Reset */ 157 return SIGURG; 158 159 case EXC_VEC: /* 7400 - Altivec unavailable */ 160 case EXC_VECAST: /* 7400 - Altivec assist */ 161 return SIGFPE; 162 #endif 163 164 case EXC_DECR: /* Decrementer interrupt */ 165 return SIGALRM; 166 167 case EXC_EXI: /* External interrupt */ 168 return SIGINT; 169 170 case EXC_PGM: /* Program interrupt */ 171 case EXC_ALI: /* Alignment */ 172 return SIGILL; 173 174 case T_BREAKPOINT: 175 case EXC_MCHK: /* Machine check */ 176 case EXC_TRC: /* Trace */ 177 return SIGTRAP; 178 179 case EXC_ISI: /* Instruction storage interrupt */ 180 case EXC_DSI: /* Data storage interrupt */ 181 return SIGSEGV; 182 183 case EXC_FPU: /* Floating point unavailable */ 184 case EXC_FPA: /* Floating-point assist */ 185 return SIGFPE; 186 187 case EXC_SC: /* System call */ 188 return SIGURG; 189 190 case EXC_RSVD: /* Reserved */ 191 case EXC_AST: /* Floating point unavailable */ 192 default: 193 return SIGEMT; 194 } 195 } 196 197 /* 198 * Translate the values stored in the kernel regs struct to the format 199 * understood by gdb. 200 */ 201 void 202 kgdb_getregs(regs, gdb_regs) 203 db_regs_t *regs; 204 kgdb_reg_t *gdb_regs; 205 { 206 memcpy(gdb_regs, regs, 32 * sizeof(unsigned long)); 207 gdb_regs[KGDB_PPC_PC_REG] = regs->iar; 208 gdb_regs[KGDB_PPC_MSR_REG] = regs->msr; 209 gdb_regs[KGDB_PPC_CR_REG] = regs->cr; 210 gdb_regs[KGDB_PPC_LR_REG] = regs->lr; 211 gdb_regs[KGDB_PPC_CTR_REG] = regs->ctr; 212 gdb_regs[KGDB_PPC_XER_REG] = regs->xer; 213 } 214 215 /* 216 * Reverse the above. 217 */ 218 void 219 kgdb_setregs(regs, gdb_regs) 220 db_regs_t *regs; 221 kgdb_reg_t *gdb_regs; 222 { 223 regs->xer = gdb_regs[KGDB_PPC_XER_REG]; 224 regs->ctr = gdb_regs[KGDB_PPC_CTR_REG]; 225 regs->lr = gdb_regs[KGDB_PPC_LR_REG]; 226 regs->cr = gdb_regs[KGDB_PPC_CR_REG]; 227 regs->msr = gdb_regs[KGDB_PPC_MSR_REG]; 228 regs->iar = gdb_regs[KGDB_PPC_PC_REG]; 229 memcpy(regs, gdb_regs, 32 * sizeof(unsigned long)); 230 } 231 232 /* 233 * Trap into kgdb to wait for debugger to connect, 234 * noting on the console why nothing else is going on. 235 */ 236 void 237 kgdb_connect(verbose) 238 int verbose; 239 { 240 241 if (kgdb_dev < 0) 242 return; 243 244 if (verbose) 245 printf("kgdb waiting..."); 246 247 asm volatile(BKPT_ASM); 248 249 if (verbose && kgdb_active) { 250 printf("kgdb connected.\n"); 251 } 252 253 kgdb_debug_panic = 1; 254 } 255 256 /* 257 * Decide what to do on panic. 258 * (This is called by panic, like Debugger()) 259 */ 260 void 261 kgdb_panic() 262 { 263 if (kgdb_dev >= 0 && kgdb_debug_panic) { 264 printf("entering kgdb\n"); 265 kgdb_connect(kgdb_active == 0); 266 } 267 } 268