Annotation of sys/arch/m88k/m88k/db_interface.c, Revision 1.1.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