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 "opt_xtrace.h"
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD$");
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
71typedef 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
74register uint64_t __db_gp __asm__("gp");
75
76static db_varfcn_t db_frame;
77static db_varfcn_t db_getip;
78static db_varfcn_t db_getrse;
79
80#define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
81struct 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};
222struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
223
224static int
225db_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
304void
305db_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
322void
323db_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
336void
337db_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
356db_addr_t
357db_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
420out:
421	slot++;
422	if (slot == 1 && tmpl[1] == 'L')
423		slot++;
424	if (slot > 2)
425		slot = 16;
426	return (loc + slot);
427}
428
429int
430db_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
443static int
444db_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
458static int
459db_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
482static int
483db_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
508int
509db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
510{
511
512	return (-1);
513}
514
515void
516db_md_list_watchpoints()
517{
518
519	return;
520}
521
522int
523db_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 */
532int
533db_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 */
554int
555db_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
576void
577db_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#ifdef XTRACE
589	db_printf("MD: xtrace_buffer = %p\n", md->xtrace_buffer);
590	db_printf("MD: xtrace_tail   = %#lx\n", md->xtrace_tail);
591#endif
592}
593
594void
595db_trace_self(void)
596{
597	struct pcb pcb;
598
599	savectx(&pcb);
600	db_backtrace(curthread, &pcb, -1);
601}
602
603int
604db_trace_thread(struct thread *td, int count)
605{
606	struct pcb *ctx;
607
608	ctx = kdb_thr_ctx(td);
609	return (db_backtrace(td, ctx, count));
610}
611