1 /* $NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $ */
5 * Mach Operating System
6 * Copyright (c) 1992,1991,1990 Carnegie Mellon University
9 * Permission to use, copy, modify and distribute this software and its
10 * documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
29 * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
33 * Parts of this file are derived from Mach 3:
35 * File: alpha_instruction.c
36 * Author: Alessandro Forin, Carnegie Mellon University
43 * Modified for NetBSD/alpha by:
45 * Christopher G. Demetriou, Carnegie Mellon University
47 * Jason R. Thorpe, Numerical Aerospace Simulation Facility,
48 * NASA Ames Research Center
51 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
53 /* __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.2 1997/09/16 19:07:19 thorpej Exp $"); */
55 #include <sys/param.h>
57 #include <sys/reboot.h>
58 #include <sys/systm.h>
59 #include <sys/kernel.h>
64 #include <machine/db_machdep.h>
65 #include <machine/pal.h>
66 #include <machine/prom.h>
68 #include <alpha/alpha/db_instruction.h>
72 #include <ddb/db_access.h>
73 #include <ddb/db_sym.h>
74 #include <ddb/db_variables.h>
77 static jmp_buf *db_nofault = 0;
78 extern jmp_buf db_jmpbuf;
80 extern void gdb_handle_exception __P((db_regs_t *, int, int));
83 extern char *trap_type[];
84 extern int trap_types;
89 void ddbprinttrap __P((unsigned long, unsigned long, unsigned long,
92 struct db_variable db_regs[] = {
93 { "v0", &ddb_regs.tf_regs[FRAME_V0], FCN_NULL },
94 { "t0", &ddb_regs.tf_regs[FRAME_T0], FCN_NULL },
95 { "t1", &ddb_regs.tf_regs[FRAME_T1], FCN_NULL },
96 { "t2", &ddb_regs.tf_regs[FRAME_T2], FCN_NULL },
97 { "t3", &ddb_regs.tf_regs[FRAME_T3], FCN_NULL },
98 { "t4", &ddb_regs.tf_regs[FRAME_T4], FCN_NULL },
99 { "t5", &ddb_regs.tf_regs[FRAME_T5], FCN_NULL },
100 { "t6", &ddb_regs.tf_regs[FRAME_T6], FCN_NULL },
101 { "t7", &ddb_regs.tf_regs[FRAME_T7], FCN_NULL },
102 { "s0", &ddb_regs.tf_regs[FRAME_S0], FCN_NULL },
103 { "s1", &ddb_regs.tf_regs[FRAME_S1], FCN_NULL },
104 { "s2", &ddb_regs.tf_regs[FRAME_S2], FCN_NULL },
105 { "s3", &ddb_regs.tf_regs[FRAME_S3], FCN_NULL },
106 { "s4", &ddb_regs.tf_regs[FRAME_S4], FCN_NULL },
107 { "s5", &ddb_regs.tf_regs[FRAME_S5], FCN_NULL },
108 { "s6", &ddb_regs.tf_regs[FRAME_S6], FCN_NULL },
109 { "a0", &ddb_regs.tf_regs[FRAME_A0], FCN_NULL },
110 { "a1", &ddb_regs.tf_regs[FRAME_A1], FCN_NULL },
111 { "a2", &ddb_regs.tf_regs[FRAME_A2], FCN_NULL },
112 { "a3", &ddb_regs.tf_regs[FRAME_A3], FCN_NULL },
113 { "a4", &ddb_regs.tf_regs[FRAME_A4], FCN_NULL },
114 { "a5", &ddb_regs.tf_regs[FRAME_A5], FCN_NULL },
115 { "t8", &ddb_regs.tf_regs[FRAME_T8], FCN_NULL },
116 { "t9", &ddb_regs.tf_regs[FRAME_T9], FCN_NULL },
117 { "t10", &ddb_regs.tf_regs[FRAME_T10], FCN_NULL },
118 { "t11", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
119 { "ra", &ddb_regs.tf_regs[FRAME_RA], FCN_NULL },
120 { "t12", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
121 { "at", &ddb_regs.tf_regs[FRAME_AT], FCN_NULL },
122 { "gp", &ddb_regs.tf_regs[FRAME_GP], FCN_NULL },
123 { "sp", &ddb_regs.tf_regs[FRAME_SP], FCN_NULL },
124 { "pc", &ddb_regs.tf_regs[FRAME_PC], FCN_NULL },
125 { "ps", &ddb_regs.tf_regs[FRAME_PS], FCN_NULL },
126 { "ai", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
127 { "pv", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
129 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
135 ddbprinttrap(a0, a1, a2, entry)
136 unsigned long a0, a1, a2, entry;
141 printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2,
146 * ddb_trap - field a kernel trap
149 kdb_trap(a0, a1, a2, entry, regs)
150 unsigned long a0, a1, a2, entry;
153 int ddb_mode = !(boothowto & RB_GDB);
157 * Don't bother checking for usermode, since a benign entry
158 * by the kernel (call to Debugger() or a breakpoint) has
159 * already checked for usermode. If neither of those
160 * conditions exist, something Bad has happened.
163 if (entry != ALPHA_KENTRY_IF ||
164 (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT
165 && a0 != ALPHA_IF_CODE_GENTRAP)) {
167 db_printf("ddbprinttrap from 0x%lx\n", /* XXX */
168 regs->tf_regs[FRAME_PC]);
169 ddbprinttrap(a0, a1, a2, entry);
171 * Tell caller "We did NOT handle the trap."
172 * Caller should panic, or whatever.
177 jmp_buf *no_fault = db_nofault;
179 longjmp(*no_fault, 1);
184 * XXX Should switch to DDB's own stack, here.
194 cndbctl(TRUE); /* DDB active, unblank video */
195 db_trap(entry, a0); /* Where the work happens */
196 cndbctl(FALSE); /* DDB inactive */
198 gdb_handle_exception(&ddb_regs, entry, a0);
207 * Tell caller "We HAVE handled the trap."
213 * Read bytes from kernel address space for debugger.
216 db_read_bytes(addr, size, data)
218 register size_t size;
223 db_nofault = &db_jmpbuf;
233 * Write bytes to kernel address space for debugger.
236 db_write_bytes(addr, size, data)
238 register size_t size;
243 db_nofault = &db_jmpbuf;
254 Debugger(const char* msg)
257 __asm("call_pal 0x81"); /* XXX bugchk */
261 * Alpha-specific ddb commands:
263 * halt set halt bit in rpb and halt
264 * reboot set reboot bit in rpb and halt
267 DB_COMMAND(halt, db_mach_halt)
273 DB_COMMAND(reboot, db_mach_reboot)
279 * Map Alpha register numbers to trapframe/db_regs_t offsets.
281 static int reg_to_frame[32] = {
320 db_register_value(regs, regno)
325 if (regno > 31 || regno < 0) {
326 db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno);
333 return (regs->tf_regs[reg_to_frame[regno]]);
337 * Support functions for software single-step.
344 alpha_instruction insn;
347 return ((insn.branch_format.opcode == op_bsr) ||
348 ((insn.jump_format.opcode == op_j) &&
349 (insn.jump_format.action & 1)));
356 alpha_instruction insn;
359 return ((insn.jump_format.opcode == op_j) &&
360 (insn.jump_format.action == op_ret));
364 db_inst_trap_return(ins)
367 alpha_instruction insn;
370 return ((insn.pal_format.opcode == op_pal) &&
371 (insn.pal_format.function == PAL_OSF1_rti));
378 alpha_instruction insn;
381 switch (insn.branch_format.opcode) {
405 db_inst_unconditional_flow_transfer(ins)
408 alpha_instruction insn;
411 switch (insn.branch_format.opcode) {
417 switch (insn.pal_format.function) {
418 case PAL_OSF1_retsys:
420 case PAL_OSF1_callsys:
430 db_inst_spill(ins, regn)
433 alpha_instruction insn;
436 return ((insn.mem_format.opcode == op_stq) &&
437 (insn.mem_format.rd == regn));
445 alpha_instruction insn;
450 if (insn.mem_format.opcode == op_ldbu ||
451 insn.mem_format.opcode == op_ldq_u ||
452 insn.mem_format.opcode == op_ldwu)
454 if ((insn.mem_format.opcode >= op_ldf) &&
455 (insn.mem_format.opcode <= op_ldt))
457 if ((insn.mem_format.opcode >= op_ldl) &&
458 (insn.mem_format.opcode <= op_ldq_l))
462 if (insn.mem_format.opcode == op_special) {
463 /* Note: MB is treated as a store. */
464 if ((insn.mem_format.displacement == (short)op_fetch) ||
465 (insn.mem_format.displacement == (short)op_fetch_m))
476 alpha_instruction insn;
481 if (insn.mem_format.opcode == op_stw ||
482 insn.mem_format.opcode == op_stb ||
483 insn.mem_format.opcode == op_stq_u)
485 if ((insn.mem_format.opcode >= op_stf) &&
486 (insn.mem_format.opcode <= op_stt))
488 if ((insn.mem_format.opcode >= op_stl) &&
489 (insn.mem_format.opcode <= op_stq_c))
493 if (insn.mem_format.opcode == op_special) {
494 if (insn.mem_format.displacement == op_mb)
502 db_branch_taken(ins, pc, regs)
507 alpha_instruction insn;
511 switch (insn.branch_format.opcode) {
513 * Jump format: target PC is (contents of instruction's "RB") & ~3.
516 newpc = db_register_value(regs, insn.jump_format.rs) & ~3;
520 * Branch format: target PC is
521 * (new PC) + (4 * sign-ext(displacement)).
539 newpc = (insn.branch_format.displacement << 2) + (pc + 4);
543 printf("DDB: db_inst_branch_taken on non-branch!\n");
544 newpc = pc; /* XXX */