Annotation of sys/arch/m88k/m88k/db_interface.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_interface.c,v 1.7 2007/05/19 20:33:49 miod Exp $ */
! 2: /*
! 3: * Mach Operating System
! 4: * Copyright (c) 1993-1991 Carnegie Mellon University
! 5: * Copyright (c) 1991 OMRON Corporation
! 6: * All Rights Reserved.
! 7: *
! 8: * Permission to use, copy, modify and distribute this software and its
! 9: * documentation is hereby granted, provided that both the copyright
! 10: * notice and this permission notice appear in all copies of the
! 11: * software, derivative works or modified versions, and any portions
! 12: * thereof, and that both notices appear in supporting documentation.
! 13: *
! 14: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 15: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 16: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 17: *
! 18: * Carnegie Mellon requests users of this software to return to
! 19: *
! 20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 21: * School of Computer Science
! 22: * Carnegie Mellon University
! 23: * Pittsburgh PA 15213-3890
! 24: *
! 25: * any improvements or extensions that they make and grant Carnegie the
! 26: * rights to redistribute these changes.
! 27: */
! 28:
! 29: /*
! 30: * m88k interface to ddb debugger
! 31: */
! 32:
! 33: #include <sys/param.h>
! 34: #include <sys/systm.h>
! 35: #include <sys/proc.h>
! 36: #include <sys/reboot.h>
! 37:
! 38: #include <uvm/uvm_extern.h>
! 39:
! 40: #include <machine/asm_macro.h>
! 41: #include <machine/cmmu.h>
! 42: #include <machine/trap.h>
! 43: #include <machine/db_machdep.h>
! 44: #include <machine/cpu.h>
! 45: #ifdef M88100
! 46: #include <machine/m88100.h>
! 47: #include <machine/m8820x.h>
! 48: #endif
! 49:
! 50: #include <ddb/db_access.h>
! 51: #include <ddb/db_command.h>
! 52: #include <ddb/db_extern.h>
! 53: #include <ddb/db_interface.h>
! 54: #include <ddb/db_output.h>
! 55: #include <ddb/db_sym.h>
! 56:
! 57: extern label_t *db_recover;
! 58: extern int frame_is_sane(db_regs_t *, int); /* db_trace */
! 59: extern void cnpollc(int);
! 60:
! 61: void kdbprinttrap(int);
! 62:
! 63: int m88k_dmx_print(u_int, u_int, u_int, u_int);
! 64:
! 65: void m88k_db_trap(int, struct trapframe *);
! 66: void ddb_error_trap(char *, db_regs_t *);
! 67: void m88k_db_pause(u_int);
! 68: void m88k_db_print_frame(db_expr_t, int, db_expr_t, char *);
! 69: void m88k_db_registers(db_expr_t, int, db_expr_t, char *);
! 70: void m88k_db_where(db_expr_t, int, db_expr_t, char *);
! 71: void m88k_db_frame_search(db_expr_t, int, db_expr_t, char *);
! 72: void m88k_db_translate(db_expr_t, int, db_expr_t, char *);
! 73: void m88k_db_cmmucfg(db_expr_t, int, db_expr_t, char *);
! 74:
! 75: db_regs_t ddb_regs;
! 76:
! 77: #ifdef MULTIPROCESSOR
! 78: #include <sys/mplock.h>
! 79: struct __mp_lock ddb_mp_lock;
! 80:
! 81: void m88k_db_cpu_cmd(db_expr_t, int, db_expr_t, char *);
! 82: #endif
! 83:
! 84: /*
! 85: * If you really feel like understanding the following procedure and
! 86: * macros, see pages 6-22 to 6-30 (Section 6.7.3) of
! 87: *
! 88: * MC88100 RISC Microprocessor User's Manual Second Edition
! 89: * (Motorola Order: MC88100UM/AD REV 1)
! 90: *
! 91: * and ERRATA-5 (6-23, 6-24, 6-24) of
! 92: *
! 93: * Errata to MC88100 User's Manual Second Edition MC88100UM/AD Rev 1
! 94: * (Oct 2, 1990)
! 95: * (Motorola Order: MC88100UMAD/AD)
! 96: */
! 97:
! 98: #ifdef M88100
! 99: /* macros for decoding dmt registers */
! 100:
! 101: /*
! 102: * return 1 if the printing of the next stage should be suppressed
! 103: */
! 104: int
! 105: m88k_dmx_print(u_int t, u_int d, u_int a, u_int no)
! 106: {
! 107: static const u_int addr_mod[16] = {
! 108: 0, 3, 2, 2, 1, 0, 0, 0,
! 109: 0, 0, 0, 0, 0, 0, 0, 0
! 110: };
! 111: static const char *mode[16] = {
! 112: "?", ".b", ".b", ".h", ".b", "?", "?", "?",
! 113: ".b", "?", "?" , "?" , ".h" , "?", "?", ""
! 114: };
! 115: static const u_int mask[16] = {
! 116: 0, 0xff, 0xff00, 0xffff,
! 117: 0xff0000, 0, 0, 0,
! 118: 0xff000000, 0, 0, 0,
! 119: 0xffff0000, 0, 0, 0xffffffff
! 120: };
! 121: static const u_int shift[16] = {
! 122: 0, 0, 8, 0, 16, 0, 0, 0,
! 123: 24, 0, 0, 0, 16, 0, 0, 0
! 124: };
! 125: int reg = DMT_DREGBITS(t);
! 126:
! 127: if (ISSET(t, DMT_LOCKBAR)) {
! 128: db_printf("xmem%s%s r%d(0x%x) <-> mem(0x%x),",
! 129: DMT_ENBITS(t) == 0x0f ? "" : ".bu",
! 130: ISSET(t, DMT_DAS) ? "" : ".usr", reg,
! 131: ((t >> 2 & 0xf) == 0xf) ? d : (d & 0xff), a);
! 132: return 1;
! 133: } else if (DMT_ENBITS(t) == 0xf) {
! 134: /* full or double word */
! 135: if (ISSET(t, DMT_WRITE)) {
! 136: if (ISSET(t, DMT_DOUB1) && no == 2)
! 137: db_printf("st.d%s -> mem(0x%x) (** restart sxip **)",
! 138: ISSET(t, DMT_DAS) ? "" : ".usr", a);
! 139: else
! 140: db_printf("st%s (0x%x) -> mem(0x%x)",
! 141: ISSET(t, DMT_DAS) ? "" : ".usr", d, a);
! 142: } else {
! 143: /* load */
! 144: if (ISSET(t, DMT_DOUB1) && no == 2)
! 145: db_printf("ld.d%s r%d <- mem(0x%x), r%d <- mem(0x%x)",
! 146: ISSET(t, DMT_DAS) ? "" : ".usr", reg, a, reg+1, a+4);
! 147: else
! 148: db_printf("ld%s r%d <- mem(0x%x)",
! 149: ISSET(t, DMT_DAS) ? "" : ".usr", reg, a);
! 150: }
! 151: } else {
! 152: /* fractional word - check if load or store */
! 153: a += addr_mod[DMT_ENBITS(t)];
! 154: if (ISSET(t, DMT_WRITE))
! 155: db_printf("st%s%s (0x%x) -> mem(0x%x)",
! 156: mode[DMT_ENBITS(t)],
! 157: ISSET(t, DMT_DAS) ? "" : ".usr",
! 158: (d & mask[DMT_ENBITS(t)]) >> shift[DMT_ENBITS(t)],
! 159: a);
! 160: else
! 161: db_printf("ld%s%s%s r%d <- mem(0x%x)",
! 162: mode[DMT_ENBITS(t)],
! 163: ISSET(t, DMT_SIGNED) ? "" : "u",
! 164: ISSET(t, DMT_DAS) ? "" : ".usr", reg, a);
! 165: }
! 166: return (0);
! 167: }
! 168: #endif /* M88100 */
! 169:
! 170: void
! 171: m88k_db_print_frame(addr, have_addr, count, modif)
! 172: db_expr_t addr;
! 173: int have_addr;
! 174: db_expr_t count;
! 175: char *modif;
! 176: {
! 177: struct trapframe *s = (struct trapframe *)addr;
! 178: char *name;
! 179: db_expr_t offset;
! 180: #ifdef M88100
! 181: int suppress1 = 0, suppress2 = 0;
! 182: #endif
! 183: int c, force = 0, help = 0;
! 184:
! 185: if (!have_addr) {
! 186: db_printf("requires address of frame\n");
! 187: help = 1;
! 188: }
! 189:
! 190: while (modif && *modif) {
! 191: switch (c = *modif++, c) {
! 192: case 'f':
! 193: force = 1;
! 194: break;
! 195: case 'h':
! 196: help = 1;
! 197: break;
! 198: default:
! 199: db_printf("unknown modifier [%c]\n", c);
! 200: help = 1;
! 201: break;
! 202: }
! 203: }
! 204:
! 205: if (help) {
! 206: db_printf("usage: mach frame/[f] ADDRESS\n");
! 207: db_printf(" /f force printing of insane frames.\n");
! 208: return;
! 209: }
! 210:
! 211: if (badaddr((vaddr_t)s, 4) ||
! 212: badaddr((vaddr_t)(&((db_regs_t*)s)->fpit), 4)) {
! 213: db_printf("frame at %8p is unreadable\n", s);
! 214: return;
! 215: }
! 216:
! 217: if (frame_is_sane((db_regs_t *)s, 0) == 0) {
! 218: if (force == 0)
! 219: return;
! 220: }
! 221:
! 222: #define R(i) s->tf_r[i]
! 223: #define IPMASK(x) ((x) & ~(3))
! 224: db_printf("R00-05: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 225: R(0), R(1), R(2), R(3), R(4), R(5));
! 226: db_printf("R06-11: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 227: R(6), R(7), R(8), R(9), R(10), R(11));
! 228: db_printf("R12-17: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 229: R(12), R(13), R(14), R(15), R(16), R(17));
! 230: db_printf("R18-23: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 231: R(18), R(19), R(20), R(21), R(22), R(23));
! 232: db_printf("R24-29: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 233: R(24), R(25), R(26), R(27), R(28), R(29));
! 234: db_printf("R30-31: 0x%08x 0x%08x\n", R(30), R(31));
! 235:
! 236: db_printf("%cxip: 0x%08x ",
! 237: CPU_IS88110 ? 'e' : 's', s->tf_sxip & XIP_ADDR);
! 238: db_find_xtrn_sym_and_offset((db_addr_t)IPMASK(s->tf_sxip),
! 239: &name, &offset);
! 240: if (name != NULL && (u_int)offset <= db_maxoff)
! 241: db_printf("%s+0x%08x", name, (u_int)offset);
! 242: db_printf("\n");
! 243:
! 244: if (s->tf_snip != s->tf_sxip + 4) {
! 245: db_printf("%cnip: 0x%08x ",
! 246: CPU_IS88110 ? 'e' : 's', s->tf_snip);
! 247: db_find_xtrn_sym_and_offset((db_addr_t)IPMASK(s->tf_snip),
! 248: &name, &offset);
! 249: if (name != NULL && (u_int)offset <= db_maxoff)
! 250: db_printf("%s+0x%08x", name, (u_int)offset);
! 251: db_printf("\n");
! 252: }
! 253:
! 254: #ifdef M88100
! 255: if (CPU_IS88100) {
! 256: if (s->tf_sfip != s->tf_snip + 4) {
! 257: db_printf("sfip: 0x%08x ", s->tf_sfip);
! 258: db_find_xtrn_sym_and_offset((db_addr_t)IPMASK(s->tf_sfip),
! 259: &name, &offset);
! 260: if (name != NULL && (u_int)offset <= db_maxoff)
! 261: db_printf("%s+0x%08x", name, (u_int)offset);
! 262: db_printf("\n");
! 263: }
! 264: }
! 265: #endif
! 266: #ifdef M88110
! 267: if (CPU_IS88110) {
! 268: db_printf("fpsr: 0x%08x fpcr: 0x%08x fpecr: 0x%08x\n",
! 269: s->tf_fpsr, s->tf_fpcr, s->tf_fpecr);
! 270: db_printf("dsap 0x%08x duap 0x%08x dsr 0x%08x dlar 0x%08x dpar 0x%08x\n",
! 271: s->tf_dsap, s->tf_duap, s->tf_dsr, s->tf_dlar, s->tf_dpar);
! 272: db_printf("isap 0x%08x iuap 0x%08x isr 0x%08x ilar 0x%08x ipar 0x%08x\n",
! 273: s->tf_isap, s->tf_iuap, s->tf_isr, s->tf_ilar, s->tf_ipar);
! 274: }
! 275: #endif
! 276:
! 277: db_printf("epsr: 0x%08x current process: %p\n",
! 278: s->tf_epsr, curproc);
! 279: db_printf("vector: 0x%02x interrupt mask: 0x%08x\n",
! 280: s->tf_vector, s->tf_mask);
! 281:
! 282: /*
! 283: * If the vector indicates trap, instead of an exception or
! 284: * interrupt, skip the check of dmt and fp regs.
! 285: *
! 286: * Interrupt and exceptions are vectored at 0-10 and 114-127.
! 287: */
! 288: if (!(s->tf_vector <= 10 ||
! 289: (114 <= s->tf_vector && s->tf_vector <= 127))) {
! 290: db_printf("\n");
! 291: return;
! 292: }
! 293:
! 294: #ifdef M88100
! 295: if (CPU_IS88100) {
! 296: if (s->tf_vector == /*data*/3 || s->tf_dmt0 & DMT_VALID) {
! 297: db_printf("dmt,d,a0: 0x%08x 0x%08x 0x%08x ",
! 298: s->tf_dmt0, s->tf_dmd0, s->tf_dma0);
! 299: db_find_xtrn_sym_and_offset((db_addr_t)s->tf_dma0,
! 300: &name, &offset);
! 301: if (name != NULL && (u_int)offset <= db_maxoff)
! 302: db_printf("%s+0x%08x", name, (u_int)offset);
! 303: db_printf("\n ");
! 304:
! 305: suppress1 = m88k_dmx_print(s->tf_dmt0, s->tf_dmd0,
! 306: s->tf_dma0, 0);
! 307: db_printf("\n");
! 308:
! 309: if ((s->tf_dmt1 & DMT_VALID) && (!suppress1)) {
! 310: db_printf("dmt,d,a1: 0x%08x 0x%08x 0x%08x ",
! 311: s->tf_dmt1, s->tf_dmd1, s->tf_dma1);
! 312: db_find_xtrn_sym_and_offset((db_addr_t)s->tf_dma1,
! 313: &name, &offset);
! 314: if (name != NULL && (u_int)offset <= db_maxoff)
! 315: db_printf("%s+0x%08x", name,
! 316: (u_int)offset);
! 317: db_printf("\n ");
! 318: suppress2 = m88k_dmx_print(s->tf_dmt1,
! 319: s->tf_dmd1, s->tf_dma1, 1);
! 320: db_printf("\n");
! 321:
! 322: if ((s->tf_dmt2 & DMT_VALID) && (!suppress2)) {
! 323: db_printf("dmt,d,a2: 0x%08x 0x%08x 0x%08x ",
! 324: s->tf_dmt2, s->tf_dmd2, s->tf_dma2);
! 325: db_find_xtrn_sym_and_offset((db_addr_t)s->tf_dma2,
! 326: &name, &offset);
! 327: if (name != 0 &&
! 328: (u_int)offset <= db_maxoff)
! 329: db_printf("%s+0x%08x", name,
! 330: (u_int)offset);
! 331: db_printf("\n ");
! 332: m88k_dmx_print(s->tf_dmt2, s->tf_dmd2,
! 333: s->tf_dma2, 2);
! 334: db_printf("\n");
! 335: }
! 336: }
! 337:
! 338: db_printf("fault code %d\n",
! 339: CMMU_PFSR_FAULT(s->tf_dpfsr));
! 340: }
! 341: }
! 342: #endif /* M88100 */
! 343:
! 344: if (s->tf_fpecr & 255) { /* floating point error occurred */
! 345: db_printf("fpecr: 0x%08x fpsr: 0x%08x fpcr: 0x%08x\n",
! 346: s->tf_fpecr, s->tf_fpsr, s->tf_fpcr);
! 347: #ifdef M88100
! 348: if (CPU_IS88100) {
! 349: db_printf("fcr1-4: 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 350: s->tf_fphs1, s->tf_fpls1, s->tf_fphs2, s->tf_fpls2);
! 351: db_printf("fcr5-8: 0x%08x 0x%08x 0x%08x 0x%08x\n",
! 352: s->tf_fppt, s->tf_fprh, s->tf_fprl, s->tf_fpit);
! 353: }
! 354: #endif
! 355: }
! 356: db_printf("\n");
! 357: }
! 358:
! 359: void
! 360: m88k_db_registers(addr, have_addr, count, modif)
! 361: db_expr_t addr;
! 362: int have_addr;
! 363: db_expr_t count;
! 364: char *modif;
! 365: {
! 366: m88k_db_print_frame((db_expr_t)DDB_REGS, TRUE, 0, modif);
! 367: }
! 368:
! 369: /*
! 370: * pause for 2*ticks many cycles
! 371: */
! 372: void
! 373: m88k_db_pause(ticks)
! 374: u_int volatile ticks;
! 375: {
! 376: while (ticks)
! 377: ticks -= 1;
! 378: }
! 379:
! 380: /*
! 381: * m88k_db_trap - field a TRACE or BPT trap
! 382: * Note that only the tf_regs part of the frame is valid - some ddb routines
! 383: * invoke this function with a promoted struct reg!
! 384: */
! 385: void
! 386: m88k_db_trap(type, frame)
! 387: int type;
! 388: struct trapframe *frame;
! 389: {
! 390: if (get_psr() & PSR_IND)
! 391: db_printf("WARNING: entered debugger with interrupts disabled\n");
! 392:
! 393: switch(type) {
! 394: case T_KDB_BREAK:
! 395: case T_KDB_TRACE:
! 396: case T_KDB_ENTRY:
! 397: break;
! 398: case -1:
! 399: break;
! 400: default:
! 401: kdbprinttrap(type);
! 402: if (db_recover != 0) {
! 403: db_error("Caught exception in ddb.\n");
! 404: /*NOTREACHED*/
! 405: }
! 406: }
! 407:
! 408: #ifdef MULTIPROCESSOR
! 409: curcpu()->ci_ddb_state = CI_DDB_ENTERDDB;
! 410: __mp_lock(&ddb_mp_lock);
! 411: curcpu()->ci_ddb_state = CI_DDB_INDDB;
! 412: m88k_broadcast_ipi(CI_IPI_DDB); /* pause other processors */
! 413: #endif
! 414:
! 415: ddb_regs = frame->tf_regs;
! 416:
! 417: cnpollc(TRUE);
! 418: db_trap(type, 0);
! 419: cnpollc(FALSE);
! 420:
! 421: frame->tf_regs = ddb_regs;
! 422:
! 423: #ifdef MULTIPROCESSOR
! 424: curcpu()->ci_ddb_state = CI_DDB_RUNNING;
! 425: __mp_release_all(&ddb_mp_lock);
! 426: #endif
! 427: }
! 428:
! 429: extern const char *trap_type[];
! 430: extern const int trap_types;
! 431:
! 432: /*
! 433: * Print trap reason.
! 434: */
! 435: void
! 436: kdbprinttrap(int type)
! 437: {
! 438: printf("kernel: ");
! 439: if (type >= trap_types || type < 0)
! 440: printf("type %d", type);
! 441: else
! 442: printf("%s", trap_type[type]);
! 443: printf(" trap\n");
! 444: }
! 445:
! 446: void
! 447: Debugger()
! 448: {
! 449: asm (ENTRY_ASM); /* entry trap */
! 450: /* ends up at ddb_entry_trap below */
! 451: return;
! 452: }
! 453:
! 454: /*
! 455: * When the below routine is entered interrupts should be on
! 456: * but spl should be high
! 457: *
! 458: * The following routine is for breakpoint and watchpoint entry.
! 459: */
! 460:
! 461: /* breakpoint/watchpoint entry */
! 462: int
! 463: ddb_break_trap(type, eframe)
! 464: int type;
! 465: db_regs_t *eframe;
! 466: {
! 467: m88k_db_trap(type, (struct trapframe *)eframe);
! 468:
! 469: if (type == T_KDB_BREAK) {
! 470: /*
! 471: * back up an instruction and retry the instruction
! 472: * at the breakpoint address. mc88110's exip reg
! 473: * already has the address of the exception instruction.
! 474: */
! 475: if (CPU_IS88100) {
! 476: eframe->sfip = eframe->snip;
! 477: eframe->snip = eframe->sxip;
! 478: }
! 479: }
! 480:
! 481: return 0;
! 482: }
! 483:
! 484: /* enter at splhigh */
! 485: int
! 486: ddb_entry_trap(level, eframe)
! 487: int level;
! 488: db_regs_t *eframe;
! 489: {
! 490: m88k_db_trap(T_KDB_ENTRY, (struct trapframe *)eframe);
! 491:
! 492: return 0;
! 493: }
! 494:
! 495: /*
! 496: * When the below routine is entered interrupts should be on
! 497: * but spl should be high
! 498: */
! 499: /* error trap - unreturnable */
! 500: void
! 501: ddb_error_trap(error, regs)
! 502: char *error;
! 503: db_regs_t *regs;
! 504: {
! 505: db_printf("KERNEL: unrecoverable error [%s]\n", error);
! 506: db_printf("KERNEL: Exiting debugger will cause abort to rom\n");
! 507: db_printf("at 0x%x ", regs->sxip & XIP_ADDR);
! 508: db_printf("dmt0 0x%x dma0 0x%x", regs->dmt0, regs->dma0);
! 509: m88k_db_pause(1000000);
! 510: m88k_db_trap(T_KDB_BREAK, (struct trapframe *)regs);
! 511: }
! 512:
! 513: /*
! 514: * Read bytes from kernel address space for debugger.
! 515: */
! 516: void
! 517: db_read_bytes(db_addr_t addr, size_t size, char *data)
! 518: {
! 519: char *src;
! 520:
! 521: src = (char *)addr;
! 522:
! 523: while (size-- > 0) {
! 524: *data++ = *src++;
! 525: }
! 526: }
! 527:
! 528: /*
! 529: * Write bytes to kernel address space for debugger.
! 530: */
! 531: void
! 532: db_write_bytes(db_addr_t addr, size_t size, char *data)
! 533: {
! 534: extern pt_entry_t *pmap_pte(pmap_t, vaddr_t);
! 535: char *dst = (char *)addr;
! 536: vaddr_t va;
! 537: paddr_t pa;
! 538: pt_entry_t *pte, opte;
! 539: size_t len, olen;
! 540: int cpu = cpu_number();
! 541:
! 542: while (size != 0) {
! 543: va = trunc_page((vaddr_t)dst);
! 544: pte = pmap_pte(pmap_kernel(), va);
! 545: opte = *pte;
! 546:
! 547: pa = (opte & PG_FRAME) | ((vaddr_t)dst & PAGE_MASK);
! 548: len = PAGE_SIZE - ((vaddr_t)dst & PAGE_MASK);
! 549: if (len > size)
! 550: len = size;
! 551: size -= olen = len;
! 552:
! 553: if (opte & PG_RO) {
! 554: *pte = opte & ~PG_RO;
! 555: cmmu_flush_tlb(cpu, TRUE, va, 1);
! 556: }
! 557: while (len-- != 0)
! 558: *dst++ = *data++;
! 559: if (opte & PG_RO) {
! 560: *pte = opte;
! 561: cmmu_flush_tlb(cpu, TRUE, va, 1);
! 562: }
! 563: cmmu_flush_cache(cpu, pa, olen);
! 564: }
! 565: }
! 566:
! 567: /* display where all the cpus are stopped at */
! 568: void
! 569: m88k_db_where(addr, have_addr, count, modif)
! 570: db_expr_t addr;
! 571: int have_addr;
! 572: db_expr_t count;
! 573: char *modif;
! 574: {
! 575: char *name;
! 576: db_expr_t offset;
! 577: db_addr_t l;
! 578:
! 579: l = PC_REGS(DDB_REGS); /* clear low bits */
! 580:
! 581: db_find_xtrn_sym_and_offset(l, &name, &offset);
! 582: if (name && (u_int)offset <= db_maxoff)
! 583: db_printf("stopped at 0x%lx (%s+0x%x)\n", l, name, offset);
! 584: else
! 585: db_printf("stopped at 0x%lx\n", l);
! 586: }
! 587:
! 588: /*
! 589: * Walk back a stack, looking for exception frames.
! 590: * These frames are recognized by the routine frame_is_sane. Frames
! 591: * only start with zero, so we only call frame_is_sane if the
! 592: * current address contains zero.
! 593: *
! 594: * If addr is given, it is assumed to an address on the stack to be
! 595: * searched. Otherwise, r31 of the current cpu is used.
! 596: */
! 597: void
! 598: m88k_db_frame_search(addr, have_addr, count, modif)
! 599: db_expr_t addr;
! 600: int have_addr;
! 601: db_expr_t count;
! 602: char *modif;
! 603: {
! 604: if (have_addr)
! 605: addr &= ~3; /* round to word */
! 606: else
! 607: addr = (DDB_REGS->r[31]);
! 608:
! 609: /* walk back up stack until 8k boundry, looking for 0 */
! 610: while (addr & ((8 * 1024) - 1)) {
! 611: if (frame_is_sane((db_regs_t *)addr, 1) != 0)
! 612: db_printf("frame found at 0x%x\n", addr);
! 613: addr += 4;
! 614: }
! 615:
! 616: db_printf("(Walked back until 0x%x)\n",addr);
! 617: }
! 618:
! 619: #ifdef MULTIPROCESSOR
! 620:
! 621: void
! 622: m88k_db_cpu_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
! 623: {
! 624: cpuid_t cpu;
! 625: struct cpu_info *ci;
! 626:
! 627: CPU_INFO_FOREACH(cpu, ci) {
! 628: db_printf("%c%4d: ", (cpu == cpu_number()) ? '*' : ' ',
! 629: CPU_INFO_UNIT(ci));
! 630: switch (ci->ci_ddb_state) {
! 631: case CI_DDB_RUNNING:
! 632: db_printf("running\n");
! 633: break;
! 634: case CI_DDB_ENTERDDB:
! 635: db_printf("entering ddb\n");
! 636: break;
! 637: case CI_DDB_INDDB:
! 638: db_printf("ddb\n");
! 639: break;
! 640: default:
! 641: db_printf("? (%d)\n",
! 642: ci->ci_ddb_state);
! 643: break;
! 644: }
! 645: }
! 646: }
! 647:
! 648: #endif /* MULTIPROCESSOR */
! 649:
! 650: /************************/
! 651: /* COMMAND TABLE / INIT */
! 652: /************************/
! 653:
! 654: struct db_command db_machine_cmds[] = {
! 655: #ifdef MULTIPROCESSOR
! 656: { "cpu", m88k_db_cpu_cmd, 0, NULL },
! 657: #endif
! 658: { "frame", m88k_db_print_frame, 0, NULL },
! 659: { "regs", m88k_db_registers, 0, NULL },
! 660: { "searchframe",m88k_db_frame_search, 0, NULL },
! 661: { "where", m88k_db_where, 0, NULL },
! 662: #if defined(EXTRA_MACHDEP_COMMANDS)
! 663: EXTRA_MACHDEP_COMMANDS
! 664: #endif
! 665: { NULL, NULL, 0, NULL }
! 666: };
! 667:
! 668: void
! 669: db_machine_init()
! 670: {
! 671: db_machine_commands_install(db_machine_cmds);
! 672: #ifdef MULTIPROCESSOR
! 673: __mp_lock_init(&ddb_mp_lock);
! 674: #endif
! 675: }
CVSweb