1/* $NetBSD: db_interface.c,v 1.6 2009/07/20 04:41:37 kiyohara Exp $ */
2
3/*-
4 * Copyright (c) 2003-2005 Marcel Moolenaar
5 * Copyright (c) 2000-2001 Doug Rabson
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31/*
32 * Mach Operating System
33 * Copyright (c) 1992,1991,1990 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS ``AS IS''
43 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
49 *  School of Computer Science
50 *  Carnegie Mellon University
51 *  Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie the
54 * rights to redistribute these changes.
55 *
56 *	db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
57 */
58
59/*
60 * Parts of this file are derived from Mach 3:
61 *
62 *	File: alpha_instruction.c
63 *	Author: Alessandro Forin, Carnegie Mellon University
64 *	Date:	6/92
65 */
66
67/*
68 * Interface to DDB.
69 *
70 * Modified for NetBSD/alpha by:
71 *
72 *	Christopher G. Demetriou, Carnegie Mellon University
73 *
74 *	Jason R. Thorpe, Numerical Aerospace Simulation Facility,
75 *	NASA Ames Research Center
76 */
77
78#include "opt_ddb.h"
79#include "opt_multiprocessor.h"
80
81#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
82
83__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.6 2009/07/20 04:41:37 kiyohara Exp $");
84
85#include <sys/param.h>
86#include <sys/proc.h>
87#include <sys/reboot.h>
88#include <sys/systm.h>
89
90#include <uvm/uvm_extern.h>
91
92#include <dev/cons.h>
93
94#include <machine/cpufunc.h>
95#include <machine/md_var.h>
96#include <machine/db_machdep.h>
97
98#include <ddb/db_sym.h>
99#include <ddb/db_command.h>
100#include <ddb/db_extern.h>
101#include <ddb/db_access.h>
102#include <ddb/db_output.h>
103#include <ddb/db_variables.h>
104#include <ddb/db_interface.h>
105#include <ddb/db_run.h>
106
107#include <ia64/disasm/disasm.h>
108
109int	db_active = 0;
110
111db_regs_t *ddb_regp;
112
113static void db_show_vector(db_expr_t, bool, db_expr_t, const char *);
114
115const struct db_command db_machine_command_table[] = {
116	{ DDB_ADD_CMD("vector", db_show_vector, 0,
117	  "Display information about vectors",
118	  "[vector]",
119	  "   vector:\tthe vector to show (all vectors otherwise)") },
120
121	{ DDB_ADD_CMD(NULL, NULL, 0, NULL,NULL,NULL) },
122};
123
124static int
125db_frame(const struct db_variable *vp, db_expr_t *valuep, int opcode)
126{
127	uint64_t *reg;
128	struct trapframe *f = NULL;
129
130	if (vp->modif != NULL && *vp->modif == 'u') {
131	  if (curlwp != NULL)
132	    f = curlwp->l_md.md_tf;
133	} else	f = DDB_REGS;
134
135	reg = (uint64_t*)((uintptr_t) f + (uintptr_t)vp->valuep);
136
137	switch (opcode) {
138	case DB_VAR_GET:
139		*valuep = *reg;
140		break;
141	case DB_VAR_SET:
142		*reg = *valuep;
143		break;
144	default:
145		panic("db_frame: unknown op %d", opcode);
146	}
147	return (0);
148}
149
150static int
151db_getip(const struct db_variable *vp, db_expr_t *valuep, int opcode)
152{
153	u_long iip, slot;
154	struct trapframe *f = NULL;
155
156	if (vp->modif != NULL && *vp->modif == 'u') {
157	  if (curlwp != NULL)
158	    f = curlwp->l_md.md_tf;
159	} else	f = DDB_REGS;
160
161	switch (opcode) {
162	case DB_VAR_GET:
163		iip = f->tf_special.iip;
164		slot = (f->tf_special.psr >> 41) & 3;
165		*valuep = iip + slot;
166		break;
167
168	case DB_VAR_SET:
169		iip = *valuep & ~0xf;
170		slot = *valuep & 0xf;
171		if (slot > 2)
172			return (0);
173		f->tf_special.iip = iip;
174		f->tf_special.psr &= ~IA64_PSR_RI;
175		f->tf_special.psr |= slot << 41;
176		break;
177
178	default:
179		panic("db_getip: unknown op %d", opcode);
180	}
181	return (0);
182}
183
184static int
185db_getrse(const struct db_variable *vp, db_expr_t *valuep, int opcode)
186{
187	u_int64_t *reg;
188	uint64_t bsp;
189	int nats, regno, sof;
190	struct trapframe *f = NULL;
191
192	if (vp->modif != NULL && *vp->modif == 'u') {
193	  if (curlwp != NULL)
194	    f = curlwp->l_md.md_tf;
195	} else	f = DDB_REGS;
196
197
198	regno = (int)(intptr_t)valuep;
199	bsp = f->tf_special.bspstore + f->tf_special.ndirty;
200	sof = (int)(f->tf_special.cfm & 0x7f);
201
202	if (regno >= sof)
203		return (0);
204
205	nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
206	reg = (void*)(bsp - ((sof - regno + nats) << 3));
207
208
209	switch (opcode) {
210	case DB_VAR_GET:
211		*valuep = *reg;
212		break;
213	case DB_VAR_SET:
214		*reg = *valuep;
215		break;
216	default:
217		panic("db_getrse: unknown op %d", opcode);
218	}
219	return (0);
220}
221
222
223#define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
224const struct db_variable db_regs[] = {
225	{"ip",		NULL,				db_getip},
226	{"cr.ifs",	DB_OFFSET(tf_special.cfm),	db_frame},
227	{"cr.ifa",	DB_OFFSET(tf_special.ifa),	db_frame},
228	{"ar.bspstore",	DB_OFFSET(tf_special.bspstore),	db_frame},
229	{"ndirty",	DB_OFFSET(tf_special.ndirty),	db_frame},
230	{"rp",		DB_OFFSET(tf_special.rp),	db_frame},
231	{"ar.pfs",	DB_OFFSET(tf_special.pfs),	db_frame},
232	{"psr",		DB_OFFSET(tf_special.psr),	db_frame},
233	{"cr.isr",	DB_OFFSET(tf_special.isr),	db_frame},
234	{"pr",		DB_OFFSET(tf_special.pr),	db_frame},
235	{"ar.rsc",	DB_OFFSET(tf_special.rsc),	db_frame},
236	{"ar.rnat",	DB_OFFSET(tf_special.rnat),	db_frame},
237	{"ar.unat",	DB_OFFSET(tf_special.unat),	db_frame},
238	{"ar.fpsr",	DB_OFFSET(tf_special.fpsr),	db_frame},
239	{"gp",		DB_OFFSET(tf_special.gp),	db_frame},
240	{"sp",		DB_OFFSET(tf_special.sp),	db_frame},
241	{"tp",		DB_OFFSET(tf_special.tp),	db_frame},
242	{"b6",		DB_OFFSET(tf_scratch.br6),	db_frame},
243	{"b7",		DB_OFFSET(tf_scratch.br7),	db_frame},
244	{"r2",		DB_OFFSET(tf_scratch.gr2),	db_frame},
245	{"r3",		DB_OFFSET(tf_scratch.gr3),	db_frame},
246	{"r8",		DB_OFFSET(tf_scratch.gr8),	db_frame},
247	{"r9",		DB_OFFSET(tf_scratch.gr9),	db_frame},
248	{"r10",		DB_OFFSET(tf_scratch.gr10),	db_frame},
249	{"r11",		DB_OFFSET(tf_scratch.gr11),	db_frame},
250	{"r14",		DB_OFFSET(tf_scratch.gr14),	db_frame},
251	{"r15",		DB_OFFSET(tf_scratch.gr15),	db_frame},
252	{"r16",		DB_OFFSET(tf_scratch.gr16),	db_frame},
253	{"r17",		DB_OFFSET(tf_scratch.gr17),	db_frame},
254	{"r18",		DB_OFFSET(tf_scratch.gr18),	db_frame},
255	{"r19",		DB_OFFSET(tf_scratch.gr19),	db_frame},
256	{"r20",		DB_OFFSET(tf_scratch.gr20),	db_frame},
257	{"r21",		DB_OFFSET(tf_scratch.gr21),	db_frame},
258	{"r22",		DB_OFFSET(tf_scratch.gr22),	db_frame},
259	{"r23",		DB_OFFSET(tf_scratch.gr23),	db_frame},
260	{"r24",		DB_OFFSET(tf_scratch.gr24),	db_frame},
261	{"r25",		DB_OFFSET(tf_scratch.gr25),	db_frame},
262	{"r26",		DB_OFFSET(tf_scratch.gr26),	db_frame},
263	{"r27",		DB_OFFSET(tf_scratch.gr27),	db_frame},
264	{"r28",		DB_OFFSET(tf_scratch.gr28),	db_frame},
265	{"r29",		DB_OFFSET(tf_scratch.gr29),	db_frame},
266	{"r30",		DB_OFFSET(tf_scratch.gr30),	db_frame},
267	{"r31",		DB_OFFSET(tf_scratch.gr31),	db_frame},
268	{"r32",		(db_expr_t*)0,			db_getrse},
269	{"r33",		(db_expr_t*)1,			db_getrse},
270	{"r34",		(db_expr_t*)2,			db_getrse},
271	{"r35",		(db_expr_t*)3,			db_getrse},
272	{"r36",		(db_expr_t*)4,			db_getrse},
273	{"r37",		(db_expr_t*)5,			db_getrse},
274	{"r38",		(db_expr_t*)6,			db_getrse},
275	{"r39",		(db_expr_t*)7,			db_getrse},
276	{"r40",		(db_expr_t*)8,			db_getrse},
277	{"r41",		(db_expr_t*)9,			db_getrse},
278	{"r42",		(db_expr_t*)10,			db_getrse},
279	{"r43",		(db_expr_t*)11,			db_getrse},
280	{"r44",		(db_expr_t*)12,			db_getrse},
281	{"r45",		(db_expr_t*)13,			db_getrse},
282	{"r46",		(db_expr_t*)14,			db_getrse},
283	{"r47",		(db_expr_t*)15,			db_getrse},
284	{"r48",		(db_expr_t*)16,			db_getrse},
285	{"r49",		(db_expr_t*)17,			db_getrse},
286	{"r50",		(db_expr_t*)18,			db_getrse},
287	{"r51",		(db_expr_t*)19,			db_getrse},
288	{"r52",		(db_expr_t*)20,			db_getrse},
289	{"r53",		(db_expr_t*)21,			db_getrse},
290	{"r54",		(db_expr_t*)22,			db_getrse},
291	{"r55",		(db_expr_t*)23,			db_getrse},
292	{"r56",		(db_expr_t*)24,			db_getrse},
293	{"r57",		(db_expr_t*)25,			db_getrse},
294	{"r58",		(db_expr_t*)26,			db_getrse},
295	{"r59",		(db_expr_t*)27,			db_getrse},
296	{"r60",		(db_expr_t*)28,			db_getrse},
297	{"r61",		(db_expr_t*)29,			db_getrse},
298	{"r62",		(db_expr_t*)30,			db_getrse},
299	{"r63",		(db_expr_t*)31,			db_getrse},
300	{"r64",		(db_expr_t*)32,			db_getrse},
301	{"r65",		(db_expr_t*)33,			db_getrse},
302	{"r66",		(db_expr_t*)34,			db_getrse},
303	{"r67",		(db_expr_t*)35,			db_getrse},
304	{"r68",		(db_expr_t*)36,			db_getrse},
305	{"r69",		(db_expr_t*)37,			db_getrse},
306	{"r70",		(db_expr_t*)38,			db_getrse},
307	{"r71",		(db_expr_t*)39,			db_getrse},
308	{"r72",		(db_expr_t*)40,			db_getrse},
309	{"r73",		(db_expr_t*)41,			db_getrse},
310	{"r74",		(db_expr_t*)42,			db_getrse},
311	{"r75",		(db_expr_t*)43,			db_getrse},
312	{"r76",		(db_expr_t*)44,			db_getrse},
313	{"r77",		(db_expr_t*)45,			db_getrse},
314	{"r78",		(db_expr_t*)46,			db_getrse},
315	{"r79",		(db_expr_t*)47,			db_getrse},
316	{"r80",		(db_expr_t*)48,			db_getrse},
317	{"r81",		(db_expr_t*)49,			db_getrse},
318	{"r82",		(db_expr_t*)50,			db_getrse},
319	{"r83",		(db_expr_t*)51,			db_getrse},
320	{"r84",		(db_expr_t*)52,			db_getrse},
321	{"r85",		(db_expr_t*)53,			db_getrse},
322	{"r86",		(db_expr_t*)54,			db_getrse},
323	{"r87",		(db_expr_t*)55,			db_getrse},
324	{"r88",		(db_expr_t*)56,			db_getrse},
325	{"r89",		(db_expr_t*)57,			db_getrse},
326	{"r90",		(db_expr_t*)58,			db_getrse},
327	{"r91",		(db_expr_t*)59,			db_getrse},
328	{"r92",		(db_expr_t*)60,			db_getrse},
329	{"r93",		(db_expr_t*)61,			db_getrse},
330	{"r94",		(db_expr_t*)62,			db_getrse},
331	{"r95",		(db_expr_t*)63,			db_getrse},
332	{"r96",		(db_expr_t*)64,			db_getrse},
333	{"r97",		(db_expr_t*)65,			db_getrse},
334	{"r98",		(db_expr_t*)66,			db_getrse},
335	{"r99",		(db_expr_t*)67,			db_getrse},
336	{"r100",	(db_expr_t*)68,			db_getrse},
337	{"r101",	(db_expr_t*)69,			db_getrse},
338	{"r102",	(db_expr_t*)70,			db_getrse},
339	{"r103",	(db_expr_t*)71,			db_getrse},
340	{"r104",	(db_expr_t*)72,			db_getrse},
341	{"r105",	(db_expr_t*)73,			db_getrse},
342	{"r106",	(db_expr_t*)74,			db_getrse},
343	{"r107",	(db_expr_t*)75,			db_getrse},
344	{"r108",	(db_expr_t*)76,			db_getrse},
345	{"r109",	(db_expr_t*)77,			db_getrse},
346	{"r110",	(db_expr_t*)78,			db_getrse},
347	{"r111",	(db_expr_t*)79,			db_getrse},
348	{"r112",	(db_expr_t*)80,			db_getrse},
349	{"r113",	(db_expr_t*)81,			db_getrse},
350	{"r114",	(db_expr_t*)82,			db_getrse},
351	{"r115",	(db_expr_t*)83,			db_getrse},
352	{"r116",	(db_expr_t*)84,			db_getrse},
353	{"r117",	(db_expr_t*)85,			db_getrse},
354	{"r118",	(db_expr_t*)86,			db_getrse},
355	{"r119",	(db_expr_t*)87,			db_getrse},
356	{"r120",	(db_expr_t*)88,			db_getrse},
357	{"r121",	(db_expr_t*)89,			db_getrse},
358	{"r122",	(db_expr_t*)90,			db_getrse},
359	{"r123",	(db_expr_t*)91,			db_getrse},
360	{"r124",	(db_expr_t*)92,			db_getrse},
361	{"r125",	(db_expr_t*)93,			db_getrse},
362	{"r126",	(db_expr_t*)94,			db_getrse},
363	{"r127",	(db_expr_t*)95,			db_getrse},
364};
365const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
366
367/*
368 * Read bytes from kernel address space for debugger.
369 */
370void
371db_read_bytes(vaddr_t addr, register size_t size, register char *data)
372{
373	register char	*src;
374
375	src = (char *)addr;
376	while (size-- > 0)
377		*data++ = *src++;
378}
379
380/*
381 * Write bytes to kernel address space for debugger.
382 */
383void
384db_write_bytes(vaddr_t addr, register size_t size, register const char *data)
385{
386	register char	*dst;
387
388	dst = (char *)addr;
389	while (size-- > 0) {
390		*dst++ = *data++;
391		ia64_fc_i((vaddr_t) dst);
392	}
393	ia64_sync_i();
394}
395
396db_expr_t
397db_bkpt_set(db_expr_t inst, db_addr_t addr)
398{
399	db_expr_t tmp;
400	int slot;
401
402	slot = addr & 0xfUL;
403	if (slot >= SLOT_COUNT) slot = 0;
404
405	tmp = inst;
406
407	tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
408	tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
409
410	return tmp;
411}
412
413void
414cpu_Debugger(void)
415{
416	printf("Broken into debugger \n");
417	breakpoint();
418}
419
420void
421db_pc_advance(db_regs_t *regs)
422{
423
424	if (regs == NULL)
425		return;
426
427	regs->tf_special.psr += IA64_PSR_RI_1;
428	if ((regs->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
429		regs->tf_special.psr &= ~IA64_PSR_RI;
430		regs->tf_special.iip += 16;
431	}
432}
433
434db_addr_t
435db_disasm(db_addr_t loc, bool altfmt)
436{
437	char buf[32];
438	struct asm_bundle bundle;
439	const struct asm_inst *i;
440	const char *tmpl;
441	int n, slot;
442
443	slot = loc & 0xf;
444	loc &= ~0xful;
445	db_read_bytes(loc, 16, buf);
446	if (asm_decode((uintptr_t)buf, &bundle)) {
447		i = bundle.b_inst + slot;
448		tmpl = bundle.b_templ + slot;
449		if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';'))
450			tmpl++;
451		if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
452			db_printf("\n");
453			goto out;
454		}
455
456		/* Unit + slot. */
457		db_printf("[%c%d] ", *tmpl, slot);
458
459		/* Predicate. */
460		if (i->i_oper[0].o_value != 0) {
461			asm_operand(i->i_oper+0, buf, loc);
462			db_printf("(%s) ", buf);
463		} else
464			db_printf("   ");
465
466		/* Mnemonic & completers. */
467		asm_mnemonic(i->i_op, buf);
468		db_printf(buf);
469		n = 0;
470		while (n < i->i_ncmpltrs) {
471			asm_completer(i->i_cmpltr + n, buf);
472			db_printf(buf);
473			n++;
474		}
475
476		db_printf(" ");
477
478		/* Operands. */
479		n = 1;
480		while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
481			if (n > 1) {
482				if (n == i->i_srcidx)
483					db_printf("=");
484				else
485					db_printf(",");
486			}
487			asm_operand(i->i_oper + n, buf, loc);
488			db_printf(buf);
489			n++;
490		}
491	} else {
492		tmpl = NULL;
493		slot = 2;
494	}
495	db_printf("\n");
496
497out:
498	slot++;
499	if (slot == 1 && tmpl[1] == 'L')
500		slot++;
501	if (slot > 2)
502		slot = 16;
503	return (loc + slot);
504}
505
506
507static void
508db_show_vector(db_expr_t addr, bool have_addr, db_expr_t count,
509	       const char *modif)
510{
511	extern void db_print_vector(u_int, int);
512	u_int vector;
513
514	if (have_addr) {
515		vector = ((addr >> 4) % 16) * 10 + (addr % 16);
516		if (vector >= 256)
517			db_printf("error: vector %u not in range [0..255]\n",
518			    vector);
519		else
520			db_print_vector(vector, 1);
521	} else
522		for (vector = 0; vector < 256; vector++)
523			db_print_vector(vector, 0);
524}
525