1149926Smarcel/*-
2149926Smarcel * Copyright (c) 2003-2005 Marcel Moolenaar
3149926Smarcel * Copyright (c) 2000-2001 Doug Rabson
4149926Smarcel * All rights reserved.
5149926Smarcel *
6149926Smarcel * Redistribution and use in source and binary forms, with or without
7149926Smarcel * modification, are permitted provided that the following conditions
8149926Smarcel * are met:
9149926Smarcel *
10149926Smarcel * 1. Redistributions of source code must retain the above copyright
11149926Smarcel *    notice, this list of conditions and the following disclaimer.
12149926Smarcel * 2. Redistributions in binary form must reproduce the above copyright
13149926Smarcel *    notice, this list of conditions and the following disclaimer in the
14149926Smarcel *    documentation and/or other materials provided with the distribution.
15149926Smarcel *
16149926Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17149926Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18149926Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19149926Smarcel * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20149926Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21149926Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22149926Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23149926Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24149926Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25149926Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26149926Smarcel * SUCH DAMAGE.
27149926Smarcel */
28149926Smarcel
29149926Smarcel#include <sys/cdefs.h>
30149926Smarcel__FBSDID("$FreeBSD$");
31149926Smarcel
32199502Smarcel#include "opt_xtrace.h"
33171665Smarcel
34149926Smarcel#include <sys/param.h>
35149926Smarcel#include <sys/systm.h>
36149926Smarcel#include <sys/cons.h>
37149926Smarcel#include <sys/kdb.h>
38149926Smarcel#include <sys/ktr.h>
39149926Smarcel#include <sys/kernel.h>
40149926Smarcel#include <sys/proc.h>
41149926Smarcel#include <sys/reboot.h>
42149926Smarcel#include <sys/smp.h>
43149926Smarcel#include <sys/stack.h>
44149926Smarcel
45149926Smarcel#include <vm/vm.h>
46149926Smarcel
47149926Smarcel#include <machine/db_machdep.h>
48149926Smarcel#include <machine/frame.h>
49170474Smarcel#include <machine/kdb.h>
50149926Smarcel#include <machine/md_var.h>
51149926Smarcel#include <machine/pcb.h>
52149926Smarcel#include <machine/setjmp.h>
53149926Smarcel#include <machine/unwind.h>
54149926Smarcel#include <machine/vmparam.h>
55149926Smarcel
56149926Smarcel#include <ddb/ddb.h>
57149926Smarcel#include <ddb/db_access.h>
58149926Smarcel#include <ddb/db_output.h>
59149926Smarcel#include <ddb/db_sym.h>
60149926Smarcel#include <ddb/db_variables.h>
61149926Smarcel
62149926Smarcel#include <ia64/disasm/disasm.h>
63149926Smarcel
64149926Smarcel#define	TMPL_BITS	5
65149926Smarcel#define	TMPL_MASK	((1 << TMPL_BITS) - 1)
66149926Smarcel#define	SLOT_BITS	41
67149926Smarcel#define	SLOT_COUNT	3
68149926Smarcel#define	SLOT_MASK	((1ULL << SLOT_BITS) - 1ULL)
69149926Smarcel#define	SLOT_SHIFT(i)	(TMPL_BITS+((i)<<3)+(i))
70149926Smarcel
71149926Smarceltypedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t,
72149926Smarcel    db_expr_t, db_expr_t, db_expr_t);
73149926Smarcel
74149926Smarcelregister uint64_t __db_gp __asm__("gp");
75149926Smarcel
76149926Smarcelstatic db_varfcn_t db_frame;
77149926Smarcelstatic db_varfcn_t db_getip;
78149926Smarcelstatic db_varfcn_t db_getrse;
79149926Smarcel
80149926Smarcel#define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
81149926Smarcelstruct db_variable db_regs[] = {
82149926Smarcel	{"ip",		NULL,				db_getip},
83149926Smarcel	{"cr.ifs",	DB_OFFSET(tf_special.cfm),	db_frame},
84149926Smarcel	{"cr.ifa",	DB_OFFSET(tf_special.ifa),	db_frame},
85149926Smarcel	{"ar.bspstore",	DB_OFFSET(tf_special.bspstore),	db_frame},
86149926Smarcel	{"ndirty",	DB_OFFSET(tf_special.ndirty),	db_frame},
87149926Smarcel	{"rp",		DB_OFFSET(tf_special.rp),	db_frame},
88149926Smarcel	{"ar.pfs",	DB_OFFSET(tf_special.pfs),	db_frame},
89149926Smarcel	{"psr",		DB_OFFSET(tf_special.psr),	db_frame},
90149926Smarcel	{"cr.isr",	DB_OFFSET(tf_special.isr),	db_frame},
91149926Smarcel	{"pr",		DB_OFFSET(tf_special.pr),	db_frame},
92149926Smarcel	{"ar.rsc",	DB_OFFSET(tf_special.rsc),	db_frame},
93149926Smarcel	{"ar.rnat",	DB_OFFSET(tf_special.rnat),	db_frame},
94149926Smarcel	{"ar.unat",	DB_OFFSET(tf_special.unat),	db_frame},
95149926Smarcel	{"ar.fpsr",	DB_OFFSET(tf_special.fpsr),	db_frame},
96149926Smarcel	{"gp",		DB_OFFSET(tf_special.gp),	db_frame},
97149926Smarcel	{"sp",		DB_OFFSET(tf_special.sp),	db_frame},
98149926Smarcel	{"tp",		DB_OFFSET(tf_special.tp),	db_frame},
99149926Smarcel	{"b6",		DB_OFFSET(tf_scratch.br6),	db_frame},
100149926Smarcel	{"b7",		DB_OFFSET(tf_scratch.br7),	db_frame},
101149926Smarcel	{"r2",		DB_OFFSET(tf_scratch.gr2),	db_frame},
102149926Smarcel	{"r3",		DB_OFFSET(tf_scratch.gr3),	db_frame},
103149926Smarcel	{"r8",		DB_OFFSET(tf_scratch.gr8),	db_frame},
104149926Smarcel	{"r9",		DB_OFFSET(tf_scratch.gr9),	db_frame},
105149926Smarcel	{"r10",		DB_OFFSET(tf_scratch.gr10),	db_frame},
106149926Smarcel	{"r11",		DB_OFFSET(tf_scratch.gr11),	db_frame},
107149926Smarcel	{"r14",		DB_OFFSET(tf_scratch.gr14),	db_frame},
108149926Smarcel	{"r15",		DB_OFFSET(tf_scratch.gr15),	db_frame},
109149926Smarcel	{"r16",		DB_OFFSET(tf_scratch.gr16),	db_frame},
110149926Smarcel	{"r17",		DB_OFFSET(tf_scratch.gr17),	db_frame},
111149926Smarcel	{"r18",		DB_OFFSET(tf_scratch.gr18),	db_frame},
112149926Smarcel	{"r19",		DB_OFFSET(tf_scratch.gr19),	db_frame},
113149926Smarcel	{"r20",		DB_OFFSET(tf_scratch.gr20),	db_frame},
114149926Smarcel	{"r21",		DB_OFFSET(tf_scratch.gr21),	db_frame},
115149926Smarcel	{"r22",		DB_OFFSET(tf_scratch.gr22),	db_frame},
116149926Smarcel	{"r23",		DB_OFFSET(tf_scratch.gr23),	db_frame},
117149926Smarcel	{"r24",		DB_OFFSET(tf_scratch.gr24),	db_frame},
118149926Smarcel	{"r25",		DB_OFFSET(tf_scratch.gr25),	db_frame},
119149926Smarcel	{"r26",		DB_OFFSET(tf_scratch.gr26),	db_frame},
120149926Smarcel	{"r27",		DB_OFFSET(tf_scratch.gr27),	db_frame},
121149926Smarcel	{"r28",		DB_OFFSET(tf_scratch.gr28),	db_frame},
122149926Smarcel	{"r29",		DB_OFFSET(tf_scratch.gr29),	db_frame},
123149926Smarcel	{"r30",		DB_OFFSET(tf_scratch.gr30),	db_frame},
124149926Smarcel	{"r31",		DB_OFFSET(tf_scratch.gr31),	db_frame},
125149926Smarcel	{"r32",		(db_expr_t*)0,			db_getrse},
126149926Smarcel	{"r33",		(db_expr_t*)1,			db_getrse},
127149926Smarcel	{"r34",		(db_expr_t*)2,			db_getrse},
128149926Smarcel	{"r35",		(db_expr_t*)3,			db_getrse},
129149926Smarcel	{"r36",		(db_expr_t*)4,			db_getrse},
130149926Smarcel	{"r37",		(db_expr_t*)5,			db_getrse},
131149926Smarcel	{"r38",		(db_expr_t*)6,			db_getrse},
132149926Smarcel	{"r39",		(db_expr_t*)7,			db_getrse},
133149926Smarcel	{"r40",		(db_expr_t*)8,			db_getrse},
134149926Smarcel	{"r41",		(db_expr_t*)9,			db_getrse},
135149926Smarcel	{"r42",		(db_expr_t*)10,			db_getrse},
136149926Smarcel	{"r43",		(db_expr_t*)11,			db_getrse},
137149926Smarcel	{"r44",		(db_expr_t*)12,			db_getrse},
138149926Smarcel	{"r45",		(db_expr_t*)13,			db_getrse},
139149926Smarcel	{"r46",		(db_expr_t*)14,			db_getrse},
140149926Smarcel	{"r47",		(db_expr_t*)15,			db_getrse},
141149926Smarcel	{"r48",		(db_expr_t*)16,			db_getrse},
142149926Smarcel	{"r49",		(db_expr_t*)17,			db_getrse},
143149926Smarcel	{"r50",		(db_expr_t*)18,			db_getrse},
144149926Smarcel	{"r51",		(db_expr_t*)19,			db_getrse},
145149926Smarcel	{"r52",		(db_expr_t*)20,			db_getrse},
146149926Smarcel	{"r53",		(db_expr_t*)21,			db_getrse},
147149926Smarcel	{"r54",		(db_expr_t*)22,			db_getrse},
148149926Smarcel	{"r55",		(db_expr_t*)23,			db_getrse},
149149926Smarcel	{"r56",		(db_expr_t*)24,			db_getrse},
150149926Smarcel	{"r57",		(db_expr_t*)25,			db_getrse},
151149926Smarcel	{"r58",		(db_expr_t*)26,			db_getrse},
152149926Smarcel	{"r59",		(db_expr_t*)27,			db_getrse},
153149926Smarcel	{"r60",		(db_expr_t*)28,			db_getrse},
154149926Smarcel	{"r61",		(db_expr_t*)29,			db_getrse},
155149926Smarcel	{"r62",		(db_expr_t*)30,			db_getrse},
156149926Smarcel	{"r63",		(db_expr_t*)31,			db_getrse},
157149926Smarcel	{"r64",		(db_expr_t*)32,			db_getrse},
158149926Smarcel	{"r65",		(db_expr_t*)33,			db_getrse},
159149926Smarcel	{"r66",		(db_expr_t*)34,			db_getrse},
160149926Smarcel	{"r67",		(db_expr_t*)35,			db_getrse},
161149926Smarcel	{"r68",		(db_expr_t*)36,			db_getrse},
162149926Smarcel	{"r69",		(db_expr_t*)37,			db_getrse},
163149926Smarcel	{"r70",		(db_expr_t*)38,			db_getrse},
164149926Smarcel	{"r71",		(db_expr_t*)39,			db_getrse},
165149926Smarcel	{"r72",		(db_expr_t*)40,			db_getrse},
166149926Smarcel	{"r73",		(db_expr_t*)41,			db_getrse},
167149926Smarcel	{"r74",		(db_expr_t*)42,			db_getrse},
168149926Smarcel	{"r75",		(db_expr_t*)43,			db_getrse},
169149926Smarcel	{"r76",		(db_expr_t*)44,			db_getrse},
170149926Smarcel	{"r77",		(db_expr_t*)45,			db_getrse},
171149926Smarcel	{"r78",		(db_expr_t*)46,			db_getrse},
172149926Smarcel	{"r79",		(db_expr_t*)47,			db_getrse},
173149926Smarcel	{"r80",		(db_expr_t*)48,			db_getrse},
174149926Smarcel	{"r81",		(db_expr_t*)49,			db_getrse},
175149926Smarcel	{"r82",		(db_expr_t*)50,			db_getrse},
176149926Smarcel	{"r83",		(db_expr_t*)51,			db_getrse},
177149926Smarcel	{"r84",		(db_expr_t*)52,			db_getrse},
178149926Smarcel	{"r85",		(db_expr_t*)53,			db_getrse},
179149926Smarcel	{"r86",		(db_expr_t*)54,			db_getrse},
180149926Smarcel	{"r87",		(db_expr_t*)55,			db_getrse},
181149926Smarcel	{"r88",		(db_expr_t*)56,			db_getrse},
182149926Smarcel	{"r89",		(db_expr_t*)57,			db_getrse},
183149926Smarcel	{"r90",		(db_expr_t*)58,			db_getrse},
184149926Smarcel	{"r91",		(db_expr_t*)59,			db_getrse},
185149926Smarcel	{"r92",		(db_expr_t*)60,			db_getrse},
186149926Smarcel	{"r93",		(db_expr_t*)61,			db_getrse},
187149926Smarcel	{"r94",		(db_expr_t*)62,			db_getrse},
188149926Smarcel	{"r95",		(db_expr_t*)63,			db_getrse},
189149926Smarcel	{"r96",		(db_expr_t*)64,			db_getrse},
190149926Smarcel	{"r97",		(db_expr_t*)65,			db_getrse},
191149926Smarcel	{"r98",		(db_expr_t*)66,			db_getrse},
192149926Smarcel	{"r99",		(db_expr_t*)67,			db_getrse},
193149926Smarcel	{"r100",	(db_expr_t*)68,			db_getrse},
194149926Smarcel	{"r101",	(db_expr_t*)69,			db_getrse},
195149926Smarcel	{"r102",	(db_expr_t*)70,			db_getrse},
196149926Smarcel	{"r103",	(db_expr_t*)71,			db_getrse},
197149926Smarcel	{"r104",	(db_expr_t*)72,			db_getrse},
198149926Smarcel	{"r105",	(db_expr_t*)73,			db_getrse},
199149926Smarcel	{"r106",	(db_expr_t*)74,			db_getrse},
200149926Smarcel	{"r107",	(db_expr_t*)75,			db_getrse},
201149926Smarcel	{"r108",	(db_expr_t*)76,			db_getrse},
202149926Smarcel	{"r109",	(db_expr_t*)77,			db_getrse},
203149926Smarcel	{"r110",	(db_expr_t*)78,			db_getrse},
204149926Smarcel	{"r111",	(db_expr_t*)79,			db_getrse},
205149926Smarcel	{"r112",	(db_expr_t*)80,			db_getrse},
206149926Smarcel	{"r113",	(db_expr_t*)81,			db_getrse},
207149926Smarcel	{"r114",	(db_expr_t*)82,			db_getrse},
208149926Smarcel	{"r115",	(db_expr_t*)83,			db_getrse},
209149926Smarcel	{"r116",	(db_expr_t*)84,			db_getrse},
210149926Smarcel	{"r117",	(db_expr_t*)85,			db_getrse},
211149926Smarcel	{"r118",	(db_expr_t*)86,			db_getrse},
212149926Smarcel	{"r119",	(db_expr_t*)87,			db_getrse},
213149926Smarcel	{"r120",	(db_expr_t*)88,			db_getrse},
214149926Smarcel	{"r121",	(db_expr_t*)89,			db_getrse},
215149926Smarcel	{"r122",	(db_expr_t*)90,			db_getrse},
216149926Smarcel	{"r123",	(db_expr_t*)91,			db_getrse},
217149926Smarcel	{"r124",	(db_expr_t*)92,			db_getrse},
218149926Smarcel	{"r125",	(db_expr_t*)93,			db_getrse},
219149926Smarcel	{"r126",	(db_expr_t*)94,			db_getrse},
220149926Smarcel	{"r127",	(db_expr_t*)95,			db_getrse},
221149926Smarcel};
222149926Smarcelstruct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
223149926Smarcel
224149926Smarcelstatic int
225149926Smarceldb_backtrace(struct thread *td, struct pcb *pcb, int count)
226149926Smarcel{
227149926Smarcel	struct unw_regstate rs;
228149926Smarcel	struct trapframe *tf;
229149926Smarcel	const char *name;
230149926Smarcel	db_expr_t offset;
231149926Smarcel	uint64_t bsp, cfm, ip, pfs, reg, sp;
232149926Smarcel	c_db_sym_t sym;
233160312Sjhb	int args, error, i;
234149926Smarcel
235149926Smarcel	error = unw_create_from_pcb(&rs, pcb);
236160312Sjhb	while (!error && count-- && !db_pager_quit) {
237149926Smarcel		error = unw_get_cfm(&rs, &cfm);
238149926Smarcel		if (!error)
239149926Smarcel			error = unw_get_bsp(&rs, &bsp);
240149926Smarcel		if (!error)
241149926Smarcel			error = unw_get_ip(&rs, &ip);
242149926Smarcel		if (!error)
243149926Smarcel			error = unw_get_sp(&rs, &sp);
244149926Smarcel		if (error)
245149926Smarcel			break;
246149926Smarcel
247149926Smarcel		args = IA64_CFM_SOL(cfm);
248149926Smarcel		if (args > 8)
249149926Smarcel			args = 8;
250149926Smarcel
251149926Smarcel		error = unw_step(&rs);
252149926Smarcel		if (!error) {
253149926Smarcel			if (!unw_get_cfm(&rs, &pfs)) {
254149926Smarcel				i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs);
255149926Smarcel				if (args > i)
256149926Smarcel					args = i;
257149926Smarcel			}
258149926Smarcel		}
259149926Smarcel
260149926Smarcel		sym = db_search_symbol(ip, DB_STGY_ANY, &offset);
261149926Smarcel		db_symbol_values(sym, &name, NULL);
262149926Smarcel		db_printf("%s(", name);
263219808Smarcel		if (bsp >= VM_MAXUSER_ADDRESS) {
264149926Smarcel			for (i = 0; i < args; i++) {
265149926Smarcel				if ((bsp & 0x1ff) == 0x1f8)
266149926Smarcel					bsp += 8;
267149926Smarcel				db_read_bytes(bsp, sizeof(reg), (void*)&reg);
268149926Smarcel				if (i > 0)
269149926Smarcel					db_printf(", ");
270149926Smarcel				db_printf("0x%lx", reg);
271149926Smarcel				bsp += 8;
272149926Smarcel			}
273149926Smarcel		} else
274149926Smarcel			db_printf("...");
275149926Smarcel		db_printf(") at ");
276149926Smarcel
277149926Smarcel		db_printsym(ip, DB_STGY_PROC);
278149926Smarcel		db_printf("\n");
279149926Smarcel
280149926Smarcel		if (error != ERESTART)
281149926Smarcel			continue;
282219808Smarcel		if (sp < VM_MAXUSER_ADDRESS)
283149926Smarcel			break;
284149926Smarcel
285149926Smarcel		tf = (struct trapframe *)(sp + 16);
286149926Smarcel		if ((tf->tf_flags & FRAME_SYSCALL) != 0 ||
287219808Smarcel		    tf->tf_special.iip < VM_MAXUSER_ADDRESS)
288149926Smarcel			break;
289149926Smarcel
290149926Smarcel		/* XXX ask if we should unwind across the trapframe. */
291149926Smarcel		db_printf("--- trapframe at %p\n", tf);
292149926Smarcel		unw_delete(&rs);
293149926Smarcel		error = unw_create_from_frame(&rs, tf);
294149926Smarcel	}
295149926Smarcel
296149926Smarcel	unw_delete(&rs);
297149926Smarcel	/*
298149926Smarcel	 * EJUSTRETURN and ERESTART signal the end of a trace and
299149926Smarcel	 * are not really errors.
300149926Smarcel	 */
301149926Smarcel	return ((error > 0) ? error : 0);
302149926Smarcel}
303149926Smarcel
304149926Smarcelvoid
305149926Smarceldb_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage)
306149926Smarcel{
307149926Smarcel	BKPT_INST_TYPE tmp;
308149926Smarcel	db_addr_t loc;
309149926Smarcel	int slot;
310149926Smarcel
311149926Smarcel	slot = addr & 0xfUL;
312149926Smarcel	if (slot >= SLOT_COUNT)
313149926Smarcel		return;
314149926Smarcel	loc = (addr & ~0xfUL) + (slot << 2);
315149926Smarcel
316149926Smarcel	db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
317149926Smarcel	tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
318149926Smarcel	tmp |= *storage << SLOT_SHIFT(slot);
319149926Smarcel	db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
320149926Smarcel}
321149926Smarcel
322149926Smarcelvoid
323149926Smarceldb_bkpt_skip(void)
324149926Smarcel{
325149926Smarcel
326149926Smarcel	if (kdb_frame == NULL)
327149926Smarcel		return;
328149926Smarcel
329149926Smarcel	kdb_frame->tf_special.psr += IA64_PSR_RI_1;
330149926Smarcel	if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
331149926Smarcel		kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
332149926Smarcel		kdb_frame->tf_special.iip += 16;
333149926Smarcel	}
334149926Smarcel}
335149926Smarcel
336149926Smarcelvoid
337149926Smarceldb_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage)
338149926Smarcel{
339149926Smarcel	BKPT_INST_TYPE tmp;
340149926Smarcel	db_addr_t loc;
341149926Smarcel	int slot;
342149926Smarcel
343149926Smarcel	slot = addr & 0xfUL;
344149926Smarcel	if (slot >= SLOT_COUNT)
345149926Smarcel		return;
346149926Smarcel	loc = (addr & ~0xfUL) + (slot << 2);
347149926Smarcel
348149926Smarcel	db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
349149926Smarcel	*storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK;
350149926Smarcel
351149926Smarcel	tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
352149926Smarcel	tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
353149926Smarcel	db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp);
354149926Smarcel}
355149926Smarcel
356149926Smarceldb_addr_t
357149926Smarceldb_disasm(db_addr_t loc, boolean_t altfmt)
358149926Smarcel{
359149926Smarcel	char buf[32];
360149926Smarcel	struct asm_bundle bundle;
361149926Smarcel	const struct asm_inst *i;
362149926Smarcel	const char *tmpl;
363149926Smarcel	int n, slot;
364149926Smarcel
365149926Smarcel	slot = loc & 0xf;
366149926Smarcel	loc &= ~0xful;
367149926Smarcel	db_read_bytes(loc, 16, buf);
368149926Smarcel	if (asm_decode((uintptr_t)buf, &bundle)) {
369149926Smarcel		i = bundle.b_inst + slot;
370149926Smarcel		tmpl = bundle.b_templ + slot;
371149926Smarcel		if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';'))
372149926Smarcel			tmpl++;
373149926Smarcel		if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
374149926Smarcel			db_printf("\n");
375149926Smarcel			goto out;
376149926Smarcel		}
377149926Smarcel
378149926Smarcel		/* Unit + slot. */
379149926Smarcel		db_printf("[%c%d] ", *tmpl, slot);
380149926Smarcel
381149926Smarcel		/* Predicate. */
382149926Smarcel		if (i->i_oper[0].o_value != 0) {
383149926Smarcel			asm_operand(i->i_oper+0, buf, loc);
384149926Smarcel			db_printf("(%s) ", buf);
385149926Smarcel		} else
386149926Smarcel			db_printf("   ");
387149926Smarcel
388149926Smarcel		/* Mnemonic & completers. */
389149926Smarcel		asm_mnemonic(i->i_op, buf);
390149926Smarcel		db_printf(buf);
391149926Smarcel		n = 0;
392149926Smarcel		while (n < i->i_ncmpltrs) {
393149926Smarcel			asm_completer(i->i_cmpltr + n, buf);
394149926Smarcel			db_printf(buf);
395149926Smarcel			n++;
396149926Smarcel		}
397149926Smarcel		db_printf(" ");
398149926Smarcel
399149926Smarcel		/* Operands. */
400149926Smarcel		n = 1;
401149926Smarcel		while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
402149926Smarcel			if (n > 1) {
403149926Smarcel				if (n == i->i_srcidx)
404149926Smarcel					db_printf("=");
405149926Smarcel				else
406149926Smarcel					db_printf(",");
407149926Smarcel			}
408149926Smarcel			asm_operand(i->i_oper + n, buf, loc);
409149926Smarcel			db_printf(buf);
410149926Smarcel			n++;
411149926Smarcel		}
412172690Smarcel		if (tmpl[1] == ';')
413172690Smarcel			db_printf(" ;;");
414149926Smarcel	} else {
415149926Smarcel		tmpl = NULL;
416149926Smarcel		slot = 2;
417149926Smarcel	}
418149926Smarcel	db_printf("\n");
419149926Smarcel
420149926Smarcelout:
421149926Smarcel	slot++;
422149926Smarcel	if (slot == 1 && tmpl[1] == 'L')
423149926Smarcel		slot++;
424149926Smarcel	if (slot > 2)
425149926Smarcel		slot = 16;
426149926Smarcel	return (loc + slot);
427149926Smarcel}
428149926Smarcel
429149926Smarcelint
430149926Smarceldb_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
431149926Smarcel{
432149926Smarcel	struct ia64_fdesc fdesc;
433149926Smarcel	__db_f *f;
434149926Smarcel
435149926Smarcel	f = (__db_f *)&fdesc;
436149926Smarcel	fdesc.func = addr;
437149926Smarcel	fdesc.gp = __db_gp;	/* XXX doesn't work for modules. */
438149926Smarcel	*rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
439149926Smarcel	    args[6], args[7]);
440149926Smarcel	return (1);
441149926Smarcel}
442149926Smarcel
443149926Smarcelstatic int
444149926Smarceldb_frame(struct db_variable *vp, db_expr_t *valuep, int op)
445149926Smarcel{
446149926Smarcel	uint64_t *reg;
447149926Smarcel
448149926Smarcel	if (kdb_frame == NULL)
449149926Smarcel		return (0);
450149926Smarcel	reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep);
451149926Smarcel	if (op == DB_VAR_GET)
452149926Smarcel		*valuep = *reg;
453149926Smarcel	else
454149926Smarcel		*reg = *valuep;
455149926Smarcel	return (1);
456149926Smarcel}
457149926Smarcel
458149926Smarcelstatic int
459149926Smarceldb_getip(struct db_variable *vp, db_expr_t *valuep, int op)
460149926Smarcel{
461149926Smarcel	u_long iip, slot;
462149926Smarcel
463149926Smarcel	if (kdb_frame == NULL)
464149926Smarcel		return (0);
465149926Smarcel
466149926Smarcel	if (op == DB_VAR_GET) {
467149926Smarcel		iip = kdb_frame->tf_special.iip;
468149926Smarcel		slot = (kdb_frame->tf_special.psr >> 41) & 3;
469149926Smarcel		*valuep = iip + slot;
470149926Smarcel	} else {
471149926Smarcel		iip = *valuep & ~0xf;
472149926Smarcel		slot = *valuep & 0xf;
473149926Smarcel		if (slot > 2)
474149926Smarcel			return (0);
475149926Smarcel		kdb_frame->tf_special.iip = iip;
476149926Smarcel		kdb_frame->tf_special.psr &= ~IA64_PSR_RI;
477149926Smarcel		kdb_frame->tf_special.psr |= slot << 41;
478149926Smarcel	}
479149926Smarcel	return (1);
480149926Smarcel}
481149926Smarcel
482149926Smarcelstatic int
483149926Smarceldb_getrse(struct db_variable *vp, db_expr_t *valuep, int op)
484149926Smarcel{
485149926Smarcel	u_int64_t *reg;
486149926Smarcel	uint64_t bsp;
487149926Smarcel	int nats, regno, sof;
488149926Smarcel
489149926Smarcel	if (kdb_frame == NULL)
490149926Smarcel		return (0);
491149926Smarcel
492149926Smarcel	regno = (int)(intptr_t)valuep;
493149926Smarcel	bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty;
494149926Smarcel	sof = (int)(kdb_frame->tf_special.cfm & 0x7f);
495149926Smarcel
496149926Smarcel	if (regno >= sof)
497149926Smarcel		return (0);
498149926Smarcel
499149926Smarcel	nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
500149926Smarcel	reg = (void*)(bsp - ((sof - regno + nats) << 3));
501149926Smarcel	if (op == DB_VAR_GET)
502149926Smarcel		*valuep = *reg;
503149926Smarcel	else
504149926Smarcel		*reg = *valuep;
505149926Smarcel	return (1);
506149926Smarcel}
507149926Smarcel
508149926Smarcelint
509149926Smarceldb_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
510149926Smarcel{
511149926Smarcel
512149926Smarcel	return (-1);
513149926Smarcel}
514149926Smarcel
515149926Smarcelvoid
516149926Smarceldb_md_list_watchpoints()
517149926Smarcel{
518149926Smarcel
519149926Smarcel	return;
520149926Smarcel}
521149926Smarcel
522149926Smarcelint
523149926Smarceldb_md_set_watchpoint(db_expr_t addr, db_expr_t size)
524149926Smarcel{
525149926Smarcel
526149926Smarcel	return (-1);
527149926Smarcel}
528149926Smarcel
529149926Smarcel/*
530149926Smarcel * Read bytes from kernel address space for debugger.
531149926Smarcel */
532149926Smarcelint
533149926Smarceldb_read_bytes(vm_offset_t addr, size_t size, char *data)
534149926Smarcel{
535149926Smarcel	jmp_buf jb;
536149926Smarcel	void *prev_jb;
537149926Smarcel	char *src;
538149926Smarcel	int ret;
539149926Smarcel
540149926Smarcel	prev_jb = kdb_jmpbuf(jb);
541149926Smarcel	ret = setjmp(jb);
542149926Smarcel	if (ret == 0) {
543149926Smarcel		src = (char *)addr;
544149926Smarcel		while (size-- > 0)
545149926Smarcel			*data++ = *src++;
546149926Smarcel	}
547149926Smarcel	(void)kdb_jmpbuf(prev_jb);
548149926Smarcel	return (ret);
549149926Smarcel}
550149926Smarcel
551149926Smarcel/*
552149926Smarcel * Write bytes to kernel address space for debugger.
553149926Smarcel */
554149926Smarcelint
555149926Smarceldb_write_bytes(vm_offset_t addr, size_t size, char *data)
556149926Smarcel{
557149926Smarcel	jmp_buf jb;
558149926Smarcel	void *prev_jb;
559170474Smarcel	size_t cnt;
560149926Smarcel	char *dst;
561149926Smarcel	int ret;
562149926Smarcel
563149926Smarcel	prev_jb = kdb_jmpbuf(jb);
564149926Smarcel	ret = setjmp(jb);
565149926Smarcel	if (ret == 0) {
566149926Smarcel		dst = (char *)addr;
567170474Smarcel		cnt = size;
568170474Smarcel		while (cnt-- > 0)
569149926Smarcel			*dst++ = *data++;
570170474Smarcel		kdb_cpu_sync_icache((void *)addr, size);
571149926Smarcel	}
572149926Smarcel	(void)kdb_jmpbuf(prev_jb);
573149926Smarcel	return (ret);
574149926Smarcel}
575149926Smarcel
576149926Smarcelvoid
577149926Smarceldb_show_mdpcpu(struct pcpu *pc)
578149926Smarcel{
579205429Smarcel	struct pcpu_md *md = &pc->pc_md;
580205429Smarcel
581223526Smarcel	db_printf("MD: vhpt       = %#lx\n", md->vhpt);
582223526Smarcel	db_printf("MD: lid        = %#lx\n", md->lid);
583223526Smarcel	db_printf("MD: clock      = %#lx\n", md->clock);
584223526Smarcel	db_printf("MD: clock_mode = %u\n", md->clock_mode);
585223526Smarcel	db_printf("MD: clock_load = %#lx\n", md->clock_load);
586223526Smarcel	db_printf("MD: stats      = %p\n", &md->stats);
587223526Smarcel	db_printf("MD: pmap       = %p\n", md->current_pmap);
588149926Smarcel}
589149926Smarcel
590149926Smarcelvoid
591149926Smarceldb_trace_self(void)
592149926Smarcel{
593149926Smarcel	struct pcb pcb;
594149926Smarcel
595149926Smarcel	savectx(&pcb);
596149926Smarcel	db_backtrace(curthread, &pcb, -1);
597149926Smarcel}
598149926Smarcel
599149926Smarcelint
600149926Smarceldb_trace_thread(struct thread *td, int count)
601149926Smarcel{
602149926Smarcel	struct pcb *ctx;
603149926Smarcel
604149926Smarcel	ctx = kdb_thr_ctx(td);
605149926Smarcel	return (db_backtrace(td, ctx, count));
606149926Smarcel}
607149926Smarcel
608171665Smarcel#ifdef EXCEPTION_TRACING
609171665Smarcel
610171665Smarcelextern long xtrace[];
611171665Smarcelextern long *xhead;
612171665Smarcel
613171665SmarcelDB_COMMAND(xtrace, db_xtrace)
614171665Smarcel{
615171665Smarcel	long *p;
616171665Smarcel
617171665Smarcel	p = (*xhead == 0) ? xtrace : xhead;
618171665Smarcel
619171665Smarcel	db_printf("ITC\t\t IVT\t\t  IIP\t\t   IFA\t\t    ISR\n");
620171665Smarcel	if (*p == 0)
621171665Smarcel		return;
622171665Smarcel
623171665Smarcel	do {
624171665Smarcel		db_printf("%016lx %016lx %016lx %016lx %016lx\n", p[0], p[1],
625171665Smarcel		    p[2], p[3], p[4]);
626171665Smarcel		p += 5;
627171665Smarcel		if (p == (void *)&xhead)
628171665Smarcel			p = xtrace;
629171665Smarcel	} while (p != xhead);
630171665Smarcel}
631171665Smarcel
632171665Smarcel#endif
633