]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/ia64/ia64/db_machdep.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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/pcb.h>
52 #include <machine/setjmp.h>
53 #include <machine/unwind.h>
54 #include <machine/vmparam.h>
55
56 #include <ddb/ddb.h>
57 #include <ddb/db_access.h>
58 #include <ddb/db_output.h>
59 #include <ddb/db_sym.h>
60 #include <ddb/db_variables.h>
61
62 #include <ia64/disasm/disasm.h>
63
64 #define TMPL_BITS       5
65 #define TMPL_MASK       ((1 << TMPL_BITS) - 1)
66 #define SLOT_BITS       41
67 #define SLOT_COUNT      3
68 #define SLOT_MASK       ((1ULL << SLOT_BITS) - 1ULL)
69 #define SLOT_SHIFT(i)   (TMPL_BITS+((i)<<3)+(i))
70
71 typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t,
72     db_expr_t, db_expr_t, db_expr_t);
73
74 register uint64_t __db_gp __asm__("gp");
75
76 static db_varfcn_t db_frame;
77 static db_varfcn_t db_getip;
78 static db_varfcn_t db_getrse;
79
80 #define DB_OFFSET(x)    (db_expr_t *)offsetof(struct trapframe, x)
81 struct db_variable db_regs[] = {
82         {"ip",          NULL,                           db_getip},
83         {"cr.ifs",      DB_OFFSET(tf_special.cfm),      db_frame},
84         {"cr.ifa",      DB_OFFSET(tf_special.ifa),      db_frame},
85         {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame},
86         {"ndirty",      DB_OFFSET(tf_special.ndirty),   db_frame},
87         {"rp",          DB_OFFSET(tf_special.rp),       db_frame},
88         {"ar.pfs",      DB_OFFSET(tf_special.pfs),      db_frame},
89         {"psr",         DB_OFFSET(tf_special.psr),      db_frame},
90         {"cr.isr",      DB_OFFSET(tf_special.isr),      db_frame},
91         {"pr",          DB_OFFSET(tf_special.pr),       db_frame},
92         {"ar.rsc",      DB_OFFSET(tf_special.rsc),      db_frame},
93         {"ar.rnat",     DB_OFFSET(tf_special.rnat),     db_frame},
94         {"ar.unat",     DB_OFFSET(tf_special.unat),     db_frame},
95         {"ar.fpsr",     DB_OFFSET(tf_special.fpsr),     db_frame},
96         {"gp",          DB_OFFSET(tf_special.gp),       db_frame},
97         {"sp",          DB_OFFSET(tf_special.sp),       db_frame},
98         {"tp",          DB_OFFSET(tf_special.tp),       db_frame},
99         {"b6",          DB_OFFSET(tf_scratch.br6),      db_frame},
100         {"b7",          DB_OFFSET(tf_scratch.br7),      db_frame},
101         {"r2",          DB_OFFSET(tf_scratch.gr2),      db_frame},
102         {"r3",          DB_OFFSET(tf_scratch.gr3),      db_frame},
103         {"r8",          DB_OFFSET(tf_scratch.gr8),      db_frame},
104         {"r9",          DB_OFFSET(tf_scratch.gr9),      db_frame},
105         {"r10",         DB_OFFSET(tf_scratch.gr10),     db_frame},
106         {"r11",         DB_OFFSET(tf_scratch.gr11),     db_frame},
107         {"r14",         DB_OFFSET(tf_scratch.gr14),     db_frame},
108         {"r15",         DB_OFFSET(tf_scratch.gr15),     db_frame},
109         {"r16",         DB_OFFSET(tf_scratch.gr16),     db_frame},
110         {"r17",         DB_OFFSET(tf_scratch.gr17),     db_frame},
111         {"r18",         DB_OFFSET(tf_scratch.gr18),     db_frame},
112         {"r19",         DB_OFFSET(tf_scratch.gr19),     db_frame},
113         {"r20",         DB_OFFSET(tf_scratch.gr20),     db_frame},
114         {"r21",         DB_OFFSET(tf_scratch.gr21),     db_frame},
115         {"r22",         DB_OFFSET(tf_scratch.gr22),     db_frame},
116         {"r23",         DB_OFFSET(tf_scratch.gr23),     db_frame},
117         {"r24",         DB_OFFSET(tf_scratch.gr24),     db_frame},
118         {"r25",         DB_OFFSET(tf_scratch.gr25),     db_frame},
119         {"r26",         DB_OFFSET(tf_scratch.gr26),     db_frame},
120         {"r27",         DB_OFFSET(tf_scratch.gr27),     db_frame},
121         {"r28",         DB_OFFSET(tf_scratch.gr28),     db_frame},
122         {"r29",         DB_OFFSET(tf_scratch.gr29),     db_frame},
123         {"r30",         DB_OFFSET(tf_scratch.gr30),     db_frame},
124         {"r31",         DB_OFFSET(tf_scratch.gr31),     db_frame},
125         {"r32",         (db_expr_t*)0,                  db_getrse},
126         {"r33",         (db_expr_t*)1,                  db_getrse},
127         {"r34",         (db_expr_t*)2,                  db_getrse},
128         {"r35",         (db_expr_t*)3,                  db_getrse},
129         {"r36",         (db_expr_t*)4,                  db_getrse},
130         {"r37",         (db_expr_t*)5,                  db_getrse},
131         {"r38",         (db_expr_t*)6,                  db_getrse},
132         {"r39",         (db_expr_t*)7,                  db_getrse},
133         {"r40",         (db_expr_t*)8,                  db_getrse},
134         {"r41",         (db_expr_t*)9,                  db_getrse},
135         {"r42",         (db_expr_t*)10,                 db_getrse},
136         {"r43",         (db_expr_t*)11,                 db_getrse},
137         {"r44",         (db_expr_t*)12,                 db_getrse},
138         {"r45",         (db_expr_t*)13,                 db_getrse},
139         {"r46",         (db_expr_t*)14,                 db_getrse},
140         {"r47",         (db_expr_t*)15,                 db_getrse},
141         {"r48",         (db_expr_t*)16,                 db_getrse},
142         {"r49",         (db_expr_t*)17,                 db_getrse},
143         {"r50",         (db_expr_t*)18,                 db_getrse},
144         {"r51",         (db_expr_t*)19,                 db_getrse},
145         {"r52",         (db_expr_t*)20,                 db_getrse},
146         {"r53",         (db_expr_t*)21,                 db_getrse},
147         {"r54",         (db_expr_t*)22,                 db_getrse},
148         {"r55",         (db_expr_t*)23,                 db_getrse},
149         {"r56",         (db_expr_t*)24,                 db_getrse},
150         {"r57",         (db_expr_t*)25,                 db_getrse},
151         {"r58",         (db_expr_t*)26,                 db_getrse},
152         {"r59",         (db_expr_t*)27,                 db_getrse},
153         {"r60",         (db_expr_t*)28,                 db_getrse},
154         {"r61",         (db_expr_t*)29,                 db_getrse},
155         {"r62",         (db_expr_t*)30,                 db_getrse},
156         {"r63",         (db_expr_t*)31,                 db_getrse},
157         {"r64",         (db_expr_t*)32,                 db_getrse},
158         {"r65",         (db_expr_t*)33,                 db_getrse},
159         {"r66",         (db_expr_t*)34,                 db_getrse},
160         {"r67",         (db_expr_t*)35,                 db_getrse},
161         {"r68",         (db_expr_t*)36,                 db_getrse},
162         {"r69",         (db_expr_t*)37,                 db_getrse},
163         {"r70",         (db_expr_t*)38,                 db_getrse},
164         {"r71",         (db_expr_t*)39,                 db_getrse},
165         {"r72",         (db_expr_t*)40,                 db_getrse},
166         {"r73",         (db_expr_t*)41,                 db_getrse},
167         {"r74",         (db_expr_t*)42,                 db_getrse},
168         {"r75",         (db_expr_t*)43,                 db_getrse},
169         {"r76",         (db_expr_t*)44,                 db_getrse},
170         {"r77",         (db_expr_t*)45,                 db_getrse},
171         {"r78",         (db_expr_t*)46,                 db_getrse},
172         {"r79",         (db_expr_t*)47,                 db_getrse},
173         {"r80",         (db_expr_t*)48,                 db_getrse},
174         {"r81",         (db_expr_t*)49,                 db_getrse},
175         {"r82",         (db_expr_t*)50,                 db_getrse},
176         {"r83",         (db_expr_t*)51,                 db_getrse},
177         {"r84",         (db_expr_t*)52,                 db_getrse},
178         {"r85",         (db_expr_t*)53,                 db_getrse},
179         {"r86",         (db_expr_t*)54,                 db_getrse},
180         {"r87",         (db_expr_t*)55,                 db_getrse},
181         {"r88",         (db_expr_t*)56,                 db_getrse},
182         {"r89",         (db_expr_t*)57,                 db_getrse},
183         {"r90",         (db_expr_t*)58,                 db_getrse},
184         {"r91",         (db_expr_t*)59,                 db_getrse},
185         {"r92",         (db_expr_t*)60,                 db_getrse},
186         {"r93",         (db_expr_t*)61,                 db_getrse},
187         {"r94",         (db_expr_t*)62,                 db_getrse},
188         {"r95",         (db_expr_t*)63,                 db_getrse},
189         {"r96",         (db_expr_t*)64,                 db_getrse},
190         {"r97",         (db_expr_t*)65,                 db_getrse},
191         {"r98",         (db_expr_t*)66,                 db_getrse},
192         {"r99",         (db_expr_t*)67,                 db_getrse},
193         {"r100",        (db_expr_t*)68,                 db_getrse},
194         {"r101",        (db_expr_t*)69,                 db_getrse},
195         {"r102",        (db_expr_t*)70,                 db_getrse},
196         {"r103",        (db_expr_t*)71,                 db_getrse},
197         {"r104",        (db_expr_t*)72,                 db_getrse},
198         {"r105",        (db_expr_t*)73,                 db_getrse},
199         {"r106",        (db_expr_t*)74,                 db_getrse},
200         {"r107",        (db_expr_t*)75,                 db_getrse},
201         {"r108",        (db_expr_t*)76,                 db_getrse},
202         {"r109",        (db_expr_t*)77,                 db_getrse},
203         {"r110",        (db_expr_t*)78,                 db_getrse},
204         {"r111",        (db_expr_t*)79,                 db_getrse},
205         {"r112",        (db_expr_t*)80,                 db_getrse},
206         {"r113",        (db_expr_t*)81,                 db_getrse},
207         {"r114",        (db_expr_t*)82,                 db_getrse},
208         {"r115",        (db_expr_t*)83,                 db_getrse},
209         {"r116",        (db_expr_t*)84,                 db_getrse},
210         {"r117",        (db_expr_t*)85,                 db_getrse},
211         {"r118",        (db_expr_t*)86,                 db_getrse},
212         {"r119",        (db_expr_t*)87,                 db_getrse},
213         {"r120",        (db_expr_t*)88,                 db_getrse},
214         {"r121",        (db_expr_t*)89,                 db_getrse},
215         {"r122",        (db_expr_t*)90,                 db_getrse},
216         {"r123",        (db_expr_t*)91,                 db_getrse},
217         {"r124",        (db_expr_t*)92,                 db_getrse},
218         {"r125",        (db_expr_t*)93,                 db_getrse},
219         {"r126",        (db_expr_t*)94,                 db_getrse},
220         {"r127",        (db_expr_t*)95,                 db_getrse},
221 };
222 struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
223
224 static int
225 db_backtrace(struct thread *td, struct pcb *pcb, int count)
226 {
227         struct unw_regstate rs;
228         struct trapframe *tf;
229         const char *name;
230         db_expr_t offset;
231         uint64_t bsp, cfm, ip, pfs, reg, sp;
232         c_db_sym_t sym;
233         int args, error, i;
234
235         error = unw_create_from_pcb(&rs, pcb);
236         while (!error && count-- && !db_pager_quit) {
237                 error = unw_get_cfm(&rs, &cfm);
238                 if (!error)
239                         error = unw_get_bsp(&rs, &bsp);
240                 if (!error)
241                         error = unw_get_ip(&rs, &ip);
242                 if (!error)
243                         error = unw_get_sp(&rs, &sp);
244                 if (error)
245                         break;
246
247                 args = IA64_CFM_SOL(cfm);
248                 if (args > 8)
249                         args = 8;
250
251                 error = unw_step(&rs);
252                 if (!error) {
253                         if (!unw_get_cfm(&rs, &pfs)) {
254                                 i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs);
255                                 if (args > i)
256                                         args = i;
257                         }
258                 }
259
260                 sym = db_search_symbol(ip, DB_STGY_ANY, &offset);
261                 db_symbol_values(sym, &name, NULL);
262                 db_printf("%s(", name);
263                 if (bsp >= VM_MAXUSER_ADDRESS) {
264                         for (i = 0; i < args; i++) {
265                                 if ((bsp & 0x1ff) == 0x1f8)
266                                         bsp += 8;
267                                 db_read_bytes(bsp, sizeof(reg), (void*)&reg);
268                                 if (i > 0)
269                                         db_printf(", ");
270                                 db_printf("0x%lx", reg);
271                                 bsp += 8;
272                         }
273                 } else
274                         db_printf("...");
275                 db_printf(") at ");
276
277                 db_printsym(ip, DB_STGY_PROC);
278                 db_printf("\n");
279
280                 if (error != ERESTART)
281                         continue;
282                 if (sp < VM_MAXUSER_ADDRESS)
283                         break;
284
285                 tf = (struct trapframe *)(sp + 16);
286                 if ((tf->tf_flags & FRAME_SYSCALL) != 0 ||
287                     tf->tf_special.iip < VM_MAXUSER_ADDRESS)
288                         break;
289
290                 /* XXX ask if we should unwind across the trapframe. */
291                 db_printf("--- trapframe at %p\n", tf);
292                 unw_delete(&rs);
293                 error = unw_create_from_frame(&rs, tf);
294         }
295
296         unw_delete(&rs);
297         /*
298          * EJUSTRETURN and ERESTART signal the end of a trace and
299          * are not really errors.
300          */
301         return ((error > 0) ? error : 0);
302 }
303
304 void
305 db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage)
306 {
307         BKPT_INST_TYPE tmp;
308         db_addr_t loc;
309         int slot;
310
311         slot = addr & 0xfUL;
312         if (slot >= SLOT_COUNT)
313                 return;
314         loc = (addr & ~0xfUL) + (slot << 2);
315
316         db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
317         tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
318         tmp |= *storage << SLOT_SHIFT(slot);
319         db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
320 }
321
322 void
323 db_bkpt_skip(void)
324 {
325
326         if (kdb_frame == NULL)
327                 return;
328
329         kdb_frame->tf_special.psr += IA64_PSR_RI_1;
330         if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
331                 kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
332                 kdb_frame->tf_special.iip += 16;
333         }
334 }
335
336 void
337 db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage)
338 {
339         BKPT_INST_TYPE tmp;
340         db_addr_t loc;
341         int slot;
342
343         slot = addr & 0xfUL;
344         if (slot >= SLOT_COUNT)
345                 return;
346         loc = (addr & ~0xfUL) + (slot << 2);
347
348         db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
349         *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK;
350
351         tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
352         tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
353         db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
354 }
355
356 db_addr_t
357 db_disasm(db_addr_t loc, boolean_t altfmt)
358 {
359         char buf[32];
360         struct asm_bundle bundle;
361         const struct asm_inst *i;
362         const char *tmpl;
363         int n, slot;
364
365         slot = loc & 0xf;
366         loc &= ~0xful;
367         db_read_bytes(loc, 16, buf);
368         if (asm_decode((uintptr_t)buf, &bundle)) {
369                 i = bundle.b_inst + slot;
370                 tmpl = bundle.b_templ + slot;
371                 if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';'))
372                         tmpl++;
373                 if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
374                         db_printf("\n");
375                         goto out;
376                 }
377
378                 /* Unit + slot. */
379                 db_printf("[%c%d] ", *tmpl, slot);
380
381                 /* Predicate. */
382                 if (i->i_oper[0].o_value != 0) {
383                         asm_operand(i->i_oper+0, buf, loc);
384                         db_printf("(%s) ", buf);
385                 } else
386                         db_printf("   ");
387
388                 /* Mnemonic & completers. */
389                 asm_mnemonic(i->i_op, buf);
390                 db_printf(buf);
391                 n = 0;
392                 while (n < i->i_ncmpltrs) {
393                         asm_completer(i->i_cmpltr + n, buf);
394                         db_printf(buf);
395                         n++;
396                 }
397                 db_printf(" ");
398
399                 /* Operands. */
400                 n = 1;
401                 while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
402                         if (n > 1) {
403                                 if (n == i->i_srcidx)
404                                         db_printf("=");
405                                 else
406                                         db_printf(",");
407                         }
408                         asm_operand(i->i_oper + n, buf, loc);
409                         db_printf(buf);
410                         n++;
411                 }
412                 if (tmpl[1] == ';')
413                         db_printf(" ;;");
414         } else {
415                 tmpl = NULL;
416                 slot = 2;
417         }
418         db_printf("\n");
419
420 out:
421         slot++;
422         if (slot == 1 && tmpl[1] == 'L')
423                 slot++;
424         if (slot > 2)
425                 slot = 16;
426         return (loc + slot);
427 }
428
429 int
430 db_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
431 {
432         struct ia64_fdesc fdesc;
433         __db_f *f;
434
435         f = (__db_f *)&fdesc;
436         fdesc.func = addr;
437         fdesc.gp = __db_gp;     /* XXX doesn't work for modules. */
438         *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
439             args[6], args[7]);
440         return (1);
441 }
442
443 static int
444 db_frame(struct db_variable *vp, db_expr_t *valuep, int op)
445 {
446         uint64_t *reg;
447
448         if (kdb_frame == NULL)
449                 return (0);
450         reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
451         if (op == DB_VAR_GET)
452                 *valuep = *reg;
453         else
454                 *reg = *valuep;
455         return (1);
456 }
457
458 static int
459 db_getip(struct db_variable *vp, db_expr_t *valuep, int op)
460 {
461         u_long iip, slot;
462
463         if (kdb_frame == NULL)
464                 return (0);
465
466         if (op == DB_VAR_GET) {
467                 iip = kdb_frame->tf_special.iip;
468                 slot = (kdb_frame->tf_special.psr >> 41) & 3;
469                 *valuep = iip + slot;
470         } else {
471                 iip = *valuep & ~0xf;
472                 slot = *valuep & 0xf;
473                 if (slot > 2)
474                         return (0);
475                 kdb_frame->tf_special.iip = iip;
476                 kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
477                 kdb_frame->tf_special.psr |= slot << 41;
478         }
479         return (1);
480 }
481
482 static int
483 db_getrse(struct db_variable *vp, db_expr_t *valuep, int op)
484 {
485         u_int64_t *reg;
486         uint64_t bsp;
487         int nats, regno, sof;
488
489         if (kdb_frame == NULL)
490                 return (0);
491
492         regno = (int)(intptr_t)valuep;
493         bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty;
494         sof = (int)(kdb_frame->tf_special.cfm & 0x7f);
495
496         if (regno >= sof)
497                 return (0);
498
499         nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
500         reg = (void*)(bsp - ((sof - regno + nats) << 3));
501         if (op == DB_VAR_GET)
502                 *valuep = *reg;
503         else
504                 *reg = *valuep;
505         return (1);
506 }
507
508 int
509 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
510 {
511
512         return (-1);
513 }
514
515 void
516 db_md_list_watchpoints()
517 {
518
519         return;
520 }
521
522 int
523 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
524 {
525
526         return (-1);
527 }
528
529 /*
530  * Read bytes from kernel address space for debugger.
531  */
532 int
533 db_read_bytes(vm_offset_t addr, size_t size, char *data)
534 {
535         jmp_buf jb;
536         void *prev_jb;
537         char *src;
538         int ret;
539
540         prev_jb = kdb_jmpbuf(jb);
541         ret = setjmp(jb);
542         if (ret == 0) {
543                 src = (char *)addr;
544                 while (size-- > 0)
545                         *data++ = *src++;
546         }
547         (void)kdb_jmpbuf(prev_jb);
548         return (ret);
549 }
550
551 /*
552  * Write bytes to kernel address space for debugger.
553  */
554 int
555 db_write_bytes(vm_offset_t addr, size_t size, char *data)
556 {
557         jmp_buf jb;
558         void *prev_jb;
559         size_t cnt;
560         char *dst;
561         int ret;
562
563         prev_jb = kdb_jmpbuf(jb);
564         ret = setjmp(jb);
565         if (ret == 0) {
566                 dst = (char *)addr;
567                 cnt = size;
568                 while (cnt-- > 0)
569                         *dst++ = *data++;
570                 kdb_cpu_sync_icache((void *)addr, size);
571         }
572         (void)kdb_jmpbuf(prev_jb);
573         return (ret);
574 }
575
576 void
577 db_show_mdpcpu(struct pcpu *pc)
578 {
579         struct pcpu_md *md = &pc->pc_md;
580
581         db_printf("MD: vhpt       = %#lx\n", md->vhpt);
582         db_printf("MD: lid        = %#lx\n", md->lid);
583         db_printf("MD: clock      = %#lx\n", md->clock);
584         db_printf("MD: clock_mode = %u\n", md->clock_mode);
585         db_printf("MD: clock_load = %#lx\n", md->clock_load);
586         db_printf("MD: stats      = %p\n", &md->stats);
587         db_printf("MD: pmap       = %p\n", md->current_pmap);
588 }
589
590 void
591 db_trace_self(void)
592 {
593         struct pcb pcb;
594
595         savectx(&pcb);
596         db_backtrace(curthread, &pcb, -1);
597 }
598
599 int
600 db_trace_thread(struct thread *td, int count)
601 {
602         struct pcb *ctx;
603
604         ctx = kdb_thr_ctx(td);
605         return (db_backtrace(td, ctx, count));
606 }
607
608 #ifdef EXCEPTION_TRACING
609
610 extern long xtrace[];
611 extern long *xhead;
612
613 DB_COMMAND(xtrace, db_xtrace)
614 {
615         long *p;
616
617         p = (*xhead == 0) ? xtrace : xhead;
618
619         db_printf("ITC\t\t IVT\t\t  IIP\t\t   IFA\t\t    ISR\n");
620         if (*p == 0)
621                 return;
622
623         do {
624                 db_printf("%016lx %016lx %016lx %016lx %016lx\n", p[0], p[1],
625                     p[2], p[3], p[4]);
626                 p += 5;
627                 if (p == (void *)&xhead)
628                         p = xtrace;
629         } while (p != xhead);
630 }
631
632 #endif