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>
68 #include <machine/db_machdep.h>
69 #include <machine/pal.h>
70 #include <machine/prom.h>
72 #include <alpha/alpha/db_instruction.h>
76 #include <ddb/db_access.h>
77 #include <ddb/db_sym.h>
78 #include <ddb/db_variables.h>
79 #include <machine/setjmp.h>
81 static jmp_buf *db_nofault = 0;
82 extern jmp_buf db_jmpbuf;
84 extern void gdb_handle_exception __P((db_regs_t *, int, int));
87 extern char *trap_type[];
88 extern int trap_types;
93 void ddbprinttrap __P((unsigned long, unsigned long, unsigned long,
96 struct db_variable db_regs[] = {
97 { "v0", &ddb_regs.tf_regs[FRAME_V0], FCN_NULL },
98 { "t0", &ddb_regs.tf_regs[FRAME_T0], FCN_NULL },
99 { "t1", &ddb_regs.tf_regs[FRAME_T1], FCN_NULL },
100 { "t2", &ddb_regs.tf_regs[FRAME_T2], FCN_NULL },
101 { "t3", &ddb_regs.tf_regs[FRAME_T3], FCN_NULL },
102 { "t4", &ddb_regs.tf_regs[FRAME_T4], FCN_NULL },
103 { "t5", &ddb_regs.tf_regs[FRAME_T5], FCN_NULL },
104 { "t6", &ddb_regs.tf_regs[FRAME_T6], FCN_NULL },
105 { "t7", &ddb_regs.tf_regs[FRAME_T7], FCN_NULL },
106 { "s0", &ddb_regs.tf_regs[FRAME_S0], FCN_NULL },
107 { "s1", &ddb_regs.tf_regs[FRAME_S1], FCN_NULL },
108 { "s2", &ddb_regs.tf_regs[FRAME_S2], FCN_NULL },
109 { "s3", &ddb_regs.tf_regs[FRAME_S3], FCN_NULL },
110 { "s4", &ddb_regs.tf_regs[FRAME_S4], FCN_NULL },
111 { "s5", &ddb_regs.tf_regs[FRAME_S5], FCN_NULL },
112 { "s6", &ddb_regs.tf_regs[FRAME_S6], FCN_NULL },
113 { "a0", &ddb_regs.tf_regs[FRAME_A0], FCN_NULL },
114 { "a1", &ddb_regs.tf_regs[FRAME_A1], FCN_NULL },
115 { "a2", &ddb_regs.tf_regs[FRAME_A2], FCN_NULL },
116 { "a3", &ddb_regs.tf_regs[FRAME_A3], FCN_NULL },
117 { "a4", &ddb_regs.tf_regs[FRAME_A4], FCN_NULL },
118 { "a5", &ddb_regs.tf_regs[FRAME_A5], FCN_NULL },
119 { "t8", &ddb_regs.tf_regs[FRAME_T8], FCN_NULL },
120 { "t9", &ddb_regs.tf_regs[FRAME_T9], FCN_NULL },
121 { "t10", &ddb_regs.tf_regs[FRAME_T10], FCN_NULL },
122 { "t11", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
123 { "ra", &ddb_regs.tf_regs[FRAME_RA], FCN_NULL },
124 { "t12", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
125 { "at", &ddb_regs.tf_regs[FRAME_AT], FCN_NULL },
126 { "gp", &ddb_regs.tf_regs[FRAME_GP], FCN_NULL },
127 { "sp", &ddb_regs.tf_regs[FRAME_SP], FCN_NULL },
128 { "pc", &ddb_regs.tf_regs[FRAME_PC], FCN_NULL },
129 { "ps", &ddb_regs.tf_regs[FRAME_PS], FCN_NULL },
130 { "ai", &ddb_regs.tf_regs[FRAME_T11], FCN_NULL },
131 { "pv", &ddb_regs.tf_regs[FRAME_T12], FCN_NULL },
133 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
139 ddbprinttrap(a0, a1, a2, entry)
140 unsigned long a0, a1, a2, entry;
145 printf("ddbprinttrap(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n", a0, a1, a2,
150 * ddb_trap - field a kernel trap
153 kdb_trap(a0, a1, a2, entry, regs)
154 unsigned long a0, a1, a2, entry;
157 int ddb_mode = !(boothowto & RB_GDB);
161 * Don't bother checking for usermode, since a benign entry
162 * by the kernel (call to Debugger() or a breakpoint) has
163 * already checked for usermode. If neither of those
164 * conditions exist, something Bad has happened.
167 if (entry != ALPHA_KENTRY_IF ||
168 (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT
169 && a0 != ALPHA_IF_CODE_GENTRAP)) {
172 db_printf("ddbprinttrap from 0x%lx\n", /* XXX */
173 regs->tf_regs[FRAME_PC]);
174 ddbprinttrap(a0, a1, a2, entry);
176 * Tell caller "We did NOT handle the trap."
177 * Caller should panic, or whatever.
183 jmp_buf *no_fault = db_nofault;
185 longjmp(*no_fault, 1);
190 * XXX Should switch to DDB's own stack, here.
195 s = cpu_critical_enter();
199 db_printf("stopping %x\n", PCPU_GET(other_cpus));
201 stop_cpus(PCPU_GET(other_cpus));
203 db_printf("stopped_cpus=%x\n", stopped_cpus);
210 cndbctl(TRUE); /* DDB active, unblank video */
211 db_trap(entry, a0); /* Where the work happens */
212 cndbctl(FALSE); /* DDB inactive */
214 gdb_handle_exception(&ddb_regs, entry, a0);
219 restart_cpus(stopped_cpus);
222 cpu_critical_exit(s);
227 * Tell caller "We HAVE handled the trap."
233 * Read bytes from kernel address space for debugger.
236 db_read_bytes(addr, size, data)
238 register size_t size;
243 db_nofault = &db_jmpbuf;
253 * Write bytes to kernel address space for debugger.
256 db_write_bytes(addr, size, data)
258 register size_t size;
263 db_nofault = &db_jmpbuf;
274 Debugger(const char* msg)
279 saveintr = alpha_pal_swpipl(ALPHA_PSL_IPL_HIGH);
280 __asm("call_pal 0x81"); /* XXX bugchk */
281 alpha_pal_swpipl(saveintr);
285 * Alpha-specific ddb commands:
287 * halt set halt bit in rpb and halt
288 * reboot set reboot bit in rpb and halt
291 DB_COMMAND(halt, db_mach_halt)
297 DB_COMMAND(reboot, db_mach_reboot)
303 * Map Alpha register numbers to trapframe/db_regs_t offsets.
305 static int reg_to_frame[32] = {
344 db_register_value(regs, regno)
349 if (regno > 31 || regno < 0) {
350 db_printf(" **** STRANGE REGISTER NUMBER %d **** ", regno);
357 return (regs->tf_regs[reg_to_frame[regno]]);
361 * Support functions for software single-step.
368 alpha_instruction insn;
371 return ((insn.branch_format.opcode == op_bsr) ||
372 ((insn.jump_format.opcode == op_j) &&
373 (insn.jump_format.action & 1)));
380 alpha_instruction insn;
383 return ((insn.jump_format.opcode == op_j) &&
384 (insn.jump_format.action == op_ret));
388 db_inst_trap_return(ins)
391 alpha_instruction insn;
394 return ((insn.pal_format.opcode == op_pal) &&
395 (insn.pal_format.function == PAL_OSF1_rti));
402 alpha_instruction insn;
405 switch (insn.branch_format.opcode) {
429 db_inst_unconditional_flow_transfer(ins)
432 alpha_instruction insn;
435 switch (insn.branch_format.opcode) {
441 switch (insn.pal_format.function) {
442 case PAL_OSF1_retsys:
444 case PAL_OSF1_callsys:
454 db_inst_spill(ins, regn)
457 alpha_instruction insn;
460 return ((insn.mem_format.opcode == op_stq) &&
461 (insn.mem_format.rd == regn));
469 alpha_instruction insn;
474 if (insn.mem_format.opcode == op_ldbu ||
475 insn.mem_format.opcode == op_ldq_u ||
476 insn.mem_format.opcode == op_ldwu)
478 if ((insn.mem_format.opcode >= op_ldf) &&
479 (insn.mem_format.opcode <= op_ldt))
481 if ((insn.mem_format.opcode >= op_ldl) &&
482 (insn.mem_format.opcode <= op_ldq_l))
486 if (insn.mem_format.opcode == op_special) {
487 /* Note: MB is treated as a store. */
488 if ((insn.mem_format.displacement == (short)op_fetch) ||
489 (insn.mem_format.displacement == (short)op_fetch_m))
500 alpha_instruction insn;
505 if (insn.mem_format.opcode == op_stw ||
506 insn.mem_format.opcode == op_stb ||
507 insn.mem_format.opcode == op_stq_u)
509 if ((insn.mem_format.opcode >= op_stf) &&
510 (insn.mem_format.opcode <= op_stt))
512 if ((insn.mem_format.opcode >= op_stl) &&
513 (insn.mem_format.opcode <= op_stq_c))
517 if (insn.mem_format.opcode == op_special) {
518 if (insn.mem_format.displacement == op_mb)
526 db_branch_taken(ins, pc, regs)
531 alpha_instruction insn;
535 switch (insn.branch_format.opcode) {
537 * Jump format: target PC is (contents of instruction's "RB") & ~3.
540 newpc = db_register_value(regs, insn.jump_format.rs) & ~3;
544 * Branch format: target PC is
545 * (new PC) + (4 * sign-ext(displacement)).
563 newpc = (insn.branch_format.displacement << 2) + (pc + 4);
567 printf("DDB: db_inst_branch_taken on non-branch!\n");
568 newpc = pc; /* XXX */
575 db_show_mdpcpu(struct pcpu *pc)
578 db_printf("ipis = 0x%lx\n", pc->pc_pending_ipis);
579 db_printf("next ASN = %d\n", pc->pc_next_asn);