1 /* $NetBSD: db_interface.c,v 1.11 2026/11/07 22:20:12 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2003-2005 Marcel Moolenaar 5 * Copyright (c) 2000-2001 Doug Rabson 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 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 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 /* 32 * Mach Operating System 33 * Copyright (c) 1992,1991,1990 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS ``AS IS'' 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie the 54 * rights to redistribute these changes. 55 * 56 * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) 57 */ 58 59 /* 60 * Parts of this file are derived from Mach 3: 61 * 62 * File: alpha_instruction.c 63 * Author: Alessandro Forin, Carnegie Mellon University 64 * Date: 6/92 65 */ 66 67 /* 68 * Interface to DDB. 69 * 70 * Modified for NetBSD/alpha by: 71 * 72 * Christopher G. Demetriou, Carnegie Mellon University 73 * 74 * Jason R. Thorpe, Numerical Aerospace Simulation Facility, 75 * NASA Ames Research Center 76 */ 77 78 #include "opt_ddb.h" 79 #include "opt_multiprocessor.h" 80 81 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 82 83 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.11 2026/11/07 22:20:12 thorpej Exp $"); 84 85 #include <sys/param.h> 86 #include <sys/proc.h> 87 #include <sys/reboot.h> 88 #include <sys/systm.h> 89 90 #include <uvm/uvm_extern.h> 91 92 #include <dev/cons.h> 93 94 #include <machine/cpufunc.h> 95 #include <machine/md_var.h> 96 #include <machine/db_machdep.h> 97 98 #include <ddb/db_sym.h> 99 #include <ddb/db_command.h> 100 #include <ddb/db_extern.h> 101 #include <ddb/db_access.h> 102 #include <ddb/db_output.h> 103 #include <ddb/db_variables.h> 104 #include <ddb/db_interface.h> 105 #include <ddb/db_run.h> 106 107 #include <ia64/disasm/disasm.h> 108 109 db_regs_t *ddb_regp; 110 111 static void db_show_vector(db_expr_t, bool, db_expr_t, const char *); 112 113 const struct db_command db_machine_command_table[] = { 114 { DDB_ADD_CMD("vector", db_show_vector, 0, 115 "Display information about vectors", 116 "[vector]", 117 " vector:\tthe vector to show (all vectors otherwise)") }, 118 119 { DDB_END_CMD }, 120 }; 121 122 static int 123 db_frame(const struct db_variable *vp, db_expr_t *valuep, int opcode) 124 { 125 uint64_t *reg; 126 struct trapframe *f = NULL; 127 128 if (vp->modif != NULL && *vp->modif == 'u') { 129 if (curlwp != NULL) 130 f = curlwp->l_md.md_tf; 131 } else f = DDB_REGS; 132 133 reg = (uint64_t*)((uintptr_t) f + (uintptr_t)vp->valuep); 134 135 switch (opcode) { 136 case DB_VAR_GET: 137 *valuep = *reg; 138 break; 139 case DB_VAR_SET: 140 *reg = *valuep; 141 break; 142 default: 143 panic("db_frame: unknown op %d", opcode); 144 } 145 return (0); 146 } 147 148 static int 149 db_getip(const struct db_variable *vp, db_expr_t *valuep, int opcode) 150 { 151 u_long iip, slot; 152 struct trapframe *f = NULL; 153 154 if (vp->modif != NULL && *vp->modif == 'u') { 155 if (curlwp != NULL) 156 f = curlwp->l_md.md_tf; 157 } else f = DDB_REGS; 158 159 switch (opcode) { 160 case DB_VAR_GET: 161 iip = f->tf_special.iip; 162 slot = (f->tf_special.psr >> 41) & 3; 163 *valuep = iip + slot; 164 break; 165 166 case DB_VAR_SET: 167 iip = *valuep & ~0xf; 168 slot = *valuep & 0xf; 169 if (slot > 2) 170 return (0); 171 f->tf_special.iip = iip; 172 f->tf_special.psr &= ~IA64_PSR_RI; 173 f->tf_special.psr |= slot << 41; 174 break; 175 176 default: 177 panic("db_getip: unknown op %d", opcode); 178 } 179 return (0); 180 } 181 182 static int 183 db_getrse(const struct db_variable *vp, db_expr_t *valuep, int opcode) 184 { 185 u_int64_t *reg; 186 uint64_t bsp; 187 int nats, regno, sof; 188 struct trapframe *f = NULL; 189 190 if (vp->modif != NULL && *vp->modif == 'u') { 191 if (curlwp != NULL) 192 f = curlwp->l_md.md_tf; 193 } else f = DDB_REGS; 194 195 196 regno = (int)(intptr_t)valuep; 197 bsp = f->tf_special.bspstore + f->tf_special.ndirty; 198 sof = (int)(f->tf_special.cfm & 0x7f); 199 200 if (regno >= sof) 201 return (0); 202 203 nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; 204 reg = (void*)(bsp - ((sof - regno + nats) << 3)); 205 206 207 switch (opcode) { 208 case DB_VAR_GET: 209 *valuep = *reg; 210 break; 211 case DB_VAR_SET: 212 *reg = *valuep; 213 break; 214 default: 215 panic("db_getrse: unknown op %d", opcode); 216 } 217 return (0); 218 } 219 220 221 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 222 const struct db_variable db_regs[] = { 223 {"ip", NULL, db_getip}, 224 {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame}, 225 {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame}, 226 {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame}, 227 {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame}, 228 {"rp", DB_OFFSET(tf_special.rp), db_frame}, 229 {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame}, 230 {"psr", DB_OFFSET(tf_special.psr), db_frame}, 231 {"cr.isr", DB_OFFSET(tf_special.isr), db_frame}, 232 {"pr", DB_OFFSET(tf_special.pr), db_frame}, 233 {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame}, 234 {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame}, 235 {"ar.unat", DB_OFFSET(tf_special.unat), db_frame}, 236 {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame}, 237 {"gp", DB_OFFSET(tf_special.gp), db_frame}, 238 {"sp", DB_OFFSET(tf_special.sp), db_frame}, 239 {"tp", DB_OFFSET(tf_special.tp), db_frame}, 240 {"b6", DB_OFFSET(tf_scratch.br6), db_frame}, 241 {"b7", DB_OFFSET(tf_scratch.br7), db_frame}, 242 {"r2", DB_OFFSET(tf_scratch.gr2), db_frame}, 243 {"r3", DB_OFFSET(tf_scratch.gr3), db_frame}, 244 {"r8", DB_OFFSET(tf_scratch.gr8), db_frame}, 245 {"r9", DB_OFFSET(tf_scratch.gr9), db_frame}, 246 {"r10", DB_OFFSET(tf_scratch.gr10), db_frame}, 247 {"r11", DB_OFFSET(tf_scratch.gr11), db_frame}, 248 {"r14", DB_OFFSET(tf_scratch.gr14), db_frame}, 249 {"r15", DB_OFFSET(tf_scratch.gr15), db_frame}, 250 {"r16", DB_OFFSET(tf_scratch.gr16), db_frame}, 251 {"r17", DB_OFFSET(tf_scratch.gr17), db_frame}, 252 {"r18", DB_OFFSET(tf_scratch.gr18), db_frame}, 253 {"r19", DB_OFFSET(tf_scratch.gr19), db_frame}, 254 {"r20", DB_OFFSET(tf_scratch.gr20), db_frame}, 255 {"r21", DB_OFFSET(tf_scratch.gr21), db_frame}, 256 {"r22", DB_OFFSET(tf_scratch.gr22), db_frame}, 257 {"r23", DB_OFFSET(tf_scratch.gr23), db_frame}, 258 {"r24", DB_OFFSET(tf_scratch.gr24), db_frame}, 259 {"r25", DB_OFFSET(tf_scratch.gr25), db_frame}, 260 {"r26", DB_OFFSET(tf_scratch.gr26), db_frame}, 261 {"r27", DB_OFFSET(tf_scratch.gr27), db_frame}, 262 {"r28", DB_OFFSET(tf_scratch.gr28), db_frame}, 263 {"r29", DB_OFFSET(tf_scratch.gr29), db_frame}, 264 {"r30", DB_OFFSET(tf_scratch.gr30), db_frame}, 265 {"r31", DB_OFFSET(tf_scratch.gr31), db_frame}, 266 {"r32", (db_expr_t*)0, db_getrse}, 267 {"r33", (db_expr_t*)1, db_getrse}, 268 {"r34", (db_expr_t*)2, db_getrse}, 269 {"r35", (db_expr_t*)3, db_getrse}, 270 {"r36", (db_expr_t*)4, db_getrse}, 271 {"r37", (db_expr_t*)5, db_getrse}, 272 {"r38", (db_expr_t*)6, db_getrse}, 273 {"r39", (db_expr_t*)7, db_getrse}, 274 {"r40", (db_expr_t*)8, db_getrse}, 275 {"r41", (db_expr_t*)9, db_getrse}, 276 {"r42", (db_expr_t*)10, db_getrse}, 277 {"r43", (db_expr_t*)11, db_getrse}, 278 {"r44", (db_expr_t*)12, db_getrse}, 279 {"r45", (db_expr_t*)13, db_getrse}, 280 {"r46", (db_expr_t*)14, db_getrse}, 281 {"r47", (db_expr_t*)15, db_getrse}, 282 {"r48", (db_expr_t*)16, db_getrse}, 283 {"r49", (db_expr_t*)17, db_getrse}, 284 {"r50", (db_expr_t*)18, db_getrse}, 285 {"r51", (db_expr_t*)19, db_getrse}, 286 {"r52", (db_expr_t*)20, db_getrse}, 287 {"r53", (db_expr_t*)21, db_getrse}, 288 {"r54", (db_expr_t*)22, db_getrse}, 289 {"r55", (db_expr_t*)23, db_getrse}, 290 {"r56", (db_expr_t*)24, db_getrse}, 291 {"r57", (db_expr_t*)25, db_getrse}, 292 {"r58", (db_expr_t*)26, db_getrse}, 293 {"r59", (db_expr_t*)27, db_getrse}, 294 {"r60", (db_expr_t*)28, db_getrse}, 295 {"r61", (db_expr_t*)29, db_getrse}, 296 {"r62", (db_expr_t*)30, db_getrse}, 297 {"r63", (db_expr_t*)31, db_getrse}, 298 {"r64", (db_expr_t*)32, db_getrse}, 299 {"r65", (db_expr_t*)33, db_getrse}, 300 {"r66", (db_expr_t*)34, db_getrse}, 301 {"r67", (db_expr_t*)35, db_getrse}, 302 {"r68", (db_expr_t*)36, db_getrse}, 303 {"r69", (db_expr_t*)37, db_getrse}, 304 {"r70", (db_expr_t*)38, db_getrse}, 305 {"r71", (db_expr_t*)39, db_getrse}, 306 {"r72", (db_expr_t*)40, db_getrse}, 307 {"r73", (db_expr_t*)41, db_getrse}, 308 {"r74", (db_expr_t*)42, db_getrse}, 309 {"r75", (db_expr_t*)43, db_getrse}, 310 {"r76", (db_expr_t*)44, db_getrse}, 311 {"r77", (db_expr_t*)45, db_getrse}, 312 {"r78", (db_expr_t*)46, db_getrse}, 313 {"r79", (db_expr_t*)47, db_getrse}, 314 {"r80", (db_expr_t*)48, db_getrse}, 315 {"r81", (db_expr_t*)49, db_getrse}, 316 {"r82", (db_expr_t*)50, db_getrse}, 317 {"r83", (db_expr_t*)51, db_getrse}, 318 {"r84", (db_expr_t*)52, db_getrse}, 319 {"r85", (db_expr_t*)53, db_getrse}, 320 {"r86", (db_expr_t*)54, db_getrse}, 321 {"r87", (db_expr_t*)55, db_getrse}, 322 {"r88", (db_expr_t*)56, db_getrse}, 323 {"r89", (db_expr_t*)57, db_getrse}, 324 {"r90", (db_expr_t*)58, db_getrse}, 325 {"r91", (db_expr_t*)59, db_getrse}, 326 {"r92", (db_expr_t*)60, db_getrse}, 327 {"r93", (db_expr_t*)61, db_getrse}, 328 {"r94", (db_expr_t*)62, db_getrse}, 329 {"r95", (db_expr_t*)63, db_getrse}, 330 {"r96", (db_expr_t*)64, db_getrse}, 331 {"r97", (db_expr_t*)65, db_getrse}, 332 {"r98", (db_expr_t*)66, db_getrse}, 333 {"r99", (db_expr_t*)67, db_getrse}, 334 {"r100", (db_expr_t*)68, db_getrse}, 335 {"r101", (db_expr_t*)69, db_getrse}, 336 {"r102", (db_expr_t*)70, db_getrse}, 337 {"r103", (db_expr_t*)71, db_getrse}, 338 {"r104", (db_expr_t*)72, db_getrse}, 339 {"r105", (db_expr_t*)73, db_getrse}, 340 {"r106", (db_expr_t*)74, db_getrse}, 341 {"r107", (db_expr_t*)75, db_getrse}, 342 {"r108", (db_expr_t*)76, db_getrse}, 343 {"r109", (db_expr_t*)77, db_getrse}, 344 {"r110", (db_expr_t*)78, db_getrse}, 345 {"r111", (db_expr_t*)79, db_getrse}, 346 {"r112", (db_expr_t*)80, db_getrse}, 347 {"r113", (db_expr_t*)81, db_getrse}, 348 {"r114", (db_expr_t*)82, db_getrse}, 349 {"r115", (db_expr_t*)83, db_getrse}, 350 {"r116", (db_expr_t*)84, db_getrse}, 351 {"r117", (db_expr_t*)85, db_getrse}, 352 {"r118", (db_expr_t*)86, db_getrse}, 353 {"r119", (db_expr_t*)87, db_getrse}, 354 {"r120", (db_expr_t*)88, db_getrse}, 355 {"r121", (db_expr_t*)89, db_getrse}, 356 {"r122", (db_expr_t*)90, db_getrse}, 357 {"r123", (db_expr_t*)91, db_getrse}, 358 {"r124", (db_expr_t*)92, db_getrse}, 359 {"r125", (db_expr_t*)93, db_getrse}, 360 {"r126", (db_expr_t*)94, db_getrse}, 361 {"r127", (db_expr_t*)95, db_getrse}, 362 }; 363 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 364 365 /* 366 * Read bytes from kernel address space for debugger. 367 */ 368 void 369 db_read_bytes(vaddr_t addr, register size_t size, register char *data) 370 { 371 register char *src; 372 373 src = (char *)addr; 374 while (size-- > 0) 375 *data++ = *src++; 376 } 377 378 /* 379 * Write bytes to kernel address space for debugger. 380 */ 381 void 382 db_write_bytes(vaddr_t addr, register size_t size, register const char *data) 383 { 384 register char *dst; 385 386 dst = (char *)addr; 387 while (size-- > 0) { 388 *dst++ = *data++; 389 ia64_fc_i((vaddr_t) dst); 390 } 391 ia64_sync_i(); 392 } 393 394 db_expr_t 395 db_bkpt_set(db_expr_t inst, db_addr_t addr) 396 { 397 db_expr_t tmp; 398 int slot; 399 400 slot = addr & 0xfUL; 401 if (slot >= SLOT_COUNT) slot = 0; 402 403 tmp = inst; 404 405 tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); 406 tmp |= (0x84000 << 6) << SLOT_SHIFT(slot); 407 408 return tmp; 409 } 410 411 void 412 cpu_Debugger(void) 413 { 414 printf("Broken into debugger \n"); 415 breakpoint(); 416 } 417 418 void 419 db_pc_advance(db_regs_t *regs) 420 { 421 422 if (regs == NULL) 423 return; 424 425 regs->tf_special.psr += IA64_PSR_RI_1; 426 if ((regs->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { 427 regs->tf_special.psr &= ~IA64_PSR_RI; 428 regs->tf_special.iip += 16; 429 } 430 } 431 432 db_addr_t 433 db_disasm(db_addr_t loc, bool altfmt) 434 { 435 char buf[32]; 436 struct asm_bundle bundle; 437 const struct asm_inst *i; 438 const char *tmpl; 439 int n, slot; 440 441 slot = loc & 0xf; 442 loc &= ~0xful; 443 db_read_bytes(loc, 16, buf); 444 if (asm_decode((uintptr_t)buf, &bundle)) { 445 i = bundle.b_inst + slot; 446 tmpl = bundle.b_templ + slot; 447 if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';')) 448 tmpl++; 449 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) { 450 db_printf("\n"); 451 goto out; 452 } 453 454 /* Unit + slot. */ 455 db_printf("[%c%d] ", *tmpl, slot); 456 457 /* Predicate. */ 458 if (i->i_oper[0].o_value != 0) { 459 asm_operand(i->i_oper+0, buf, sizeof(buf), loc); 460 db_printf("(%s) ", buf); 461 } else 462 db_printf(" "); 463 464 /* Mnemonic & completers. */ 465 asm_mnemonic(i->i_op, buf, sizeof(buf)); 466 db_printf(buf); 467 n = 0; 468 while (n < i->i_ncmpltrs) { 469 asm_completer(i->i_cmpltr + n, buf, sizeof(buf)); 470 db_printf(buf); 471 n++; 472 } 473 474 db_printf(" "); 475 476 /* Operands. */ 477 n = 1; 478 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) { 479 if (n > 1) { 480 if (n == i->i_srcidx) 481 db_printf("="); 482 else 483 db_printf(","); 484 } 485 asm_operand(i->i_oper + n, buf, sizeof(buf), loc); 486 db_printf(buf); 487 n++; 488 } 489 } else { 490 tmpl = NULL; 491 slot = 2; 492 } 493 db_printf("\n"); 494 495 out: 496 slot++; 497 if (slot == 1 && tmpl[1] == 'L') 498 slot++; 499 if (slot > 2) 500 slot = 16; 501 return (loc + slot); 502 } 503 504 505 static void 506 db_show_vector(db_expr_t addr, bool have_addr, db_expr_t count, 507 const char *modif) 508 { 509 extern void db_print_vector(u_int, int); 510 u_int vector; 511 512 if (have_addr) { 513 vector = ((addr >> 4) % 16) * 10 + (addr % 16); 514 if (vector >= 256) 515 db_printf("error: vector %u not in range [0..255]\n", 516 vector); 517 else 518 db_print_vector(vector, 1); 519 } else 520 for (vector = 0; vector < 256; vector++) 521 db_print_vector(vector, 0); 522 } 523