2 * Copyright (c) 2003-2005 Marcel Moolenaar
3 * Copyright (c) 2000-2001 Doug Rabson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_xtrace.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
39 #include <sys/kernel.h>
41 #include <sys/reboot.h>
43 #include <sys/stack.h>
47 #include <machine/db_machdep.h>
48 #include <machine/frame.h>
49 #include <machine/kdb.h>
50 #include <machine/md_var.h>
51 #include <machine/mutex.h>
52 #include <machine/pcb.h>
53 #include <machine/setjmp.h>
54 #include <machine/unwind.h>
55 #include <machine/vmparam.h>
58 #include <ddb/db_access.h>
59 #include <ddb/db_output.h>
60 #include <ddb/db_sym.h>
61 #include <ddb/db_variables.h>
63 #include <ia64/disasm/disasm.h>
66 #define TMPL_MASK ((1 << TMPL_BITS) - 1)
69 #define SLOT_MASK ((1ULL << SLOT_BITS) - 1ULL)
70 #define SLOT_SHIFT(i) (TMPL_BITS+((i)<<3)+(i))
72 typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t,
73 db_expr_t, db_expr_t, db_expr_t);
75 register uint64_t __db_gp __asm__("gp");
77 static db_varfcn_t db_frame;
78 static db_varfcn_t db_getip;
79 static db_varfcn_t db_getrse;
81 #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
82 struct db_variable db_regs[] = {
83 {"ip", NULL, db_getip},
84 {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame},
85 {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame},
86 {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame},
87 {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame},
88 {"rp", DB_OFFSET(tf_special.rp), db_frame},
89 {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame},
90 {"psr", DB_OFFSET(tf_special.psr), db_frame},
91 {"cr.isr", DB_OFFSET(tf_special.isr), db_frame},
92 {"pr", DB_OFFSET(tf_special.pr), db_frame},
93 {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame},
94 {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame},
95 {"ar.unat", DB_OFFSET(tf_special.unat), db_frame},
96 {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame},
97 {"gp", DB_OFFSET(tf_special.gp), db_frame},
98 {"sp", DB_OFFSET(tf_special.sp), db_frame},
99 {"tp", DB_OFFSET(tf_special.tp), db_frame},
100 {"b6", DB_OFFSET(tf_scratch.br6), db_frame},
101 {"b7", DB_OFFSET(tf_scratch.br7), db_frame},
102 {"r2", DB_OFFSET(tf_scratch.gr2), db_frame},
103 {"r3", DB_OFFSET(tf_scratch.gr3), db_frame},
104 {"r8", DB_OFFSET(tf_scratch.gr8), db_frame},
105 {"r9", DB_OFFSET(tf_scratch.gr9), db_frame},
106 {"r10", DB_OFFSET(tf_scratch.gr10), db_frame},
107 {"r11", DB_OFFSET(tf_scratch.gr11), db_frame},
108 {"r14", DB_OFFSET(tf_scratch.gr14), db_frame},
109 {"r15", DB_OFFSET(tf_scratch.gr15), db_frame},
110 {"r16", DB_OFFSET(tf_scratch.gr16), db_frame},
111 {"r17", DB_OFFSET(tf_scratch.gr17), db_frame},
112 {"r18", DB_OFFSET(tf_scratch.gr18), db_frame},
113 {"r19", DB_OFFSET(tf_scratch.gr19), db_frame},
114 {"r20", DB_OFFSET(tf_scratch.gr20), db_frame},
115 {"r21", DB_OFFSET(tf_scratch.gr21), db_frame},
116 {"r22", DB_OFFSET(tf_scratch.gr22), db_frame},
117 {"r23", DB_OFFSET(tf_scratch.gr23), db_frame},
118 {"r24", DB_OFFSET(tf_scratch.gr24), db_frame},
119 {"r25", DB_OFFSET(tf_scratch.gr25), db_frame},
120 {"r26", DB_OFFSET(tf_scratch.gr26), db_frame},
121 {"r27", DB_OFFSET(tf_scratch.gr27), db_frame},
122 {"r28", DB_OFFSET(tf_scratch.gr28), db_frame},
123 {"r29", DB_OFFSET(tf_scratch.gr29), db_frame},
124 {"r30", DB_OFFSET(tf_scratch.gr30), db_frame},
125 {"r31", DB_OFFSET(tf_scratch.gr31), db_frame},
126 {"r32", (db_expr_t*)0, db_getrse},
127 {"r33", (db_expr_t*)1, db_getrse},
128 {"r34", (db_expr_t*)2, db_getrse},
129 {"r35", (db_expr_t*)3, db_getrse},
130 {"r36", (db_expr_t*)4, db_getrse},
131 {"r37", (db_expr_t*)5, db_getrse},
132 {"r38", (db_expr_t*)6, db_getrse},
133 {"r39", (db_expr_t*)7, db_getrse},
134 {"r40", (db_expr_t*)8, db_getrse},
135 {"r41", (db_expr_t*)9, db_getrse},
136 {"r42", (db_expr_t*)10, db_getrse},
137 {"r43", (db_expr_t*)11, db_getrse},
138 {"r44", (db_expr_t*)12, db_getrse},
139 {"r45", (db_expr_t*)13, db_getrse},
140 {"r46", (db_expr_t*)14, db_getrse},
141 {"r47", (db_expr_t*)15, db_getrse},
142 {"r48", (db_expr_t*)16, db_getrse},
143 {"r49", (db_expr_t*)17, db_getrse},
144 {"r50", (db_expr_t*)18, db_getrse},
145 {"r51", (db_expr_t*)19, db_getrse},
146 {"r52", (db_expr_t*)20, db_getrse},
147 {"r53", (db_expr_t*)21, db_getrse},
148 {"r54", (db_expr_t*)22, db_getrse},
149 {"r55", (db_expr_t*)23, db_getrse},
150 {"r56", (db_expr_t*)24, db_getrse},
151 {"r57", (db_expr_t*)25, db_getrse},
152 {"r58", (db_expr_t*)26, db_getrse},
153 {"r59", (db_expr_t*)27, db_getrse},
154 {"r60", (db_expr_t*)28, db_getrse},
155 {"r61", (db_expr_t*)29, db_getrse},
156 {"r62", (db_expr_t*)30, db_getrse},
157 {"r63", (db_expr_t*)31, db_getrse},
158 {"r64", (db_expr_t*)32, db_getrse},
159 {"r65", (db_expr_t*)33, db_getrse},
160 {"r66", (db_expr_t*)34, db_getrse},
161 {"r67", (db_expr_t*)35, db_getrse},
162 {"r68", (db_expr_t*)36, db_getrse},
163 {"r69", (db_expr_t*)37, db_getrse},
164 {"r70", (db_expr_t*)38, db_getrse},
165 {"r71", (db_expr_t*)39, db_getrse},
166 {"r72", (db_expr_t*)40, db_getrse},
167 {"r73", (db_expr_t*)41, db_getrse},
168 {"r74", (db_expr_t*)42, db_getrse},
169 {"r75", (db_expr_t*)43, db_getrse},
170 {"r76", (db_expr_t*)44, db_getrse},
171 {"r77", (db_expr_t*)45, db_getrse},
172 {"r78", (db_expr_t*)46, db_getrse},
173 {"r79", (db_expr_t*)47, db_getrse},
174 {"r80", (db_expr_t*)48, db_getrse},
175 {"r81", (db_expr_t*)49, db_getrse},
176 {"r82", (db_expr_t*)50, db_getrse},
177 {"r83", (db_expr_t*)51, db_getrse},
178 {"r84", (db_expr_t*)52, db_getrse},
179 {"r85", (db_expr_t*)53, db_getrse},
180 {"r86", (db_expr_t*)54, db_getrse},
181 {"r87", (db_expr_t*)55, db_getrse},
182 {"r88", (db_expr_t*)56, db_getrse},
183 {"r89", (db_expr_t*)57, db_getrse},
184 {"r90", (db_expr_t*)58, db_getrse},
185 {"r91", (db_expr_t*)59, db_getrse},
186 {"r92", (db_expr_t*)60, db_getrse},
187 {"r93", (db_expr_t*)61, db_getrse},
188 {"r94", (db_expr_t*)62, db_getrse},
189 {"r95", (db_expr_t*)63, db_getrse},
190 {"r96", (db_expr_t*)64, db_getrse},
191 {"r97", (db_expr_t*)65, db_getrse},
192 {"r98", (db_expr_t*)66, db_getrse},
193 {"r99", (db_expr_t*)67, db_getrse},
194 {"r100", (db_expr_t*)68, db_getrse},
195 {"r101", (db_expr_t*)69, db_getrse},
196 {"r102", (db_expr_t*)70, db_getrse},
197 {"r103", (db_expr_t*)71, db_getrse},
198 {"r104", (db_expr_t*)72, db_getrse},
199 {"r105", (db_expr_t*)73, db_getrse},
200 {"r106", (db_expr_t*)74, db_getrse},
201 {"r107", (db_expr_t*)75, db_getrse},
202 {"r108", (db_expr_t*)76, db_getrse},
203 {"r109", (db_expr_t*)77, db_getrse},
204 {"r110", (db_expr_t*)78, db_getrse},
205 {"r111", (db_expr_t*)79, db_getrse},
206 {"r112", (db_expr_t*)80, db_getrse},
207 {"r113", (db_expr_t*)81, db_getrse},
208 {"r114", (db_expr_t*)82, db_getrse},
209 {"r115", (db_expr_t*)83, db_getrse},
210 {"r116", (db_expr_t*)84, db_getrse},
211 {"r117", (db_expr_t*)85, db_getrse},
212 {"r118", (db_expr_t*)86, db_getrse},
213 {"r119", (db_expr_t*)87, db_getrse},
214 {"r120", (db_expr_t*)88, db_getrse},
215 {"r121", (db_expr_t*)89, db_getrse},
216 {"r122", (db_expr_t*)90, db_getrse},
217 {"r123", (db_expr_t*)91, db_getrse},
218 {"r124", (db_expr_t*)92, db_getrse},
219 {"r125", (db_expr_t*)93, db_getrse},
220 {"r126", (db_expr_t*)94, db_getrse},
221 {"r127", (db_expr_t*)95, db_getrse},
223 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
226 db_backtrace(struct thread *td, struct pcb *pcb, int count)
228 struct unw_regstate rs;
229 struct trapframe *tf;
232 uint64_t bsp, cfm, ip, pfs, reg, sp;
236 error = unw_create_from_pcb(&rs, pcb);
237 while (!error && count-- && !db_pager_quit) {
238 error = unw_get_cfm(&rs, &cfm);
240 error = unw_get_bsp(&rs, &bsp);
242 error = unw_get_ip(&rs, &ip);
244 error = unw_get_sp(&rs, &sp);
248 args = IA64_CFM_SOL(cfm);
252 error = unw_step(&rs);
254 if (!unw_get_cfm(&rs, &pfs)) {
255 i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs);
261 sym = db_search_symbol(ip, DB_STGY_ANY, &offset);
262 db_symbol_values(sym, &name, NULL);
263 db_printf("%s(", name);
264 if (bsp >= IA64_RR_BASE(5)) {
265 for (i = 0; i < args; i++) {
266 if ((bsp & 0x1ff) == 0x1f8)
268 db_read_bytes(bsp, sizeof(reg), (void*)®);
271 db_printf("0x%lx", reg);
278 db_printsym(ip, DB_STGY_PROC);
281 if (error != ERESTART)
283 if (sp < IA64_RR_BASE(5))
286 tf = (struct trapframe *)(sp + 16);
287 if ((tf->tf_flags & FRAME_SYSCALL) != 0 ||
288 tf->tf_special.iip < IA64_RR_BASE(5))
291 /* XXX ask if we should unwind across the trapframe. */
292 db_printf("--- trapframe at %p\n", tf);
294 error = unw_create_from_frame(&rs, tf);
299 * EJUSTRETURN and ERESTART signal the end of a trace and
300 * are not really errors.
302 return ((error > 0) ? error : 0);
306 db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage)
313 if (slot >= SLOT_COUNT)
315 loc = (addr & ~0xfUL) + (slot << 2);
317 db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
318 tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
319 tmp |= *storage << SLOT_SHIFT(slot);
320 db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
327 if (kdb_frame == NULL)
330 kdb_frame->tf_special.psr += IA64_PSR_RI_1;
331 if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
332 kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
333 kdb_frame->tf_special.iip += 16;
338 db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage)
345 if (slot >= SLOT_COUNT)
347 loc = (addr & ~0xfUL) + (slot << 2);
349 db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
350 *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK;
352 tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
353 tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
354 db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
358 db_disasm(db_addr_t loc, boolean_t altfmt)
361 struct asm_bundle bundle;
362 const struct asm_inst *i;
368 db_read_bytes(loc, 16, buf);
369 if (asm_decode((uintptr_t)buf, &bundle)) {
370 i = bundle.b_inst + slot;
371 tmpl = bundle.b_templ + slot;
372 if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';'))
374 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
380 db_printf("[%c%d] ", *tmpl, slot);
383 if (i->i_oper[0].o_value != 0) {
384 asm_operand(i->i_oper+0, buf, loc);
385 db_printf("(%s) ", buf);
389 /* Mnemonic & completers. */
390 asm_mnemonic(i->i_op, buf);
393 while (n < i->i_ncmpltrs) {
394 asm_completer(i->i_cmpltr + n, buf);
402 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
404 if (n == i->i_srcidx)
409 asm_operand(i->i_oper + n, buf, loc);
423 if (slot == 1 && tmpl[1] == 'L')
431 db_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
433 struct ia64_fdesc fdesc;
436 f = (__db_f *)&fdesc;
438 fdesc.gp = __db_gp; /* XXX doesn't work for modules. */
439 *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
445 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
449 if (kdb_frame == NULL)
451 reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
452 if (op == DB_VAR_GET)
460 db_getip(struct db_variable *vp, db_expr_t *valuep, int op)
464 if (kdb_frame == NULL)
467 if (op == DB_VAR_GET) {
468 iip = kdb_frame->tf_special.iip;
469 slot = (kdb_frame->tf_special.psr >> 41) & 3;
470 *valuep = iip + slot;
472 iip = *valuep & ~0xf;
473 slot = *valuep & 0xf;
476 kdb_frame->tf_special.iip = iip;
477 kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
478 kdb_frame->tf_special.psr |= slot << 41;
484 db_getrse(struct db_variable *vp, db_expr_t *valuep, int op)
488 int nats, regno, sof;
490 if (kdb_frame == NULL)
493 regno = (int)(intptr_t)valuep;
494 bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty;
495 sof = (int)(kdb_frame->tf_special.cfm & 0x7f);
500 nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
501 reg = (void*)(bsp - ((sof - regno + nats) << 3));
502 if (op == DB_VAR_GET)
510 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
517 db_md_list_watchpoints()
524 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
531 * Read bytes from kernel address space for debugger.
534 db_read_bytes(vm_offset_t addr, size_t size, char *data)
541 prev_jb = kdb_jmpbuf(jb);
548 (void)kdb_jmpbuf(prev_jb);
553 * Write bytes to kernel address space for debugger.
556 db_write_bytes(vm_offset_t addr, size_t size, char *data)
564 prev_jb = kdb_jmpbuf(jb);
571 kdb_cpu_sync_icache((void *)addr, size);
573 (void)kdb_jmpbuf(prev_jb);
578 db_show_mdpcpu(struct pcpu *pc)
580 struct pcpu_md *md = &pc->pc_md;
582 db_printf("MD: vhpt = %#lx\n", md->vhpt);
583 db_printf("MD: lid = %#lx\n", md->lid);
584 db_printf("MD: clock = %#lx/%#lx\n", md->clock, md->clockadj);
585 db_printf("MD: stats = %p\n", &md->stats);
586 db_printf("MD: pmap = %p\n", md->current_pmap);
595 db_backtrace(curthread, &pcb, -1);
599 db_trace_thread(struct thread *td, int count)
603 ctx = kdb_thr_ctx(td);
604 return (db_backtrace(td, ctx, count));
607 #ifdef EXCEPTION_TRACING
609 extern long xtrace[];
612 DB_COMMAND(xtrace, db_xtrace)
616 p = (*xhead == 0) ? xtrace : xhead;
618 db_printf("ITC\t\t IVT\t\t IIP\t\t IFA\t\t ISR\n");
623 db_printf("%016lx %016lx %016lx %016lx %016lx\n", p[0], p[1],
626 if (p == (void *)&xhead)
628 } while (p != xhead);