1*5b28f239Srillig /* $NetBSD: kgdb_machdep.c,v 1.5 2024/09/08 09:36:49 rillig Exp $ */ 2203c061eSreinoud 3203c061eSreinoud /* 4203c061eSreinoud * Copyright (c) 1996 Matthias Pfaller. 5203c061eSreinoud * All rights reserved. 6203c061eSreinoud * 7203c061eSreinoud * Redistribution and use in source and binary forms, with or without 8203c061eSreinoud * modification, are permitted provided that the following conditions 9203c061eSreinoud * are met: 10203c061eSreinoud * 1. Redistributions of source code must retain the above copyright 11203c061eSreinoud * notice, this list of conditions and the following disclaimer. 12203c061eSreinoud * 2. Redistributions in binary form must reproduce the above copyright 13203c061eSreinoud * notice, this list of conditions and the following disclaimer in the 14203c061eSreinoud * documentation and/or other materials provided with the distribution. 15203c061eSreinoud * 16203c061eSreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17203c061eSreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18203c061eSreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19203c061eSreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20203c061eSreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21203c061eSreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22203c061eSreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23203c061eSreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24203c061eSreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25203c061eSreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26203c061eSreinoud */ 27203c061eSreinoud 28203c061eSreinoud #include <sys/cdefs.h> 29*5b28f239Srillig __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.5 2024/09/08 09:36:49 rillig Exp $"); 30203c061eSreinoud 31203c061eSreinoud #include "opt_ddb.h" 32203c061eSreinoud #include "opt_kgdb.h" 33203c061eSreinoud 34203c061eSreinoud #include <sys/param.h> 35203c061eSreinoud #include <sys/systm.h> 36203c061eSreinoud #include <sys/kgdb.h> 37203c061eSreinoud #include <sys/socket.h> 38203c061eSreinoud 39203c061eSreinoud #include <uvm/uvm_extern.h> 40203c061eSreinoud 41203c061eSreinoud //#include <machine/frame.h> 42203c061eSreinoud #include <machine/reg.h> 43203c061eSreinoud #include <machine/trap.h> 44203c061eSreinoud #include <machine/db_machdep.h> 45203c061eSreinoud #include <machine/thunk.h> 46203c061eSreinoud #include <netinet/in.h> 47203c061eSreinoud 48203c061eSreinoud 49203c061eSreinoud /* 50203c061eSreinoud * Determine if the memory at va..(va+len) is valid. 51203c061eSreinoud */ 52203c061eSreinoud int 53203c061eSreinoud kgdb_acc(vaddr_t va, size_t len) 54203c061eSreinoud { 55203c061eSreinoud vaddr_t last_va; 56203c061eSreinoud 57203c061eSreinoud last_va = va + len; 58203c061eSreinoud va &= ~PGOFSET; 59203c061eSreinoud last_va &= ~PGOFSET; 60203c061eSreinoud 61517b4f49Sreinoud thunk_printf_debug("%s: [%p .. %p]\n", __func__, 62517b4f49Sreinoud (void *) va, (void *) last_va); 63203c061eSreinoud do { 64203c061eSreinoud if (db_validate_address(va)) 65203c061eSreinoud return (0); 66203c061eSreinoud va += PAGE_SIZE; 67203c061eSreinoud } while (va < last_va); 68203c061eSreinoud 69203c061eSreinoud return (1); 70203c061eSreinoud } 71203c061eSreinoud 72203c061eSreinoud /* 73203c061eSreinoud * Translate a trap number into a unix compatible signal value. 74203c061eSreinoud * (gdb only understands unix signal numbers). 75203c061eSreinoud */ 76203c061eSreinoud int 77203c061eSreinoud kgdb_signal(int type) 78203c061eSreinoud { 79203c061eSreinoud return type; 80203c061eSreinoud 81203c061eSreinoud // panic("%s", __func__); 82203c061eSreinoud #if 0 83203c061eSreinoud switch (type) { 84203c061eSreinoud case T_BREAKPOINT: 85203c061eSreinoud return(SIGTRAP); 86203c061eSreinoud case -1: 87203c061eSreinoud return(SIGSEGV); 88203c061eSreinoud default: 89203c061eSreinoud return(SIGINT); 90203c061eSreinoud } 91203c061eSreinoud #endif 92203c061eSreinoud } 93203c061eSreinoud 94203c061eSreinoud /* 95203c061eSreinoud * Definitions exported from gdb. 96203c061eSreinoud */ 97203c061eSreinoud 98203c061eSreinoud /* 99203c061eSreinoud * Translate the values stored in the kernel regs struct to the format 100203c061eSreinoud * understood by gdb. 101203c061eSreinoud */ 102203c061eSreinoud void 103203c061eSreinoud kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs) 104203c061eSreinoud { 105203c061eSreinoud #ifdef __x86_64__ 106203c061eSreinoud kgdb_reg_t *gregs = regs->uc_mcontext.__gregs; 107203c061eSreinoud 108203c061eSreinoud gdb_regs[ 0] = gregs[_REG_RAX]; 109203c061eSreinoud gdb_regs[ 1] = gregs[_REG_RBX]; 110203c061eSreinoud gdb_regs[ 2] = gregs[_REG_RCX]; 111203c061eSreinoud gdb_regs[ 3] = gregs[_REG_RDX]; 112203c061eSreinoud gdb_regs[ 4] = gregs[_REG_RSI]; 113203c061eSreinoud gdb_regs[ 5] = gregs[_REG_RDI]; 114203c061eSreinoud gdb_regs[ 6] = gregs[_REG_RBP]; 115203c061eSreinoud gdb_regs[ 7] = gregs[_REG_RSP]; 116203c061eSreinoud gdb_regs[ 8] = gregs[_REG_R8]; 117203c061eSreinoud gdb_regs[ 9] = gregs[_REG_R9]; 118203c061eSreinoud gdb_regs[10] = gregs[_REG_R10]; 119203c061eSreinoud gdb_regs[11] = gregs[_REG_R11]; 120203c061eSreinoud gdb_regs[12] = gregs[_REG_R12]; 121203c061eSreinoud gdb_regs[13] = gregs[_REG_R13]; 122203c061eSreinoud gdb_regs[14] = gregs[_REG_R14]; 123203c061eSreinoud gdb_regs[15] = gregs[_REG_R15]; 124203c061eSreinoud gdb_regs[16] = gregs[_REG_RIP]; 125203c061eSreinoud gdb_regs[17] = gregs[_REG_RFLAGS]; 126203c061eSreinoud gdb_regs[18] = gregs[_REG_CS]; 127203c061eSreinoud gdb_regs[19] = gregs[_REG_SS]; 128203c061eSreinoud 129203c061eSreinoud #elif defined(__i386) 130e4b9cc03Sreinoud kgdb_reg_t *gregs = regs->uc_mcontext.__gregs; 131203c061eSreinoud 132e4b9cc03Sreinoud gdb_regs[ 0] = gregs[_REG_EAX]; 133e4b9cc03Sreinoud gdb_regs[ 1] = gregs[_REG_ECX]; 134e4b9cc03Sreinoud gdb_regs[ 2] = gregs[_REG_EDX]; 135e4b9cc03Sreinoud gdb_regs[ 3] = gregs[_REG_EBX]; 136e4b9cc03Sreinoud gdb_regs[ 4] = gregs[_REG_ESP]; 137e4b9cc03Sreinoud gdb_regs[ 5] = gregs[_REG_EBP]; 138e4b9cc03Sreinoud gdb_regs[ 6] = gregs[_REG_ESI]; 139e4b9cc03Sreinoud gdb_regs[ 7] = gregs[_REG_EDI]; 140e4b9cc03Sreinoud gdb_regs[ 8] = gregs[_REG_EIP]; 141e4b9cc03Sreinoud gdb_regs[ 9] = gregs[_REG_EFL]; 142e4b9cc03Sreinoud gdb_regs[10] = gregs[_REG_CS]; 143e4b9cc03Sreinoud gdb_regs[11] = gregs[_REG_SS]; 144e4b9cc03Sreinoud gdb_regs[12] = gregs[_REG_DS]; 145e4b9cc03Sreinoud gdb_regs[13] = gregs[_REG_ES]; 146e4b9cc03Sreinoud gdb_regs[14] = gregs[_REG_FS]; 147e4b9cc03Sreinoud gdb_regs[15] = gregs[_REG_GS]; 148e4b9cc03Sreinoud 149203c061eSreinoud #else 150203c061eSreinoud #error port kgdb_machdep.c kgdb_getregs 151203c061eSreinoud #endif 152203c061eSreinoud } 153203c061eSreinoud 154203c061eSreinoud /* 155203c061eSreinoud * And the reverse. 156203c061eSreinoud */ 157203c061eSreinoud 158203c061eSreinoud void 159203c061eSreinoud kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs) 160203c061eSreinoud { 161203c061eSreinoud #ifdef __x86_64__ 162203c061eSreinoud kgdb_reg_t *gregs = regs->uc_mcontext.__gregs; 163203c061eSreinoud 164203c061eSreinoud gregs[_REG_RAX] = gdb_regs[ 0]; 165203c061eSreinoud gregs[_REG_RBX] = gdb_regs[ 1]; 166203c061eSreinoud gregs[_REG_RCX] = gdb_regs[ 2]; 167203c061eSreinoud gregs[_REG_RDX] = gdb_regs[ 3]; 168203c061eSreinoud gregs[_REG_RSI] = gdb_regs[ 4]; 169203c061eSreinoud gregs[_REG_RDI] = gdb_regs[ 5]; 170203c061eSreinoud gregs[_REG_RBP] = gdb_regs[ 6]; 171203c061eSreinoud gregs[_REG_RSP] = gdb_regs[ 7]; 172203c061eSreinoud gregs[_REG_R8 ] = gdb_regs[ 8]; 173203c061eSreinoud gregs[_REG_R9 ] = gdb_regs[ 9]; 174203c061eSreinoud gregs[_REG_R10] = gdb_regs[10]; 175203c061eSreinoud gregs[_REG_R11] = gdb_regs[11]; 176203c061eSreinoud gregs[_REG_R12] = gdb_regs[12]; 177203c061eSreinoud gregs[_REG_R13] = gdb_regs[13]; 178203c061eSreinoud gregs[_REG_R14] = gdb_regs[14]; 179203c061eSreinoud gregs[_REG_R15] = gdb_regs[15]; 180203c061eSreinoud gregs[_REG_RIP] = gdb_regs[16]; 181203c061eSreinoud gregs[_REG_RFLAGS] = gdb_regs[17]; 182203c061eSreinoud gregs[_REG_CS ] = gdb_regs[18]; 183203c061eSreinoud gregs[_REG_SS ] = gdb_regs[19]; 184203c061eSreinoud #elif defined(__i386) 185203c061eSreinoud panic("%s", __func__); 186e4b9cc03Sreinoud kgdb_reg_t *gregs = regs->uc_mcontext.__gregs; 187203c061eSreinoud 188e4b9cc03Sreinoud gregs[_REG_EAX] = gdb_regs[ 0]; 189e4b9cc03Sreinoud gregs[_REG_ECX] = gdb_regs[ 1]; 190e4b9cc03Sreinoud gregs[_REG_EDX] = gdb_regs[ 2]; 191e4b9cc03Sreinoud gregs[_REG_EBX] = gdb_regs[ 3]; 192e4b9cc03Sreinoud gregs[_REG_EBP] = gdb_regs[ 5]; 193e4b9cc03Sreinoud gregs[_REG_ESI] = gdb_regs[ 6]; 194e4b9cc03Sreinoud gregs[_REG_EDI] = gdb_regs[ 7]; 195e4b9cc03Sreinoud gregs[_REG_EIP] = gdb_regs[ 8]; 196e4b9cc03Sreinoud gregs[_REG_EFL] = gdb_regs[ 9]; 197e4b9cc03Sreinoud gregs[_REG_CS] = gdb_regs[10]; 198e4b9cc03Sreinoud gregs[_REG_DS] = gdb_regs[12]; 199e4b9cc03Sreinoud gregs[_REG_ES] = gdb_regs[13]; 200e4b9cc03Sreinoud 201203c061eSreinoud #else 202203c061eSreinoud panic("%s", __func__); 203203c061eSreinoud #endif 204203c061eSreinoud } 205203c061eSreinoud 206203c061eSreinoud /* 207203c061eSreinoud * Trap into kgdb to wait for debugger to connect, 208203c061eSreinoud * noting on the console why nothing else is going on. 209203c061eSreinoud */ 210203c061eSreinoud void 211203c061eSreinoud kgdb_connect(int verbose) 212203c061eSreinoud { 213203c061eSreinoud if (kgdb_dev == NODEV) 214203c061eSreinoud return; 215203c061eSreinoud 216203c061eSreinoud if (verbose) 217203c061eSreinoud printf("kgdb waiting..."); 218203c061eSreinoud 219203c061eSreinoud breakpoint(); 220203c061eSreinoud 221203c061eSreinoud if (verbose) 222203c061eSreinoud printf("connected.\n"); 223203c061eSreinoud 224203c061eSreinoud kgdb_debug_panic = 1; 225203c061eSreinoud } 226203c061eSreinoud 227203c061eSreinoud /* 228203c061eSreinoud * Decide what to do on panic. 229203c061eSreinoud * (This is called by panic, like Debugger()) 230203c061eSreinoud */ 231203c061eSreinoud void 232203c061eSreinoud kgdb_panic(void) 233203c061eSreinoud { 234203c061eSreinoud if (kgdb_dev != NODEV && kgdb_debug_panic) { 235203c061eSreinoud printf("entering kgdb\n"); 236203c061eSreinoud kgdb_connect(kgdb_active == 0); 237203c061eSreinoud } 238203c061eSreinoud } 239203c061eSreinoud 240203c061eSreinoud static int kgdb_socket, kgdb_fd; 241203c061eSreinoud static int kgdb_connected; 242203c061eSreinoud 243203c061eSreinoud 244203c061eSreinoud static void 245203c061eSreinoud kgdb_get_connection(void) 246203c061eSreinoud { 247203c061eSreinoud while (!kgdb_connected) { 248203c061eSreinoud thunk_printf("...[kgdb connecting]..."); 249203c061eSreinoud kgdb_fd = thunk_gdb_accept(kgdb_socket); 250203c061eSreinoud if (kgdb_fd) 251203c061eSreinoud kgdb_connected = 1; 252203c061eSreinoud } 253203c061eSreinoud kgdb_active = 1; 254203c061eSreinoud } 255203c061eSreinoud 256203c061eSreinoud static int 257203c061eSreinoud kgdb_getc(void *arg) 258203c061eSreinoud { 259203c061eSreinoud char ch; 260203c061eSreinoud 261203c061eSreinoud while (thunk_kgdb_getc(kgdb_fd, &ch) < 0) { 262203c061eSreinoud kgdb_connected = 0; 263203c061eSreinoud kgdb_get_connection(); 264203c061eSreinoud } 265203c061eSreinoud //thunk_printf("[<%c]", ch); 266203c061eSreinoud return (int) ch; 267203c061eSreinoud } 268203c061eSreinoud 269203c061eSreinoud 270203c061eSreinoud static void 271203c061eSreinoud kgdb_putc(void *arg, int ch_in) 272203c061eSreinoud { 273203c061eSreinoud char ch = (char) ch_in; 274203c061eSreinoud while (thunk_kgdb_putc(kgdb_fd, ch) < 0) { 275203c061eSreinoud kgdb_connected = 0; 276203c061eSreinoud kgdb_get_connection(); 277203c061eSreinoud } 278203c061eSreinoud //thunk_printf("[>%c]", ch); 279203c061eSreinoud } 280203c061eSreinoud 281203c061eSreinoud void 282203c061eSreinoud kgdb_port_init(void) 283203c061eSreinoud { 284203c061eSreinoud kgdb_connected = 0; 285203c061eSreinoud 286203c061eSreinoud /* open our socket */ 287203c061eSreinoud kgdb_socket = thunk_gdb_open(); 288203c061eSreinoud if (kgdb_socket == 0) { 289203c061eSreinoud kgdb_dev = 0; 290203c061eSreinoud printf("aborting kgdb\n"); 291203c061eSreinoud return; 292203c061eSreinoud } 293203c061eSreinoud 294203c061eSreinoud /* signal we have a connection `dev' */ 295203c061eSreinoud kgdb_dev = 0x123; 296203c061eSreinoud kgdb_attach(kgdb_getc, kgdb_putc, 0); 297203c061eSreinoud } 298203c061eSreinoud 299203c061eSreinoud /* 300*5b28f239Srillig * handle a trap instruction encountered from KGDB 301203c061eSreinoud */ 302203c061eSreinoud void 303203c061eSreinoud kgdb_kernel_trap(int signo, vaddr_t pc, vaddr_t va, ucontext_t *ucp) 304203c061eSreinoud { 305203c061eSreinoud kgdb_get_connection(); 306203c061eSreinoud 307203c061eSreinoud thunk_printf("entering trap\n"); 308203c061eSreinoud thunk_printf(" signo %d, pc %p, va %p\n", signo, (void *) pc, (void *) va); 309203c061eSreinoud kgdb_trap(signo, ucp); 310203c061eSreinoud } 311203c061eSreinoud 312