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