xref: /netbsd-src/sys/arch/ia64/ia64/db_interface.c (revision dbfa10e52a5827a2b548912aaaea11468b4c7f47)
1 /* $NetBSD: db_interface.c,v 1.10 2022/10/26 23:38:08 riastradh 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.10 2022/10/26 23:38:08 riastradh 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_active.h>
99 #include <ddb/db_sym.h>
100 #include <ddb/db_command.h>
101 #include <ddb/db_extern.h>
102 #include <ddb/db_access.h>
103 #include <ddb/db_output.h>
104 #include <ddb/db_variables.h>
105 #include <ddb/db_interface.h>
106 #include <ddb/db_run.h>
107 
108 #include <ia64/disasm/disasm.h>
109 
110 int	db_active = 0;
111 
112 db_regs_t *ddb_regp;
113 
114 static void db_show_vector(db_expr_t, bool, db_expr_t, const char *);
115 
116 const struct db_command db_machine_command_table[] = {
117 	{ DDB_ADD_CMD("vector", db_show_vector, 0,
118 	  "Display information about vectors",
119 	  "[vector]",
120 	  "   vector:\tthe vector to show (all vectors otherwise)") },
121 
122 	{ DDB_END_CMD },
123 };
124 
125 static int
db_frame(const struct db_variable * vp,db_expr_t * valuep,int opcode)126 db_frame(const struct db_variable *vp, db_expr_t *valuep, int opcode)
127 {
128 	uint64_t *reg;
129 	struct trapframe *f = NULL;
130 
131 	if (vp->modif != NULL && *vp->modif == 'u') {
132 	  if (curlwp != NULL)
133 	    f = curlwp->l_md.md_tf;
134 	} else	f = DDB_REGS;
135 
136 	reg = (uint64_t*)((uintptr_t) f + (uintptr_t)vp->valuep);
137 
138 	switch (opcode) {
139 	case DB_VAR_GET:
140 		*valuep = *reg;
141 		break;
142 	case DB_VAR_SET:
143 		*reg = *valuep;
144 		break;
145 	default:
146 		panic("db_frame: unknown op %d", opcode);
147 	}
148 	return (0);
149 }
150 
151 static int
db_getip(const struct db_variable * vp,db_expr_t * valuep,int opcode)152 db_getip(const struct db_variable *vp, db_expr_t *valuep, int opcode)
153 {
154 	u_long iip, slot;
155 	struct trapframe *f = NULL;
156 
157 	if (vp->modif != NULL && *vp->modif == 'u') {
158 	  if (curlwp != NULL)
159 	    f = curlwp->l_md.md_tf;
160 	} else	f = DDB_REGS;
161 
162 	switch (opcode) {
163 	case DB_VAR_GET:
164 		iip = f->tf_special.iip;
165 		slot = (f->tf_special.psr >> 41) & 3;
166 		*valuep = iip + slot;
167 		break;
168 
169 	case DB_VAR_SET:
170 		iip = *valuep & ~0xf;
171 		slot = *valuep & 0xf;
172 		if (slot > 2)
173 			return (0);
174 		f->tf_special.iip = iip;
175 		f->tf_special.psr &= ~IA64_PSR_RI;
176 		f->tf_special.psr |= slot << 41;
177 		break;
178 
179 	default:
180 		panic("db_getip: unknown op %d", opcode);
181 	}
182 	return (0);
183 }
184 
185 static int
db_getrse(const struct db_variable * vp,db_expr_t * valuep,int opcode)186 db_getrse(const struct db_variable *vp, db_expr_t *valuep, int opcode)
187 {
188 	u_int64_t *reg;
189 	uint64_t bsp;
190 	int nats, regno, sof;
191 	struct trapframe *f = NULL;
192 
193 	if (vp->modif != NULL && *vp->modif == 'u') {
194 	  if (curlwp != NULL)
195 	    f = curlwp->l_md.md_tf;
196 	} else	f = DDB_REGS;
197 
198 
199 	regno = (int)(intptr_t)valuep;
200 	bsp = f->tf_special.bspstore + f->tf_special.ndirty;
201 	sof = (int)(f->tf_special.cfm & 0x7f);
202 
203 	if (regno >= sof)
204 		return (0);
205 
206 	nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63;
207 	reg = (void*)(bsp - ((sof - regno + nats) << 3));
208 
209 
210 	switch (opcode) {
211 	case DB_VAR_GET:
212 		*valuep = *reg;
213 		break;
214 	case DB_VAR_SET:
215 		*reg = *valuep;
216 		break;
217 	default:
218 		panic("db_getrse: unknown op %d", opcode);
219 	}
220 	return (0);
221 }
222 
223 
224 #define	DB_OFFSET(x)	(db_expr_t *)offsetof(struct trapframe, x)
225 const struct db_variable db_regs[] = {
226 	{"ip",		NULL,				db_getip},
227 	{"cr.ifs",	DB_OFFSET(tf_special.cfm),	db_frame},
228 	{"cr.ifa",	DB_OFFSET(tf_special.ifa),	db_frame},
229 	{"ar.bspstore",	DB_OFFSET(tf_special.bspstore),	db_frame},
230 	{"ndirty",	DB_OFFSET(tf_special.ndirty),	db_frame},
231 	{"rp",		DB_OFFSET(tf_special.rp),	db_frame},
232 	{"ar.pfs",	DB_OFFSET(tf_special.pfs),	db_frame},
233 	{"psr",		DB_OFFSET(tf_special.psr),	db_frame},
234 	{"cr.isr",	DB_OFFSET(tf_special.isr),	db_frame},
235 	{"pr",		DB_OFFSET(tf_special.pr),	db_frame},
236 	{"ar.rsc",	DB_OFFSET(tf_special.rsc),	db_frame},
237 	{"ar.rnat",	DB_OFFSET(tf_special.rnat),	db_frame},
238 	{"ar.unat",	DB_OFFSET(tf_special.unat),	db_frame},
239 	{"ar.fpsr",	DB_OFFSET(tf_special.fpsr),	db_frame},
240 	{"gp",		DB_OFFSET(tf_special.gp),	db_frame},
241 	{"sp",		DB_OFFSET(tf_special.sp),	db_frame},
242 	{"tp",		DB_OFFSET(tf_special.tp),	db_frame},
243 	{"b6",		DB_OFFSET(tf_scratch.br6),	db_frame},
244 	{"b7",		DB_OFFSET(tf_scratch.br7),	db_frame},
245 	{"r2",		DB_OFFSET(tf_scratch.gr2),	db_frame},
246 	{"r3",		DB_OFFSET(tf_scratch.gr3),	db_frame},
247 	{"r8",		DB_OFFSET(tf_scratch.gr8),	db_frame},
248 	{"r9",		DB_OFFSET(tf_scratch.gr9),	db_frame},
249 	{"r10",		DB_OFFSET(tf_scratch.gr10),	db_frame},
250 	{"r11",		DB_OFFSET(tf_scratch.gr11),	db_frame},
251 	{"r14",		DB_OFFSET(tf_scratch.gr14),	db_frame},
252 	{"r15",		DB_OFFSET(tf_scratch.gr15),	db_frame},
253 	{"r16",		DB_OFFSET(tf_scratch.gr16),	db_frame},
254 	{"r17",		DB_OFFSET(tf_scratch.gr17),	db_frame},
255 	{"r18",		DB_OFFSET(tf_scratch.gr18),	db_frame},
256 	{"r19",		DB_OFFSET(tf_scratch.gr19),	db_frame},
257 	{"r20",		DB_OFFSET(tf_scratch.gr20),	db_frame},
258 	{"r21",		DB_OFFSET(tf_scratch.gr21),	db_frame},
259 	{"r22",		DB_OFFSET(tf_scratch.gr22),	db_frame},
260 	{"r23",		DB_OFFSET(tf_scratch.gr23),	db_frame},
261 	{"r24",		DB_OFFSET(tf_scratch.gr24),	db_frame},
262 	{"r25",		DB_OFFSET(tf_scratch.gr25),	db_frame},
263 	{"r26",		DB_OFFSET(tf_scratch.gr26),	db_frame},
264 	{"r27",		DB_OFFSET(tf_scratch.gr27),	db_frame},
265 	{"r28",		DB_OFFSET(tf_scratch.gr28),	db_frame},
266 	{"r29",		DB_OFFSET(tf_scratch.gr29),	db_frame},
267 	{"r30",		DB_OFFSET(tf_scratch.gr30),	db_frame},
268 	{"r31",		DB_OFFSET(tf_scratch.gr31),	db_frame},
269 	{"r32",		(db_expr_t*)0,			db_getrse},
270 	{"r33",		(db_expr_t*)1,			db_getrse},
271 	{"r34",		(db_expr_t*)2,			db_getrse},
272 	{"r35",		(db_expr_t*)3,			db_getrse},
273 	{"r36",		(db_expr_t*)4,			db_getrse},
274 	{"r37",		(db_expr_t*)5,			db_getrse},
275 	{"r38",		(db_expr_t*)6,			db_getrse},
276 	{"r39",		(db_expr_t*)7,			db_getrse},
277 	{"r40",		(db_expr_t*)8,			db_getrse},
278 	{"r41",		(db_expr_t*)9,			db_getrse},
279 	{"r42",		(db_expr_t*)10,			db_getrse},
280 	{"r43",		(db_expr_t*)11,			db_getrse},
281 	{"r44",		(db_expr_t*)12,			db_getrse},
282 	{"r45",		(db_expr_t*)13,			db_getrse},
283 	{"r46",		(db_expr_t*)14,			db_getrse},
284 	{"r47",		(db_expr_t*)15,			db_getrse},
285 	{"r48",		(db_expr_t*)16,			db_getrse},
286 	{"r49",		(db_expr_t*)17,			db_getrse},
287 	{"r50",		(db_expr_t*)18,			db_getrse},
288 	{"r51",		(db_expr_t*)19,			db_getrse},
289 	{"r52",		(db_expr_t*)20,			db_getrse},
290 	{"r53",		(db_expr_t*)21,			db_getrse},
291 	{"r54",		(db_expr_t*)22,			db_getrse},
292 	{"r55",		(db_expr_t*)23,			db_getrse},
293 	{"r56",		(db_expr_t*)24,			db_getrse},
294 	{"r57",		(db_expr_t*)25,			db_getrse},
295 	{"r58",		(db_expr_t*)26,			db_getrse},
296 	{"r59",		(db_expr_t*)27,			db_getrse},
297 	{"r60",		(db_expr_t*)28,			db_getrse},
298 	{"r61",		(db_expr_t*)29,			db_getrse},
299 	{"r62",		(db_expr_t*)30,			db_getrse},
300 	{"r63",		(db_expr_t*)31,			db_getrse},
301 	{"r64",		(db_expr_t*)32,			db_getrse},
302 	{"r65",		(db_expr_t*)33,			db_getrse},
303 	{"r66",		(db_expr_t*)34,			db_getrse},
304 	{"r67",		(db_expr_t*)35,			db_getrse},
305 	{"r68",		(db_expr_t*)36,			db_getrse},
306 	{"r69",		(db_expr_t*)37,			db_getrse},
307 	{"r70",		(db_expr_t*)38,			db_getrse},
308 	{"r71",		(db_expr_t*)39,			db_getrse},
309 	{"r72",		(db_expr_t*)40,			db_getrse},
310 	{"r73",		(db_expr_t*)41,			db_getrse},
311 	{"r74",		(db_expr_t*)42,			db_getrse},
312 	{"r75",		(db_expr_t*)43,			db_getrse},
313 	{"r76",		(db_expr_t*)44,			db_getrse},
314 	{"r77",		(db_expr_t*)45,			db_getrse},
315 	{"r78",		(db_expr_t*)46,			db_getrse},
316 	{"r79",		(db_expr_t*)47,			db_getrse},
317 	{"r80",		(db_expr_t*)48,			db_getrse},
318 	{"r81",		(db_expr_t*)49,			db_getrse},
319 	{"r82",		(db_expr_t*)50,			db_getrse},
320 	{"r83",		(db_expr_t*)51,			db_getrse},
321 	{"r84",		(db_expr_t*)52,			db_getrse},
322 	{"r85",		(db_expr_t*)53,			db_getrse},
323 	{"r86",		(db_expr_t*)54,			db_getrse},
324 	{"r87",		(db_expr_t*)55,			db_getrse},
325 	{"r88",		(db_expr_t*)56,			db_getrse},
326 	{"r89",		(db_expr_t*)57,			db_getrse},
327 	{"r90",		(db_expr_t*)58,			db_getrse},
328 	{"r91",		(db_expr_t*)59,			db_getrse},
329 	{"r92",		(db_expr_t*)60,			db_getrse},
330 	{"r93",		(db_expr_t*)61,			db_getrse},
331 	{"r94",		(db_expr_t*)62,			db_getrse},
332 	{"r95",		(db_expr_t*)63,			db_getrse},
333 	{"r96",		(db_expr_t*)64,			db_getrse},
334 	{"r97",		(db_expr_t*)65,			db_getrse},
335 	{"r98",		(db_expr_t*)66,			db_getrse},
336 	{"r99",		(db_expr_t*)67,			db_getrse},
337 	{"r100",	(db_expr_t*)68,			db_getrse},
338 	{"r101",	(db_expr_t*)69,			db_getrse},
339 	{"r102",	(db_expr_t*)70,			db_getrse},
340 	{"r103",	(db_expr_t*)71,			db_getrse},
341 	{"r104",	(db_expr_t*)72,			db_getrse},
342 	{"r105",	(db_expr_t*)73,			db_getrse},
343 	{"r106",	(db_expr_t*)74,			db_getrse},
344 	{"r107",	(db_expr_t*)75,			db_getrse},
345 	{"r108",	(db_expr_t*)76,			db_getrse},
346 	{"r109",	(db_expr_t*)77,			db_getrse},
347 	{"r110",	(db_expr_t*)78,			db_getrse},
348 	{"r111",	(db_expr_t*)79,			db_getrse},
349 	{"r112",	(db_expr_t*)80,			db_getrse},
350 	{"r113",	(db_expr_t*)81,			db_getrse},
351 	{"r114",	(db_expr_t*)82,			db_getrse},
352 	{"r115",	(db_expr_t*)83,			db_getrse},
353 	{"r116",	(db_expr_t*)84,			db_getrse},
354 	{"r117",	(db_expr_t*)85,			db_getrse},
355 	{"r118",	(db_expr_t*)86,			db_getrse},
356 	{"r119",	(db_expr_t*)87,			db_getrse},
357 	{"r120",	(db_expr_t*)88,			db_getrse},
358 	{"r121",	(db_expr_t*)89,			db_getrse},
359 	{"r122",	(db_expr_t*)90,			db_getrse},
360 	{"r123",	(db_expr_t*)91,			db_getrse},
361 	{"r124",	(db_expr_t*)92,			db_getrse},
362 	{"r125",	(db_expr_t*)93,			db_getrse},
363 	{"r126",	(db_expr_t*)94,			db_getrse},
364 	{"r127",	(db_expr_t*)95,			db_getrse},
365 };
366 const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
367 
368 /*
369  * Read bytes from kernel address space for debugger.
370  */
371 void
db_read_bytes(vaddr_t addr,register size_t size,register char * data)372 db_read_bytes(vaddr_t addr, register size_t size, register char *data)
373 {
374 	register char	*src;
375 
376 	src = (char *)addr;
377 	while (size-- > 0)
378 		*data++ = *src++;
379 }
380 
381 /*
382  * Write bytes to kernel address space for debugger.
383  */
384 void
db_write_bytes(vaddr_t addr,register size_t size,register const char * data)385 db_write_bytes(vaddr_t addr, register size_t size, register const char *data)
386 {
387 	register char	*dst;
388 
389 	dst = (char *)addr;
390 	while (size-- > 0) {
391 		*dst++ = *data++;
392 		ia64_fc_i((vaddr_t) dst);
393 	}
394 	ia64_sync_i();
395 }
396 
397 db_expr_t
db_bkpt_set(db_expr_t inst,db_addr_t addr)398 db_bkpt_set(db_expr_t inst, db_addr_t addr)
399 {
400 	db_expr_t tmp;
401 	int slot;
402 
403 	slot = addr & 0xfUL;
404 	if (slot >= SLOT_COUNT) slot = 0;
405 
406 	tmp = inst;
407 
408 	tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot));
409 	tmp |= (0x84000 << 6) << SLOT_SHIFT(slot);
410 
411 	return tmp;
412 }
413 
414 void
cpu_Debugger(void)415 cpu_Debugger(void)
416 {
417 	printf("Broken into debugger \n");
418 	breakpoint();
419 }
420 
421 void
db_pc_advance(db_regs_t * regs)422 db_pc_advance(db_regs_t *regs)
423 {
424 
425 	if (regs == NULL)
426 		return;
427 
428 	regs->tf_special.psr += IA64_PSR_RI_1;
429 	if ((regs->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) {
430 		regs->tf_special.psr &= ~IA64_PSR_RI;
431 		regs->tf_special.iip += 16;
432 	}
433 }
434 
435 db_addr_t
db_disasm(db_addr_t loc,bool altfmt)436 db_disasm(db_addr_t loc, bool altfmt)
437 {
438 	char buf[32];
439 	struct asm_bundle bundle;
440 	const struct asm_inst *i;
441 	const char *tmpl;
442 	int n, slot;
443 
444 	slot = loc & 0xf;
445 	loc &= ~0xful;
446 	db_read_bytes(loc, 16, buf);
447 	if (asm_decode((uintptr_t)buf, &bundle)) {
448 		i = bundle.b_inst + slot;
449 		tmpl = bundle.b_templ + slot;
450 		if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';'))
451 			tmpl++;
452 		if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) {
453 			db_printf("\n");
454 			goto out;
455 		}
456 
457 		/* Unit + slot. */
458 		db_printf("[%c%d] ", *tmpl, slot);
459 
460 		/* Predicate. */
461 		if (i->i_oper[0].o_value != 0) {
462 			asm_operand(i->i_oper+0, buf, sizeof(buf), loc);
463 			db_printf("(%s) ", buf);
464 		} else
465 			db_printf("   ");
466 
467 		/* Mnemonic & completers. */
468 		asm_mnemonic(i->i_op, buf, sizeof(buf));
469 		db_printf(buf);
470 		n = 0;
471 		while (n < i->i_ncmpltrs) {
472 			asm_completer(i->i_cmpltr + n, buf, sizeof(buf));
473 			db_printf(buf);
474 			n++;
475 		}
476 
477 		db_printf(" ");
478 
479 		/* Operands. */
480 		n = 1;
481 		while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) {
482 			if (n > 1) {
483 				if (n == i->i_srcidx)
484 					db_printf("=");
485 				else
486 					db_printf(",");
487 			}
488 			asm_operand(i->i_oper + n, buf, sizeof(buf), loc);
489 			db_printf(buf);
490 			n++;
491 		}
492 	} else {
493 		tmpl = NULL;
494 		slot = 2;
495 	}
496 	db_printf("\n");
497 
498 out:
499 	slot++;
500 	if (slot == 1 && tmpl[1] == 'L')
501 		slot++;
502 	if (slot > 2)
503 		slot = 16;
504 	return (loc + slot);
505 }
506 
507 
508 static void
db_show_vector(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)509 db_show_vector(db_expr_t addr, bool have_addr, db_expr_t count,
510 	       const char *modif)
511 {
512 	extern void db_print_vector(u_int, int);
513 	u_int vector;
514 
515 	if (have_addr) {
516 		vector = ((addr >> 4) % 16) * 10 + (addr % 16);
517 		if (vector >= 256)
518 			db_printf("error: vector %u not in range [0..255]\n",
519 			    vector);
520 		else
521 			db_print_vector(vector, 1);
522 	} else
523 		for (vector = 0; vector < 256; vector++)
524 			db_print_vector(vector, 0);
525 }
526