1 /* $NetBSD: db_interface.c,v 1.10 2022/10/26 23:38:08 riastradh 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.10 2022/10/26 23:38:08 riastradh 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_active.h> 99 #include <ddb/db_sym.h> 100 #include <ddb/db_command.h> 101 #include <ddb/db_extern.h> 102 #include <ddb/db_access.h> 103 #include <ddb/db_output.h> 104 #include <ddb/db_variables.h> 105 #include <ddb/db_interface.h> 106 #include <ddb/db_run.h> 107 108 #include <ia64/disasm/disasm.h> 109 110 int db_active = 0; 111 112 db_regs_t *ddb_regp; 113 114 static void db_show_vector(db_expr_t, bool, db_expr_t, const char *); 115 116 const struct db_command db_machine_command_table[] = { 117 { DDB_ADD_CMD("vector", db_show_vector, 0, 118 "Display information about vectors", 119 "[vector]", 120 " vector:\tthe vector to show (all vectors otherwise)") }, 121 122 { DDB_END_CMD }, 123 }; 124 125 static int 126 db_frame(const struct db_variable *vp, db_expr_t *valuep, int opcode) 127 { 128 uint64_t *reg; 129 struct trapframe *f = NULL; 130 131 if (vp->modif != NULL && *vp->modif == 'u') { 132 if (curlwp != NULL) 133 f = curlwp->l_md.md_tf; 134 } else f = DDB_REGS; 135 136 reg = (uint64_t*)((uintptr_t) f + (uintptr_t)vp->valuep); 137 138 switch (opcode) { 139 case DB_VAR_GET: 140 *valuep = *reg; 141 break; 142 case DB_VAR_SET: 143 *reg = *valuep; 144 break; 145 default: 146 panic("db_frame: unknown op %d", opcode); 147 } 148 return (0); 149 } 150 151 static int 152 db_getip(const struct db_variable *vp, db_expr_t *valuep, int opcode) 153 { 154 u_long iip, slot; 155 struct trapframe *f = NULL; 156 157 if (vp->modif != NULL && *vp->modif == 'u') { 158 if (curlwp != NULL) 159 f = curlwp->l_md.md_tf; 160 } else f = DDB_REGS; 161 162 switch (opcode) { 163 case DB_VAR_GET: 164 iip = f->tf_special.iip; 165 slot = (f->tf_special.psr >> 41) & 3; 166 *valuep = iip + slot; 167 break; 168 169 case DB_VAR_SET: 170 iip = *valuep & ~0xf; 171 slot = *valuep & 0xf; 172 if (slot > 2) 173 return (0); 174 f->tf_special.iip = iip; 175 f->tf_special.psr &= ~IA64_PSR_RI; 176 f->tf_special.psr |= slot << 41; 177 break; 178 179 default: 180 panic("db_getip: unknown op %d", opcode); 181 } 182 return (0); 183 } 184 185 static int 186 db_getrse(const struct db_variable *vp, db_expr_t *valuep, int opcode) 187 { 188 u_int64_t *reg; 189 uint64_t bsp; 190 int nats, regno, sof; 191 struct trapframe *f = NULL; 192 193 if (vp->modif != NULL && *vp->modif == 'u') { 194 if (curlwp != NULL) 195 f = curlwp->l_md.md_tf; 196 } else f = DDB_REGS; 197 198 199 regno = (int)(intptr_t)valuep; 200 bsp = f->tf_special.bspstore + f->tf_special.ndirty; 201 sof = (int)(f->tf_special.cfm & 0x7f); 202 203 if (regno >= sof) 204 return (0); 205 206 nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; 207 reg = (void*)(bsp - ((sof - regno + nats) << 3)); 208 209 210 switch (opcode) { 211 case DB_VAR_GET: 212 *valuep = *reg; 213 break; 214 case DB_VAR_SET: 215 *reg = *valuep; 216 break; 217 default: 218 panic("db_getrse: unknown op %d", opcode); 219 } 220 return (0); 221 } 222 223 224 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 225 const struct db_variable db_regs[] = { 226 {"ip", NULL, db_getip}, 227 {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame}, 228 {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame}, 229 {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame}, 230 {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame}, 231 {"rp", DB_OFFSET(tf_special.rp), db_frame}, 232 {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame}, 233 {"psr", DB_OFFSET(tf_special.psr), db_frame}, 234 {"cr.isr", DB_OFFSET(tf_special.isr), db_frame}, 235 {"pr", DB_OFFSET(tf_special.pr), db_frame}, 236 {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame}, 237 {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame}, 238 {"ar.unat", DB_OFFSET(tf_special.unat), db_frame}, 239 {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame}, 240 {"gp", DB_OFFSET(tf_special.gp), db_frame}, 241 {"sp", DB_OFFSET(tf_special.sp), db_frame}, 242 {"tp", DB_OFFSET(tf_special.tp), db_frame}, 243 {"b6", DB_OFFSET(tf_scratch.br6), db_frame}, 244 {"b7", DB_OFFSET(tf_scratch.br7), db_frame}, 245 {"r2", DB_OFFSET(tf_scratch.gr2), db_frame}, 246 {"r3", DB_OFFSET(tf_scratch.gr3), db_frame}, 247 {"r8", DB_OFFSET(tf_scratch.gr8), db_frame}, 248 {"r9", DB_OFFSET(tf_scratch.gr9), db_frame}, 249 {"r10", DB_OFFSET(tf_scratch.gr10), db_frame}, 250 {"r11", DB_OFFSET(tf_scratch.gr11), db_frame}, 251 {"r14", DB_OFFSET(tf_scratch.gr14), db_frame}, 252 {"r15", DB_OFFSET(tf_scratch.gr15), db_frame}, 253 {"r16", DB_OFFSET(tf_scratch.gr16), db_frame}, 254 {"r17", DB_OFFSET(tf_scratch.gr17), db_frame}, 255 {"r18", DB_OFFSET(tf_scratch.gr18), db_frame}, 256 {"r19", DB_OFFSET(tf_scratch.gr19), db_frame}, 257 {"r20", DB_OFFSET(tf_scratch.gr20), db_frame}, 258 {"r21", DB_OFFSET(tf_scratch.gr21), db_frame}, 259 {"r22", DB_OFFSET(tf_scratch.gr22), db_frame}, 260 {"r23", DB_OFFSET(tf_scratch.gr23), db_frame}, 261 {"r24", DB_OFFSET(tf_scratch.gr24), db_frame}, 262 {"r25", DB_OFFSET(tf_scratch.gr25), db_frame}, 263 {"r26", DB_OFFSET(tf_scratch.gr26), db_frame}, 264 {"r27", DB_OFFSET(tf_scratch.gr27), db_frame}, 265 {"r28", DB_OFFSET(tf_scratch.gr28), db_frame}, 266 {"r29", DB_OFFSET(tf_scratch.gr29), db_frame}, 267 {"r30", DB_OFFSET(tf_scratch.gr30), db_frame}, 268 {"r31", DB_OFFSET(tf_scratch.gr31), db_frame}, 269 {"r32", (db_expr_t*)0, db_getrse}, 270 {"r33", (db_expr_t*)1, db_getrse}, 271 {"r34", (db_expr_t*)2, db_getrse}, 272 {"r35", (db_expr_t*)3, db_getrse}, 273 {"r36", (db_expr_t*)4, db_getrse}, 274 {"r37", (db_expr_t*)5, db_getrse}, 275 {"r38", (db_expr_t*)6, db_getrse}, 276 {"r39", (db_expr_t*)7, db_getrse}, 277 {"r40", (db_expr_t*)8, db_getrse}, 278 {"r41", (db_expr_t*)9, db_getrse}, 279 {"r42", (db_expr_t*)10, db_getrse}, 280 {"r43", (db_expr_t*)11, db_getrse}, 281 {"r44", (db_expr_t*)12, db_getrse}, 282 {"r45", (db_expr_t*)13, db_getrse}, 283 {"r46", (db_expr_t*)14, db_getrse}, 284 {"r47", (db_expr_t*)15, db_getrse}, 285 {"r48", (db_expr_t*)16, db_getrse}, 286 {"r49", (db_expr_t*)17, db_getrse}, 287 {"r50", (db_expr_t*)18, db_getrse}, 288 {"r51", (db_expr_t*)19, db_getrse}, 289 {"r52", (db_expr_t*)20, db_getrse}, 290 {"r53", (db_expr_t*)21, db_getrse}, 291 {"r54", (db_expr_t*)22, db_getrse}, 292 {"r55", (db_expr_t*)23, db_getrse}, 293 {"r56", (db_expr_t*)24, db_getrse}, 294 {"r57", (db_expr_t*)25, db_getrse}, 295 {"r58", (db_expr_t*)26, db_getrse}, 296 {"r59", (db_expr_t*)27, db_getrse}, 297 {"r60", (db_expr_t*)28, db_getrse}, 298 {"r61", (db_expr_t*)29, db_getrse}, 299 {"r62", (db_expr_t*)30, db_getrse}, 300 {"r63", (db_expr_t*)31, db_getrse}, 301 {"r64", (db_expr_t*)32, db_getrse}, 302 {"r65", (db_expr_t*)33, db_getrse}, 303 {"r66", (db_expr_t*)34, db_getrse}, 304 {"r67", (db_expr_t*)35, db_getrse}, 305 {"r68", (db_expr_t*)36, db_getrse}, 306 {"r69", (db_expr_t*)37, db_getrse}, 307 {"r70", (db_expr_t*)38, db_getrse}, 308 {"r71", (db_expr_t*)39, db_getrse}, 309 {"r72", (db_expr_t*)40, db_getrse}, 310 {"r73", (db_expr_t*)41, db_getrse}, 311 {"r74", (db_expr_t*)42, db_getrse}, 312 {"r75", (db_expr_t*)43, db_getrse}, 313 {"r76", (db_expr_t*)44, db_getrse}, 314 {"r77", (db_expr_t*)45, db_getrse}, 315 {"r78", (db_expr_t*)46, db_getrse}, 316 {"r79", (db_expr_t*)47, db_getrse}, 317 {"r80", (db_expr_t*)48, db_getrse}, 318 {"r81", (db_expr_t*)49, db_getrse}, 319 {"r82", (db_expr_t*)50, db_getrse}, 320 {"r83", (db_expr_t*)51, db_getrse}, 321 {"r84", (db_expr_t*)52, db_getrse}, 322 {"r85", (db_expr_t*)53, db_getrse}, 323 {"r86", (db_expr_t*)54, db_getrse}, 324 {"r87", (db_expr_t*)55, db_getrse}, 325 {"r88", (db_expr_t*)56, db_getrse}, 326 {"r89", (db_expr_t*)57, db_getrse}, 327 {"r90", (db_expr_t*)58, db_getrse}, 328 {"r91", (db_expr_t*)59, db_getrse}, 329 {"r92", (db_expr_t*)60, db_getrse}, 330 {"r93", (db_expr_t*)61, db_getrse}, 331 {"r94", (db_expr_t*)62, db_getrse}, 332 {"r95", (db_expr_t*)63, db_getrse}, 333 {"r96", (db_expr_t*)64, db_getrse}, 334 {"r97", (db_expr_t*)65, db_getrse}, 335 {"r98", (db_expr_t*)66, db_getrse}, 336 {"r99", (db_expr_t*)67, db_getrse}, 337 {"r100", (db_expr_t*)68, db_getrse}, 338 {"r101", (db_expr_t*)69, db_getrse}, 339 {"r102", (db_expr_t*)70, db_getrse}, 340 {"r103", (db_expr_t*)71, db_getrse}, 341 {"r104", (db_expr_t*)72, db_getrse}, 342 {"r105", (db_expr_t*)73, db_getrse}, 343 {"r106", (db_expr_t*)74, db_getrse}, 344 {"r107", (db_expr_t*)75, db_getrse}, 345 {"r108", (db_expr_t*)76, db_getrse}, 346 {"r109", (db_expr_t*)77, db_getrse}, 347 {"r110", (db_expr_t*)78, db_getrse}, 348 {"r111", (db_expr_t*)79, db_getrse}, 349 {"r112", (db_expr_t*)80, db_getrse}, 350 {"r113", (db_expr_t*)81, db_getrse}, 351 {"r114", (db_expr_t*)82, db_getrse}, 352 {"r115", (db_expr_t*)83, db_getrse}, 353 {"r116", (db_expr_t*)84, db_getrse}, 354 {"r117", (db_expr_t*)85, db_getrse}, 355 {"r118", (db_expr_t*)86, db_getrse}, 356 {"r119", (db_expr_t*)87, db_getrse}, 357 {"r120", (db_expr_t*)88, db_getrse}, 358 {"r121", (db_expr_t*)89, db_getrse}, 359 {"r122", (db_expr_t*)90, db_getrse}, 360 {"r123", (db_expr_t*)91, db_getrse}, 361 {"r124", (db_expr_t*)92, db_getrse}, 362 {"r125", (db_expr_t*)93, db_getrse}, 363 {"r126", (db_expr_t*)94, db_getrse}, 364 {"r127", (db_expr_t*)95, db_getrse}, 365 }; 366 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 367 368 /* 369 * Read bytes from kernel address space for debugger. 370 */ 371 void 372 db_read_bytes(vaddr_t addr, register size_t size, register char *data) 373 { 374 register char *src; 375 376 src = (char *)addr; 377 while (size-- > 0) 378 *data++ = *src++; 379 } 380 381 /* 382 * Write bytes to kernel address space for debugger. 383 */ 384 void 385 db_write_bytes(vaddr_t addr, register size_t size, register const char *data) 386 { 387 register char *dst; 388 389 dst = (char *)addr; 390 while (size-- > 0) { 391 *dst++ = *data++; 392 ia64_fc_i((vaddr_t) dst); 393 } 394 ia64_sync_i(); 395 } 396 397 db_expr_t 398 db_bkpt_set(db_expr_t inst, db_addr_t addr) 399 { 400 db_expr_t tmp; 401 int slot; 402 403 slot = addr & 0xfUL; 404 if (slot >= SLOT_COUNT) slot = 0; 405 406 tmp = inst; 407 408 tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); 409 tmp |= (0x84000 << 6) << SLOT_SHIFT(slot); 410 411 return tmp; 412 } 413 414 void 415 cpu_Debugger(void) 416 { 417 printf("Broken into debugger \n"); 418 breakpoint(); 419 } 420 421 void 422 db_pc_advance(db_regs_t *regs) 423 { 424 425 if (regs == NULL) 426 return; 427 428 regs->tf_special.psr += IA64_PSR_RI_1; 429 if ((regs->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { 430 regs->tf_special.psr &= ~IA64_PSR_RI; 431 regs->tf_special.iip += 16; 432 } 433 } 434 435 db_addr_t 436 db_disasm(db_addr_t loc, bool altfmt) 437 { 438 char buf[32]; 439 struct asm_bundle bundle; 440 const struct asm_inst *i; 441 const char *tmpl; 442 int n, slot; 443 444 slot = loc & 0xf; 445 loc &= ~0xful; 446 db_read_bytes(loc, 16, buf); 447 if (asm_decode((uintptr_t)buf, &bundle)) { 448 i = bundle.b_inst + slot; 449 tmpl = bundle.b_templ + slot; 450 if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';')) 451 tmpl++; 452 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) { 453 db_printf("\n"); 454 goto out; 455 } 456 457 /* Unit + slot. */ 458 db_printf("[%c%d] ", *tmpl, slot); 459 460 /* Predicate. */ 461 if (i->i_oper[0].o_value != 0) { 462 asm_operand(i->i_oper+0, buf, sizeof(buf), loc); 463 db_printf("(%s) ", buf); 464 } else 465 db_printf(" "); 466 467 /* Mnemonic & completers. */ 468 asm_mnemonic(i->i_op, buf, sizeof(buf)); 469 db_printf(buf); 470 n = 0; 471 while (n < i->i_ncmpltrs) { 472 asm_completer(i->i_cmpltr + n, buf, sizeof(buf)); 473 db_printf(buf); 474 n++; 475 } 476 477 db_printf(" "); 478 479 /* Operands. */ 480 n = 1; 481 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) { 482 if (n > 1) { 483 if (n == i->i_srcidx) 484 db_printf("="); 485 else 486 db_printf(","); 487 } 488 asm_operand(i->i_oper + n, buf, sizeof(buf), loc); 489 db_printf(buf); 490 n++; 491 } 492 } else { 493 tmpl = NULL; 494 slot = 2; 495 } 496 db_printf("\n"); 497 498 out: 499 slot++; 500 if (slot == 1 && tmpl[1] == 'L') 501 slot++; 502 if (slot > 2) 503 slot = 16; 504 return (loc + slot); 505 } 506 507 508 static void 509 db_show_vector(db_expr_t addr, bool have_addr, db_expr_t count, 510 const char *modif) 511 { 512 extern void db_print_vector(u_int, int); 513 u_int vector; 514 515 if (have_addr) { 516 vector = ((addr >> 4) % 16) * 10 + (addr % 16); 517 if (vector >= 256) 518 db_printf("error: vector %u not in range [0..255]\n", 519 vector); 520 else 521 db_print_vector(vector, 1); 522 } else 523 for (vector = 0; vector < 256; vector++) 524 db_print_vector(vector, 0); 525 } 526