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