1 /* $NetBSD: kgdb_machdep.c,v 1.22 2010/03/02 21:53:20 matt 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 <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.22 2010/03/02 21:53:20 matt Exp $"); 40 41 #include "opt_ddb.h" 42 43 /* 44 * Machine-dependent functions for remote KGDB. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/kgdb.h> 49 #include <sys/systm.h> 50 51 #include <uvm/uvm_extern.h> 52 53 #include <machine/reg.h> 54 #include <machine/trap.h> 55 #include <machine/pmap.h> 56 57 #include <powerpc/spr.h> 58 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE) 59 #include <powerpc/oea/spr.h> 60 #include <powerpc/oea/bat.h> 61 62 #elif defined (PPC_OEA64) 63 #include <powerpc/oea/spr.h> 64 65 #elif defined (PPC_IBM4XX) 66 #include <powerpc/booke/spr.h> 67 68 #elif defined (PPC_BOOKE) 69 #include <powerpc/booke/spr.h> 70 71 #else 72 #error unknown architecture 73 #endif 74 75 /* 76 * Determine if the memory at va..(va+len) is valid. 77 */ 78 int 79 kgdb_acc(vaddr_t va, size_t len) 80 { 81 vaddr_t last_va; 82 paddr_t pa; 83 u_int msr; 84 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE) 85 u_int batu, batl; 86 #endif 87 88 /* If translation is off, everything is fair game */ 89 __asm volatile ("mfmsr %0" : "=r"(msr)); 90 if ((msr & PSL_DR) == 0) { 91 return 1; 92 } 93 94 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE) 95 /* Now check battable registers */ 96 #ifdef PPC_OEA601 97 if ((mfpvr() >> 16) == MPC601) { 98 __asm volatile ("mfibatl %0,0" : "=r"(batl)); 99 __asm volatile ("mfibatu %0,0" : "=r"(batu)); 100 if (BAT601_VALID_P(batl) && 101 BAT601_VA_MATCH_P(batu,batl,va)) 102 return 1; 103 __asm volatile ("mfibatl %0,1" : "=r"(batl)); 104 __asm volatile ("mfibatu %0,1" : "=r"(batu)); 105 if (BAT601_VALID_P(batl) && 106 BAT601_VA_MATCH_P(batu,batl,va)) 107 return 1; 108 __asm volatile ("mfibatl %0,2" : "=r"(batl)); 109 __asm volatile ("mfibatu %0,2" : "=r"(batu)); 110 if (BAT601_VALID_P(batl) && 111 BAT601_VA_MATCH_P(batu,batl,va)) 112 return 1; 113 __asm volatile ("mfibatl %0,3" : "=r"(batl)); 114 __asm volatile ("mfibatu %0,3" : "=r"(batu)); 115 if (BAT601_VALID_P(batl) && 116 BAT601_VA_MATCH_P(batu,batl,va)) 117 return 1; 118 } else { 119 #endif /* PPC_OEA601 */ 120 __asm volatile ("mfdbatu %0,0" : "=r"(batu)); 121 if (BAT_VALID_P(batu,msr) && 122 BAT_VA_MATCH_P(batu,va) && 123 (batu & BAT_PP) != BAT_PP_NONE) { 124 return 1; 125 } 126 __asm volatile ("mfdbatu %0,1" : "=r"(batu)); 127 if (BAT_VALID_P(batu,msr) && 128 BAT_VA_MATCH_P(batu,va) && 129 (batu & BAT_PP) != BAT_PP_NONE) { 130 return 1; 131 } 132 __asm volatile ("mfdbatu %0,2" : "=r"(batu)); 133 if (BAT_VALID_P(batu,msr) && 134 BAT_VA_MATCH_P(batu,va) && 135 (batu & BAT_PP) != BAT_PP_NONE) { 136 return 1; 137 } 138 __asm volatile ("mfdbatu %0,3" : "=r"(batu)); 139 if (BAT_VALID_P(batu,msr) && 140 BAT_VA_MATCH_P(batu,va) && 141 (batu & BAT_PP) != BAT_PP_NONE) { 142 return 1; 143 #ifdef PPC_OEA601 144 } 145 #endif 146 } 147 #endif /* PPC_OEA || PPC_OEA601 || PPC_OEA64_BRIDGE */ 148 149 #if defined(PPC_IBM4XX) 150 /* Is it (supposed to be) TLB-reserved mapping? */ 151 if (va < VM_MIN_KERNEL_ADDRESS || va > VM_MAX_KERNEL_ADDRESS) 152 return (1); 153 #endif 154 155 last_va = va + len; 156 va &= ~PGOFSET; 157 last_va &= ~PGOFSET; 158 159 do { 160 /* 161 * I think this should be able to handle 162 * non-pmap_kernel() va's, too. 163 */ 164 if (!pmap_extract(pmap_kernel(), va, &pa)) 165 return 0; 166 va += PAGE_SIZE; 167 } while (va <= last_va); 168 169 return (1); 170 } 171 172 /* 173 * Translate a trap number into a unix compatible signal value. 174 * (gdb only understands unix signal numbers). Some of these are bogus 175 * and should be reviewed. 176 */ 177 int 178 kgdb_signal(int type) 179 { 180 switch (type) { 181 #if defined (PPC_IBM4XX) || defined (PPC_BOOKE) 182 case EXC_PIT: /* 40x - Programmable interval timer */ 183 case EXC_FIT: /* 40x - Fixed interval timer */ 184 return SIGALRM; 185 186 case EXC_CII: /* 40x - Critical input interrupt */ 187 case EXC_WDOG: /* 40x - Watchdog timer */ 188 case EXC_DEBUG: /* 40x - Debug trap */ 189 return SIGTRAP; 190 191 case EXC_DTMISS: /* 40x - Instruction TLB miss */ 192 case EXC_ITMISS: /* 40x - Data TLB miss */ 193 return SIGSEGV; 194 #endif 195 196 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE) 197 case EXC_PERF: /* 604/750/7400 - Performance monitoring */ 198 case EXC_BPT: /* 604/750/7400 - Instruction breakpoint */ 199 case EXC_SMI: /* 604/750/7400 - System management interrupt */ 200 case EXC_THRM: /* 750/7400 - Thermal management interrupt */ 201 return SIGTRAP; 202 203 case EXC_IMISS: /* 603 - Instruction translation miss */ 204 case EXC_DLMISS: /* 603 - Data load translation miss */ 205 case EXC_DSMISS: /* 603 - Data store translation miss */ 206 return SIGSEGV; 207 208 case EXC_RST: /* All but IBM 4xx - Reset */ 209 return SIGURG; 210 211 case EXC_VEC: /* 7400 - Altivec unavailable */ 212 case EXC_VECAST: /* 7400 - Altivec assist */ 213 return SIGFPE; 214 #endif 215 216 case EXC_DECR: /* Decrementer interrupt */ 217 return SIGALRM; 218 219 case EXC_EXI: /* External interrupt */ 220 return SIGINT; 221 222 case EXC_PGM: /* Program interrupt */ 223 case EXC_ALI: /* Alignment */ 224 return SIGILL; 225 226 case T_BREAKPOINT: 227 case EXC_MCHK: /* Machine check */ 228 case EXC_TRC: /* Trace */ 229 return SIGTRAP; 230 231 case EXC_ISI: /* Instruction storage interrupt */ 232 case EXC_DSI: /* Data storage interrupt */ 233 return SIGSEGV; 234 235 case EXC_FPU: /* Floating point unavailable */ 236 case EXC_FPA: /* Floating-point assist */ 237 return SIGFPE; 238 239 case EXC_SC: /* System call */ 240 return SIGURG; 241 242 case EXC_RSVD: /* Reserved */ 243 case EXC_AST: /* Floating point unavailable */ 244 default: 245 return SIGEMT; 246 } 247 } 248 249 /* 250 * Translate the values stored in the kernel regs struct to the format 251 * understood by gdb. 252 */ 253 void 254 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs) 255 { 256 memcpy(gdb_regs, regs, 32 * sizeof(unsigned long)); 257 gdb_regs[KGDB_PPC_PC_REG] = regs->iar; 258 gdb_regs[KGDB_PPC_MSR_REG] = regs->msr; 259 gdb_regs[KGDB_PPC_CR_REG] = regs->cr; 260 gdb_regs[KGDB_PPC_LR_REG] = regs->lr; 261 gdb_regs[KGDB_PPC_CTR_REG] = regs->ctr; 262 gdb_regs[KGDB_PPC_XER_REG] = regs->xer; 263 } 264 265 /* 266 * Reverse the above. 267 */ 268 void 269 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs) 270 { 271 regs->xer = gdb_regs[KGDB_PPC_XER_REG]; 272 regs->ctr = gdb_regs[KGDB_PPC_CTR_REG]; 273 regs->lr = gdb_regs[KGDB_PPC_LR_REG]; 274 regs->cr = gdb_regs[KGDB_PPC_CR_REG]; 275 regs->msr = gdb_regs[KGDB_PPC_MSR_REG]; 276 regs->iar = gdb_regs[KGDB_PPC_PC_REG]; 277 memcpy(regs, gdb_regs, 32 * sizeof(unsigned long)); 278 } 279 280 /* 281 * Trap into kgdb to wait for debugger to connect, 282 * noting on the console why nothing else is going on. 283 */ 284 void 285 kgdb_connect(int verbose) 286 { 287 if (kgdb_dev == NODEV) 288 return; 289 290 if (verbose) 291 printf("kgdb waiting..."); 292 293 __asm volatile(BKPT_ASM); 294 295 if (verbose && kgdb_active) { 296 printf("kgdb connected.\n"); 297 } 298 299 kgdb_debug_panic = 1; 300 } 301 302 /* 303 * Decide what to do on panic. 304 * (This is called by panic, like Debugger()) 305 */ 306 void 307 kgdb_panic(void) 308 { 309 if (kgdb_dev != NODEV && kgdb_debug_panic) { 310 printf("entering kgdb\n"); 311 kgdb_connect(kgdb_active == 0); 312 } 313 } 314