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