1 /* $NetBSD: kgdb_machdep.c,v 1.2 2003/07/15 00:24:42 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Matthias Pfaller. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Matthias Pfaller. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.2 2003/07/15 00:24:42 lukem Exp $"); 35 36 #include "opt_ddb.h" 37 #include "opt_kgdb.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kgdb.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #include <machine/frame.h> 46 #include <machine/reg.h> 47 #include <machine/trap.h> 48 49 /* 50 * Determine if the memory at va..(va+len) is valid. 51 */ 52 int 53 kgdb_acc(va, len) 54 vaddr_t va; 55 size_t len; 56 { 57 vaddr_t last_va; 58 59 last_va = va + len; 60 va &= ~PGOFSET; 61 last_va &= ~PGOFSET; 62 63 do { 64 if (db_validate_address(va)) 65 return (0); 66 va += PAGE_SIZE; 67 } while (va < last_va); 68 69 return (1); 70 } 71 72 /* 73 * Translate a trap number into a unix compatible signal value. 74 * (gdb only understands unix signal numbers). 75 */ 76 int 77 kgdb_signal(type) 78 int type; 79 { 80 81 switch (type) { 82 case T_BREAKPOINT: 83 return(SIGTRAP); 84 case -1: 85 return(SIGSEGV); 86 default: 87 return(SIGINT); 88 } 89 } 90 91 /* 92 * Definitions exported from gdb. 93 */ 94 95 /* 96 * Translate the values stored in the kernel regs struct to the format 97 * understood by gdb. 98 */ 99 void 100 kgdb_getregs(regs, gdb_regs) 101 db_regs_t *regs; 102 kgdb_reg_t *gdb_regs; 103 { 104 105 gdb_regs[KGDB_REGNUM_R0 + 0] = regs->tf_r0; 106 gdb_regs[KGDB_REGNUM_R0 + 1] = regs->tf_r1; 107 gdb_regs[KGDB_REGNUM_R0 + 2] = regs->tf_r2; 108 gdb_regs[KGDB_REGNUM_R0 + 3] = regs->tf_r3; 109 gdb_regs[KGDB_REGNUM_R0 + 4] = regs->tf_r4; 110 gdb_regs[KGDB_REGNUM_R0 + 5] = regs->tf_r5; 111 gdb_regs[KGDB_REGNUM_R0 + 6] = regs->tf_r6; 112 gdb_regs[KGDB_REGNUM_R0 + 7] = regs->tf_r7; 113 gdb_regs[KGDB_REGNUM_R0 + 8] = regs->tf_r8; 114 gdb_regs[KGDB_REGNUM_R0 + 9] = regs->tf_r9; 115 gdb_regs[KGDB_REGNUM_R0 + 10] = regs->tf_r10; 116 gdb_regs[KGDB_REGNUM_R0 + 11] = regs->tf_r11; 117 gdb_regs[KGDB_REGNUM_R0 + 12] = regs->tf_r12; 118 gdb_regs[KGDB_REGNUM_R0 + 13] = regs->tf_svc_sp; 119 gdb_regs[KGDB_REGNUM_R0 + 14] = regs->tf_svc_lr; 120 gdb_regs[KGDB_REGNUM_R0 + 15] = regs->tf_pc; 121 122 gdb_regs[KGDB_REGNUM_SPSR] = regs->tf_spsr; 123 } 124 125 /* 126 * Reverse the above. 127 */ 128 void 129 kgdb_setregs(regs, gdb_regs) 130 db_regs_t *regs; 131 kgdb_reg_t *gdb_regs; 132 { 133 regs->tf_r0 = gdb_regs[KGDB_REGNUM_R0 + 0]; 134 regs->tf_r1 = gdb_regs[KGDB_REGNUM_R0 + 1]; 135 regs->tf_r2 = gdb_regs[KGDB_REGNUM_R0 + 2]; 136 regs->tf_r3 = gdb_regs[KGDB_REGNUM_R0 + 3]; 137 regs->tf_r4 = gdb_regs[KGDB_REGNUM_R0 + 4]; 138 regs->tf_r5 = gdb_regs[KGDB_REGNUM_R0 + 5]; 139 regs->tf_r6 = gdb_regs[KGDB_REGNUM_R0 + 6]; 140 regs->tf_r7 = gdb_regs[KGDB_REGNUM_R0 + 7]; 141 regs->tf_r8 = gdb_regs[KGDB_REGNUM_R0 + 8]; 142 regs->tf_r9 = gdb_regs[KGDB_REGNUM_R0 + 9]; 143 regs->tf_r10 = gdb_regs[KGDB_REGNUM_R0 + 10]; 144 regs->tf_r11 = gdb_regs[KGDB_REGNUM_R0 + 11]; 145 regs->tf_r12 = gdb_regs[KGDB_REGNUM_R0 + 12]; 146 regs->tf_svc_sp = gdb_regs[KGDB_REGNUM_R0 + 13]; 147 regs->tf_svc_lr = gdb_regs[KGDB_REGNUM_R0 + 14]; 148 regs->tf_pc = gdb_regs[KGDB_REGNUM_R0 + 15]; 149 150 regs->tf_spsr = gdb_regs[KGDB_REGNUM_SPSR]; 151 } 152 153 /* 154 * Trap into kgdb to wait for debugger to connect, 155 * noting on the console why nothing else is going on. 156 */ 157 void 158 kgdb_connect(verbose) 159 int verbose; 160 { 161 162 if (kgdb_dev < 0) 163 return; 164 165 if (verbose) 166 printf("kgdb waiting..."); 167 168 asm volatile(KBPT_ASM); 169 170 if (verbose) 171 printf("connected.\n"); 172 173 kgdb_debug_panic = 1; 174 } 175 176 /* 177 * Decide what to do on panic. 178 * (This is called by panic, like Debugger()) 179 */ 180 void 181 kgdb_panic() 182 { 183 184 if (kgdb_dev >= 0 && kgdb_debug_panic) { 185 printf("entering kgdb\n"); 186 kgdb_connect(kgdb_active == 0); 187 } 188 } 189