]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/ia64/ia64/db_machdep.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / ia64 / ia64 / db_machdep.c
1 /*-
2  * Copyright (c) 2003-2005 Marcel Moolenaar
3  * Copyright (c) 2000-2001 Doug Rabson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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.
15  *
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
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "opt_xtrace.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/cons.h>
37 #include <sys/kdb.h>
38 #include <sys/ktr.h>
39 #include <sys/kernel.h>
40 #include <sys/proc.h>
41 #include <sys/reboot.h>
42 #include <sys/smp.h>
43 #include <sys/stack.h>
44
45 #include <vm/vm.h>
46
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>
56
57 #include <ddb/ddb.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>
62
63 #include <ia64/disasm/disasm.h>
64
65 #define TMPL_BITS       5
66 #define TMPL_MASK       ((1 << TMPL_BITS) - 1)
67 #define SLOT_BITS       41
68 #define SLOT_COUNT      3
69 #define SLOT_MASK       ((1ULL << SLOT_BITS) - 1ULL)
70 #define SLOT_SHIFT(i)   (TMPL_BITS+((i)<<3)+(i))
71
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);
74
75 register uint64_t __db_gp __asm__("gp");
76
77 static db_varfcn_t db_frame;
78 static db_varfcn_t db_getip;
79 static db_varfcn_t db_getrse;
80
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},
222 };
223 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
224
225 static int
226 db_backtrace(struct thread *td, struct pcb *pcb, int count)
227 {
228         struct unw_regstate rs;
229         struct trapframe *tf;
230         const char *name;
231         db_expr_t offset;
232         uint64_t bsp, cfm, ip, pfs, reg, sp;
233         c_db_sym_t sym;
234         int args, error, i;
235
236         error = unw_create_from_pcb(&rs, pcb);
237         while (!error && count-- && !db_pager_quit) {
238                 error = unw_get_cfm(&rs, &cfm);
239                 if (!error)
240                         error = unw_get_bsp(&rs, &bsp);
241                 if (!error)
242                         error = unw_get_ip(&rs, &ip);
243                 if (!error)
244                         error = unw_get_sp(&rs, &sp);
245                 if (error)
246                         break;
247
248                 args = IA64_CFM_SOL(cfm);
249                 if (args > 8)
250                         args = 8;
251
252                 error = unw_step(&rs);
253                 if (!error) {
254                         if (!unw_get_cfm(&rs, &pfs)) {
255                                 i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs);
256                                 if (args > i)
257                                         args = i;
258                         }
259                 }
260
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)
267                                         bsp += 8;
268                                 db_read_bytes(bsp, sizeof(reg), (void*)&reg);
269                                 if (i > 0)
270                                         db_printf(", ");
271                                 db_printf("0x%lx", reg);
272                                 bsp += 8;
273                         }
274                 } else
275                         db_printf("...");
276                 db_printf(") at ");
277
278                 db_printsym(ip, DB_STGY_PROC);
279                 db_printf("\n");
280
281                 if (error != ERESTART)
282                         continue;
283                 if (sp < IA64_RR_BASE(5))
284                         break;
285
286                 tf = (struct trapframe *)(sp + 16);
287                 if ((tf->tf_flags & FRAME_SYSCALL) != 0 ||
288                     tf->tf_special.iip < IA64_RR_BASE(5))
289                         break;
290
291                 /* XXX ask if we should unwind across the trapframe. */
292                 db_printf("--- trapframe at %p\n", tf);
293                 unw_delete(&rs);
294                 error = unw_create_from_frame(&rs, tf);
295         }
296
297         unw_delete(&rs);
298         /*
299          * EJUSTRETURN and ERESTART signal the end of a trace and
300          * are not really errors.
301          */
302         return ((error > 0) ? error : 0);
303 }
304
305 void
306 db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage)
307 {
308         BKPT_INST_TYPE tmp;
309         db_addr_t loc;
310         int slot;
311
312         slot = addr & 0xfUL;
313         if (slot >= SLOT_COUNT)
314                 return;
315         loc = (addr & ~0xfUL) + (slot << 2);
316
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);
321 }
322
323 void
324 db_bkpt_skip(void)
325 {
326
327         if (kdb_frame == NULL)
328                 return;
329
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;
334         }
335 }
336
337 void
338 db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage)
339 {
340         BKPT_INST_TYPE tmp;
341         db_addr_t loc;
342         int slot;
343
344         slot = addr & 0xfUL;
345         if (slot >= SLOT_COUNT)
346                 return;
347         loc = (addr & ~0xfUL) + (slot << 2);
348
349         db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
350         *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK;
351
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);
355 }
356
357 db_addr_t
358 db_disasm(db_addr_t loc, boolean_t altfmt)
359 {
360         char buf[32];
361         struct asm_bundle bundle;
362         const struct asm_inst *i;
363         const char *tmpl;
364         int n, slot;
365
366         slot = loc & 0xf;
367         loc &= ~0xful;
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] == ';'))
373                         tmpl++;
374                 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
375                         db_printf("\n");
376                         goto out;
377                 }
378
379                 /* Unit + slot. */
380                 db_printf("[%c%d] ", *tmpl, slot);
381
382                 /* Predicate. */
383                 if (i->i_oper[0].o_value != 0) {
384                         asm_operand(i->i_oper+0, buf, loc);
385                         db_printf("(%s) ", buf);
386                 } else
387                         db_printf("   ");
388
389                 /* Mnemonic & completers. */
390                 asm_mnemonic(i->i_op, buf);
391                 db_printf(buf);
392                 n = 0;
393                 while (n < i->i_ncmpltrs) {
394                         asm_completer(i->i_cmpltr + n, buf);
395                         db_printf(buf);
396                         n++;
397                 }
398                 db_printf(" ");
399
400                 /* Operands. */
401                 n = 1;
402                 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
403                         if (n > 1) {
404                                 if (n == i->i_srcidx)
405                                         db_printf("=");
406                                 else
407                                         db_printf(",");
408                         }
409                         asm_operand(i->i_oper + n, buf, loc);
410                         db_printf(buf);
411                         n++;
412                 }
413                 if (tmpl[1] == ';')
414                         db_printf(" ;;");
415         } else {
416                 tmpl = NULL;
417                 slot = 2;
418         }
419         db_printf("\n");
420
421 out:
422         slot++;
423         if (slot == 1 && tmpl[1] == 'L')
424                 slot++;
425         if (slot > 2)
426                 slot = 16;
427         return (loc + slot);
428 }
429
430 int
431 db_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
432 {
433         struct ia64_fdesc fdesc;
434         __db_f *f;
435
436         f = (__db_f *)&fdesc;
437         fdesc.func = addr;
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],
440             args[6], args[7]);
441         return (1);
442 }
443
444 static int
445 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
446 {
447         uint64_t *reg;
448
449         if (kdb_frame == NULL)
450                 return (0);
451         reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
452         if (op == DB_VAR_GET)
453                 *valuep = *reg;
454         else
455                 *reg = *valuep;
456         return (1);
457 }
458
459 static int
460 db_getip(struct db_variable *vp, db_expr_t *valuep, int op)
461 {
462         u_long iip, slot;
463
464         if (kdb_frame == NULL)
465                 return (0);
466
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;
471         } else {
472                 iip = *valuep & ~0xf;
473                 slot = *valuep & 0xf;
474                 if (slot > 2)
475                         return (0);
476                 kdb_frame->tf_special.iip = iip;
477                 kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
478                 kdb_frame->tf_special.psr |= slot << 41;
479         }
480         return (1);
481 }
482
483 static int
484 db_getrse(struct db_variable *vp, db_expr_t *valuep, int op)
485 {
486         u_int64_t *reg;
487         uint64_t bsp;
488         int nats, regno, sof;
489
490         if (kdb_frame == NULL)
491                 return (0);
492
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);
496
497         if (regno >= sof)
498                 return (0);
499
500         nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
501         reg = (void*)(bsp - ((sof - regno + nats) << 3));
502         if (op == DB_VAR_GET)
503                 *valuep = *reg;
504         else
505                 *reg = *valuep;
506         return (1);
507 }
508
509 int
510 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
511 {
512
513         return (-1);
514 }
515
516 void
517 db_md_list_watchpoints()
518 {
519
520         return;
521 }
522
523 int
524 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
525 {
526
527         return (-1);
528 }
529
530 /*
531  * Read bytes from kernel address space for debugger.
532  */
533 int
534 db_read_bytes(vm_offset_t addr, size_t size, char *data)
535 {
536         jmp_buf jb;
537         void *prev_jb;
538         char *src;
539         int ret;
540
541         prev_jb = kdb_jmpbuf(jb);
542         ret = setjmp(jb);
543         if (ret == 0) {
544                 src = (char *)addr;
545                 while (size-- > 0)
546                         *data++ = *src++;
547         }
548         (void)kdb_jmpbuf(prev_jb);
549         return (ret);
550 }
551
552 /*
553  * Write bytes to kernel address space for debugger.
554  */
555 int
556 db_write_bytes(vm_offset_t addr, size_t size, char *data)
557 {
558         jmp_buf jb;
559         void *prev_jb;
560         size_t cnt;
561         char *dst;
562         int ret;
563
564         prev_jb = kdb_jmpbuf(jb);
565         ret = setjmp(jb);
566         if (ret == 0) {
567                 dst = (char *)addr;
568                 cnt = size;
569                 while (cnt-- > 0)
570                         *dst++ = *data++;
571                 kdb_cpu_sync_icache((void *)addr, size);
572         }
573         (void)kdb_jmpbuf(prev_jb);
574         return (ret);
575 }
576
577 void
578 db_show_mdpcpu(struct pcpu *pc)
579 {
580         struct pcpu_md *md = &pc->pc_md;
581
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);
587 }
588
589 void
590 db_trace_self(void)
591 {
592         struct pcb pcb;
593
594         savectx(&pcb);
595         db_backtrace(curthread, &pcb, -1);
596 }
597
598 int
599 db_trace_thread(struct thread *td, int count)
600 {
601         struct pcb *ctx;
602
603         ctx = kdb_thr_ctx(td);
604         return (db_backtrace(td, ctx, count));
605 }
606
607 #ifdef EXCEPTION_TRACING
608
609 extern long xtrace[];
610 extern long *xhead;
611
612 DB_COMMAND(xtrace, db_xtrace)
613 {
614         long *p;
615
616         p = (*xhead == 0) ? xtrace : xhead;
617
618         db_printf("ITC\t\t IVT\t\t  IIP\t\t   IFA\t\t    ISR\n");
619         if (*p == 0)
620                 return;
621
622         do {
623                 db_printf("%016lx %016lx %016lx %016lx %016lx\n", p[0], p[1],
624                     p[2], p[3], p[4]);
625                 p += 5;
626                 if (p == (void *)&xhead)
627                         p = xtrace;
628         } while (p != xhead);
629 }
630
631 #endif