xref: /openbsd-src/sys/arch/sparc64/sparc64/db_interface.c (revision da5607f65bdedd8aa46e3abfd846bd3bccd1e805)
1 /*	$OpenBSD: db_interface.c,v 1.66 2024/06/26 01:40:49 jsg Exp $	*/
2 /*	$NetBSD: db_interface.c,v 1.61 2001/07/31 06:55:47 eeh Exp $ */
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie the
27  * rights to redistribute these changes.
28  *
29  *	From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
30  */
31 
32 #include <sys/param.h>
33 #include <sys/proc.h>
34 #include <sys/user.h>
35 #include <sys/reboot.h>
36 #include <sys/systm.h>
37 #include <sys/malloc.h>
38 #include <sys/mutex.h>
39 
40 #include <dev/cons.h>
41 
42 #include <machine/db_machdep.h>
43 #include <ddb/db_command.h>
44 #include <ddb/db_sym.h>
45 #include <ddb/db_variables.h>
46 #include <ddb/db_extern.h>
47 #include <ddb/db_access.h>
48 #include <ddb/db_output.h>
49 #include <ddb/db_interface.h>
50 #include <ddb/db_run.h>
51 
52 #include <machine/instr.h>
53 #include <machine/cpu.h>
54 #include <machine/openfirm.h>
55 #include <machine/ctlreg.h>
56 #include <machine/pte.h>
57 
58 #ifdef notyet
59 #include "fb.h"
60 #include "esp_sbus.h"
61 #endif
62 
63 #include "tda.h"
64 
65 #ifdef MULTIPROCESSOR
66 struct db_mutex ddb_mp_mutex = DB_MUTEX_INITIALIZER;
67 volatile int ddb_state = DDB_STATE_NOT_RUNNING;
68 volatile cpuid_t ddb_active_cpu;
69 int		 db_switch_cpu;
70 struct cpu_info *db_switch_to_cpu;
71 #endif
72 
73 db_regs_t	ddb_regs;	/* register state */
74 
75 extern void OF_enter(void);
76 
77 static long nil;
78 
79 static int
db__char_value(struct db_variable * var,db_expr_t * expr,int mode)80 db__char_value(struct db_variable *var, db_expr_t *expr, int mode)
81 {
82 
83 	switch (mode) {
84 	case DB_VAR_SET:
85 		*var->valuep = *(char *)expr;
86 		break;
87 	case DB_VAR_GET:
88 		*expr = *(char *)var->valuep;
89 		break;
90 #ifdef DIAGNOSTIC
91 	default:
92 		printf("db__char_value: mode %d\n", mode);
93 		break;
94 #endif
95 	}
96 
97 	return 0;
98 }
99 
100 #ifdef notdef_yet
101 static int
db__short_value(struct db_variable * var,db_expr_t * expr,int mode)102 db__short_value(struct db_variable *var, db_expr_t *expr, int mode)
103 {
104 
105 	switch (mode) {
106 	case DB_VAR_SET:
107 		*var->valuep = *(short *)expr;
108 		break;
109 	case DB_VAR_GET:
110 		*expr = *(short *)var->valuep;
111 		break;
112 #ifdef DIAGNOSTIC
113 	default:
114 		printf("db__short_value: mode %d\n", mode);
115 		break;
116 #endif
117 	}
118 
119 	return 0;
120 }
121 #endif
122 
123 struct db_variable db_regs[] = {
124 	{ "tstate", (long *)&DDB_TF->tf_tstate, FCN_NULL, },
125 	{ "pc", (long *)&DDB_TF->tf_pc, FCN_NULL, },
126 	{ "npc", (long *)&DDB_TF->tf_npc, FCN_NULL, },
127 	{ "ipl", (long *)&DDB_TF->tf_oldpil, db__char_value, },
128 	{ "y", (long *)&DDB_TF->tf_y, db_var_rw_int, },
129 	{ "g0", (long *)&nil, FCN_NULL, },
130 	{ "g1", (long *)&DDB_TF->tf_global[1], FCN_NULL, },
131 	{ "g2", (long *)&DDB_TF->tf_global[2], FCN_NULL, },
132 	{ "g3", (long *)&DDB_TF->tf_global[3], FCN_NULL, },
133 	{ "g4", (long *)&DDB_TF->tf_global[4], FCN_NULL, },
134 	{ "g5", (long *)&DDB_TF->tf_global[5], FCN_NULL, },
135 	{ "g6", (long *)&DDB_TF->tf_global[6], FCN_NULL, },
136 	{ "g7", (long *)&DDB_TF->tf_global[7], FCN_NULL, },
137 	{ "o0", (long *)&DDB_TF->tf_out[0], FCN_NULL, },
138 	{ "o1", (long *)&DDB_TF->tf_out[1], FCN_NULL, },
139 	{ "o2", (long *)&DDB_TF->tf_out[2], FCN_NULL, },
140 	{ "o3", (long *)&DDB_TF->tf_out[3], FCN_NULL, },
141 	{ "o4", (long *)&DDB_TF->tf_out[4], FCN_NULL, },
142 	{ "o5", (long *)&DDB_TF->tf_out[5], FCN_NULL, },
143 	{ "o6", (long *)&DDB_TF->tf_out[6], FCN_NULL, },
144 	{ "o7", (long *)&DDB_TF->tf_out[7], FCN_NULL, },
145 	{ "l0", (long *)&DDB_TF->tf_local[0], FCN_NULL, },
146 	{ "l1", (long *)&DDB_TF->tf_local[1], FCN_NULL, },
147 	{ "l2", (long *)&DDB_TF->tf_local[2], FCN_NULL, },
148 	{ "l3", (long *)&DDB_TF->tf_local[3], FCN_NULL, },
149 	{ "l4", (long *)&DDB_TF->tf_local[4], FCN_NULL, },
150 	{ "l5", (long *)&DDB_TF->tf_local[5], FCN_NULL, },
151 	{ "l6", (long *)&DDB_TF->tf_local[6], FCN_NULL, },
152 	{ "l7", (long *)&DDB_TF->tf_local[7], FCN_NULL, },
153 	{ "i0", (long *)&DDB_FR->fr_arg[0], FCN_NULL, },
154 	{ "i1", (long *)&DDB_FR->fr_arg[1], FCN_NULL, },
155 	{ "i2", (long *)&DDB_FR->fr_arg[2], FCN_NULL, },
156 	{ "i3", (long *)&DDB_FR->fr_arg[3], FCN_NULL, },
157 	{ "i4", (long *)&DDB_FR->fr_arg[4], FCN_NULL, },
158 	{ "i5", (long *)&DDB_FR->fr_arg[5], FCN_NULL, },
159 	{ "i6", (long *)&DDB_FR->fr_arg[6], FCN_NULL, },
160 	{ "i7", (long *)&DDB_FR->fr_arg[7], FCN_NULL, },
161 	{ "f0", (long *)&DDB_FP->fs_regs[0], FCN_NULL, },
162 	{ "f2", (long *)&DDB_FP->fs_regs[2], FCN_NULL, },
163 	{ "f4", (long *)&DDB_FP->fs_regs[4], FCN_NULL, },
164 	{ "f6", (long *)&DDB_FP->fs_regs[6], FCN_NULL, },
165 	{ "f8", (long *)&DDB_FP->fs_regs[8], FCN_NULL, },
166 	{ "f10", (long *)&DDB_FP->fs_regs[10], FCN_NULL, },
167 	{ "f12", (long *)&DDB_FP->fs_regs[12], FCN_NULL, },
168 	{ "f14", (long *)&DDB_FP->fs_regs[14], FCN_NULL, },
169 	{ "f16", (long *)&DDB_FP->fs_regs[16], FCN_NULL, },
170 	{ "f18", (long *)&DDB_FP->fs_regs[18], FCN_NULL, },
171 	{ "f20", (long *)&DDB_FP->fs_regs[20], FCN_NULL, },
172 	{ "f22", (long *)&DDB_FP->fs_regs[22], FCN_NULL, },
173 	{ "f24", (long *)&DDB_FP->fs_regs[24], FCN_NULL, },
174 	{ "f26", (long *)&DDB_FP->fs_regs[26], FCN_NULL, },
175 	{ "f28", (long *)&DDB_FP->fs_regs[28], FCN_NULL, },
176 	{ "f30", (long *)&DDB_FP->fs_regs[30], FCN_NULL, },
177 	{ "f32", (long *)&DDB_FP->fs_regs[32], FCN_NULL, },
178 	{ "f34", (long *)&DDB_FP->fs_regs[34], FCN_NULL, },
179 	{ "f36", (long *)&DDB_FP->fs_regs[36], FCN_NULL, },
180 	{ "f38", (long *)&DDB_FP->fs_regs[38], FCN_NULL, },
181 	{ "f40", (long *)&DDB_FP->fs_regs[40], FCN_NULL, },
182 	{ "f42", (long *)&DDB_FP->fs_regs[42], FCN_NULL, },
183 	{ "f44", (long *)&DDB_FP->fs_regs[44], FCN_NULL, },
184 	{ "f46", (long *)&DDB_FP->fs_regs[46], FCN_NULL, },
185 	{ "f48", (long *)&DDB_FP->fs_regs[48], FCN_NULL, },
186 	{ "f50", (long *)&DDB_FP->fs_regs[50], FCN_NULL, },
187 	{ "f52", (long *)&DDB_FP->fs_regs[52], FCN_NULL, },
188 	{ "f54", (long *)&DDB_FP->fs_regs[54], FCN_NULL, },
189 	{ "f56", (long *)&DDB_FP->fs_regs[56], FCN_NULL, },
190 	{ "f58", (long *)&DDB_FP->fs_regs[58], FCN_NULL, },
191 	{ "f60", (long *)&DDB_FP->fs_regs[60], FCN_NULL, },
192 	{ "f62", (long *)&DDB_FP->fs_regs[62], FCN_NULL, },
193 	{ "fsr", (long *)&DDB_FP->fs_fsr, FCN_NULL, },
194 	{ "gsr", (long *)&DDB_FP->fs_gsr, FCN_NULL, },
195 
196 };
197 struct db_variable *db_eregs = db_regs + nitems(db_regs);
198 
199 extern label_t	*db_recover;
200 
201 extern char *trap_type[];
202 
203 void kdb_kbd_trap(struct trapframe *);
204 void db_prom_cmd(db_expr_t, int, db_expr_t, char *);
205 void db_proc_cmd(db_expr_t, int, db_expr_t, char *);
206 void db_ctx_cmd(db_expr_t, int, db_expr_t, char *);
207 void db_dump_window(db_expr_t, int, db_expr_t, char *);
208 void db_dump_stack(db_expr_t, int, db_expr_t, char *);
209 void db_dump_trap(db_expr_t, int, db_expr_t, char *);
210 void db_dump_fpstate(db_expr_t, int, db_expr_t, char *);
211 void db_dump_ts(db_expr_t, int, db_expr_t, char *);
212 void db_dump_pcb(db_expr_t, int, db_expr_t, char *);
213 void db_dump_pv(db_expr_t, int, db_expr_t, char *);
214 void db_setpcb(db_expr_t, int, db_expr_t, char *);
215 void db_dump_dtlb(db_expr_t, int, db_expr_t, char *);
216 void db_dump_itlb(db_expr_t, int, db_expr_t, char *);
217 void db_dump_dtsb(db_expr_t, int, db_expr_t, char *);
218 void db_pmap_kernel(db_expr_t, int, db_expr_t, char *);
219 void db_pload_cmd(db_expr_t, int, db_expr_t, char *);
220 void db_pmap_cmd(db_expr_t, int, db_expr_t, char *);
221 void db_lock(db_expr_t, int, db_expr_t, char *);
222 void db_watch(db_expr_t, int, db_expr_t, char *);
223 void db_xir(db_expr_t, int, db_expr_t, char *);
224 
225 static void db_dump_pmap(struct pmap*);
226 
227 #ifdef MULTIPROCESSOR
228 void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
229 void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
230 void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
231 void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
232 #endif
233 
234 /*
235  * Received keyboard interrupt sequence.
236  */
237 void
kdb_kbd_trap(struct trapframe * tf)238 kdb_kbd_trap(struct trapframe *tf)
239 {
240 	if (db_active == 0 /* && (boothowto & RB_KDB) */) {
241 		printf("\n\nkernel: keyboard interrupt tf=%p\n", tf);
242 		db_ktrap(-1, tf);
243 	}
244 }
245 
246 /*
247  *  db_ktrap - field a TRACE or BPT trap
248  */
249 int
db_ktrap(int type,register struct trapframe * tf)250 db_ktrap(int type, register struct trapframe *tf)
251 {
252 	int s, tl;
253 	struct trapstate *ts = &ddb_regs.ddb_ts[0];
254 	extern int savetstate(struct trapstate *ts);
255 	extern void restoretstate(int tl, struct trapstate *ts);
256 
257 #if NTDA > 0
258 	tda_full_blast();
259 #endif
260 
261 	fb_unblank();
262 
263 	switch (type) {
264 	case T_BREAKPOINT:	/* breakpoint */
265 	case -1:		/* keyboard interrupt */
266 		break;
267 	default:
268 		printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
269 		if (db_recover != 0) {
270 			OF_enter();
271 			db_error("Faulted in DDB; continuing...\n");
272 			OF_enter();
273 			/*NOTREACHED*/
274 		}
275 		db_recover = (label_t *)1;
276 	}
277 
278 #ifdef MULTIPROCESSOR
279 	db_mtx_enter(&ddb_mp_mutex);
280 	if (ddb_state == DDB_STATE_EXITING)
281 		ddb_state = DDB_STATE_NOT_RUNNING;
282 	db_mtx_leave(&ddb_mp_mutex);
283 	while (db_enter_ddb()) {
284 #endif
285 
286 	/* Should switch to kdb`s own stack here. */
287 	write_all_windows();
288 
289 	ddb_regs.ddb_tf = *tf;
290 	if (fpproc) {
291 		savefpstate(fpproc->p_md.md_fpstate);
292 		ddb_regs.ddb_fpstate = *fpproc->p_md.md_fpstate;
293 		loadfpstate(fpproc->p_md.md_fpstate);
294 	}
295 
296 	s = splhigh();
297 	db_active++;
298 	cnpollc(1);
299 	/* Need to do spl stuff till cnpollc works */
300 	tl = ddb_regs.ddb_tl = savetstate(ts);
301 	db_dump_ts(0, 0, 0, 0);
302 	db_trap(type, 0/*code*/);
303 	restoretstate(tl,ts);
304 	cnpollc(0);
305 	db_active--;
306 	splx(s);
307 
308 	if (fpproc) {
309 		*fpproc->p_md.md_fpstate = ddb_regs.ddb_fpstate;
310 		loadfpstate(fpproc->p_md.md_fpstate);
311 	}
312 #if 0
313 	/* We will not alter the machine's running state until we get everything else working */
314 	*(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr;
315 #endif
316 	*tf = ddb_regs.ddb_tf;
317 
318 #ifdef MULTIPROCESSOR
319 		if (!db_switch_cpu)
320 			ddb_state = DDB_STATE_EXITING;
321 	}
322 #endif
323 
324 	return (1);
325 }
326 
327 #ifdef MULTIPROCESSOR
328 
329 void ipi_db(void);
330 
331 void
db_cpuinfo_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)332 db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
333 {
334 	struct cpu_info *ci;
335 
336 	for (ci = cpus; ci != NULL; ci = ci->ci_next) {
337 		db_printf("%c%4d: ", (ci == curcpu()) ? '*' : ' ',
338 		    ci->ci_cpuid);
339 		switch(ci->ci_ddb_paused) {
340 		case CI_DDB_RUNNING:
341 			db_printf("running\n");
342 			break;
343 		case CI_DDB_SHOULDSTOP:
344 			db_printf("stopping\n");
345 			break;
346 		case CI_DDB_STOPPED:
347 			db_printf("stopped\n");
348 			break;
349 		case CI_DDB_ENTERDDB:
350 			db_printf("entering ddb\n");
351 			break;
352 		case CI_DDB_INDDB:
353 			db_printf("ddb\n");
354 			break;
355 		default:
356 			db_printf("? (%d)\n",
357 			    ci->ci_ddb_paused);
358 			break;
359 		}
360 	}
361 }
362 
363 void
db_startproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)364 db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
365 {
366 	struct cpu_info *ci;
367 
368 	if (have_addr) {
369 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
370 			if (addr == ci->ci_cpuid) {
371 				db_startcpu(ci);
372 				break;
373 			}
374 		}
375 		if (ci == NULL)
376 			db_printf("Invalid cpu %d\n", (int)addr);
377 	} else {
378 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
379 			if (ci != curcpu())
380 				db_startcpu(ci);
381 		}
382 	}
383 }
384 
385 void
db_stopproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)386 db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
387 {
388 	struct cpu_info *ci;
389 
390 	if (have_addr) {
391 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
392 			if (addr == ci->ci_cpuid) {
393 				db_stopcpu(ci);
394 				break;
395 			}
396 		}
397 		if (ci == NULL)
398 			db_printf("Invalid cpu %d\n", (int)addr);
399 	} else {
400 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
401 			if (ci != curcpu())
402 				db_stopcpu(ci);
403 		}
404 	}
405 }
406 
407 void
db_ddbproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)408 db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
409 {
410 	struct cpu_info *ci;
411 
412 	if (have_addr) {
413 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
414 			if (addr == ci->ci_cpuid && ci != curcpu()) {
415 				db_stopcpu(ci);
416 				db_switch_to_cpu = ci;
417 				db_switch_cpu = 1;
418 				db_cmd_loop_done = 1;
419 				break;
420 			}
421 		}
422 		if (ci == NULL)
423 			db_printf("Invalid cpu %d\n", (int)addr);
424 	} else {
425 		db_printf("CPU not specified\n");
426 	}
427 }
428 
429 int
db_enter_ddb(void)430 db_enter_ddb(void)
431 {
432 	struct cpu_info *ci;
433 
434 	db_mtx_enter(&ddb_mp_mutex);
435 
436 	/* If we are first in, grab ddb and stop all other CPUs */
437 	if (ddb_state == DDB_STATE_NOT_RUNNING) {
438 		ddb_active_cpu = cpu_number();
439 		ddb_state = DDB_STATE_RUNNING;
440 		curcpu()->ci_ddb_paused = CI_DDB_INDDB;
441 		db_mtx_leave(&ddb_mp_mutex);
442 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
443 			if (ci != curcpu() &&
444 			    ci->ci_ddb_paused != CI_DDB_STOPPED) {
445 				ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
446 				sparc64_send_ipi(ci->ci_itid, ipi_db, 0, 0);
447 			}
448 		}
449 		return (1);
450 	}
451 
452 	/* Leaving ddb completely.  Start all other CPUs and return 0 */
453 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
454 		for (ci = cpus; ci != NULL; ci = ci->ci_next)
455 			ci->ci_ddb_paused = CI_DDB_RUNNING;
456 		db_mtx_leave(&ddb_mp_mutex);
457 		return (0);
458 	}
459 
460 	/* We're switching to another CPU.  db_ddbproc_cmd() has made sure
461 	 * it is waiting for ddb, we just have to set ddb_active_cpu. */
462 	if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
463 		curcpu()->ci_ddb_paused = CI_DDB_SHOULDSTOP;
464 		db_switch_cpu = 0;
465 		ddb_active_cpu = db_switch_to_cpu->ci_cpuid;
466 		db_switch_to_cpu->ci_ddb_paused = CI_DDB_ENTERDDB;
467 	}
468 
469 	/* Wait until we should enter ddb or resume */
470 	while (ddb_active_cpu != cpu_number() &&
471 	    curcpu()->ci_ddb_paused != CI_DDB_RUNNING) {
472 		if (curcpu()->ci_ddb_paused == CI_DDB_SHOULDSTOP)
473 			curcpu()->ci_ddb_paused = CI_DDB_STOPPED;
474 		db_mtx_leave(&ddb_mp_mutex);
475 
476 		/* Busy wait without locking, we'll confirm with lock later */
477 		while (ddb_active_cpu != cpu_number() &&
478 		    curcpu()->ci_ddb_paused != CI_DDB_RUNNING)
479 			CPU_BUSY_CYCLE();
480 
481 		db_mtx_enter(&ddb_mp_mutex);
482 	}
483 
484 	/* Either enter ddb or exit */
485 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
486 		curcpu()->ci_ddb_paused = CI_DDB_INDDB;
487 		db_mtx_leave(&ddb_mp_mutex);
488 		return (1);
489 	} else {
490 		db_mtx_leave(&ddb_mp_mutex);
491 		return (0);
492 	}
493 }
494 
495 void
db_startcpu(struct cpu_info * ci)496 db_startcpu(struct cpu_info *ci)
497 {
498 	if (ci != curcpu()) {
499 		db_mtx_enter(&ddb_mp_mutex);
500 		ci->ci_ddb_paused = CI_DDB_RUNNING;
501 		db_mtx_leave(&ddb_mp_mutex);
502 	}
503 }
504 
505 void
db_stopcpu(struct cpu_info * ci)506 db_stopcpu(struct cpu_info *ci)
507 {
508 	db_mtx_enter(&ddb_mp_mutex);
509 	if (ci != curcpu() && ci->ci_ddb_paused != CI_DDB_STOPPED) {
510 		ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
511 		db_mtx_leave(&ddb_mp_mutex);
512 		sparc64_send_ipi(ci->ci_itid, ipi_db, 0, 0);
513 	} else {
514 		db_mtx_leave(&ddb_mp_mutex);
515 	}
516 }
517 
518 #endif
519 
520 /*
521  * Read bytes from kernel address space for debugger.
522  */
523 void
db_read_bytes(vaddr_t addr,size_t size,void * datap)524 db_read_bytes(vaddr_t addr, size_t size, void *datap)
525 {
526 	char *data = datap;
527 	register char	*src;
528 
529 	src = (char *)addr;
530 	while (size-- > 0) {
531 		if (src >= (char *)VM_MIN_KERNEL_ADDRESS)
532 			*data++ = probeget((paddr_t)(u_long)src++, ASI_P, 1);
533 		else
534 			_copyin(src++, data++, sizeof(u_char));
535 	}
536 }
537 
538 
539 /*
540  * Write bytes to kernel address space for debugger.
541  */
542 void
db_write_bytes(vaddr_t addr,size_t size,void * datap)543 db_write_bytes(vaddr_t addr, size_t size, void *datap)
544 {
545 	char *data = datap;
546 	register char	*dst;
547 	extern vaddr_t ktext;
548 	extern paddr_t ktextp;
549 
550 	dst = (char *)addr;
551 	while (size-- > 0) {
552 		if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS+0x800000))
553 			*dst = *data;
554 		else if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) &&
555 			 (dst < (char *)VM_MIN_KERNEL_ADDRESS+0x800000))
556 			/* Read Only mapping -- need to do a bypass access */
557 			stba((u_long)dst - ktext + ktextp, ASI_PHYS_CACHED, *data);
558 		else
559 			copyout(data, dst, sizeof(char));
560 		dst++, data++;
561 	}
562 
563 }
564 
565 void
db_enter(void)566 db_enter(void)
567 {
568 	/* We use the breakpoint to trap into DDB */
569 	asm("ta 1; nop");
570 }
571 
572 void
db_prom_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)573 db_prom_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
574 {
575 	OF_enter();
576 }
577 
578 #define CHEETAHP (((getver()>>32) & 0x1ff) >= 0x14)
579 unsigned long db_get_dtlb_data(int entry), db_get_dtlb_tag(int entry),
580 db_get_itlb_data(int entry), db_get_itlb_tag(int entry);
581 void db_print_itlb_entry(int entry, int i, int endc);
582 void db_print_dtlb_entry(int entry, int i, int endc);
583 
584 extern __inline__ unsigned long
db_get_dtlb_data(int entry)585 db_get_dtlb_data(int entry)
586 {
587 	unsigned long r;
588 	__asm__ volatile("ldxa [%1] %2,%0"
589 		: "=r" (r)
590 		: "r" (entry <<3), "i" (ASI_DMMU_TLB_DATA));
591 	return r;
592 }
593 
594 extern __inline__ unsigned long
db_get_dtlb_tag(int entry)595 db_get_dtlb_tag(int entry)
596 {
597 	unsigned long r;
598 	__asm__ volatile("ldxa [%1] %2,%0"
599 		: "=r" (r)
600 		: "r" (entry <<3), "i" (ASI_DMMU_TLB_TAG));
601 	return r;
602 }
603 
604 extern __inline__ unsigned long
db_get_itlb_data(int entry)605 db_get_itlb_data(int entry)
606 {
607 	unsigned long r;
608 	__asm__ volatile("ldxa [%1] %2,%0"
609 		: "=r" (r)
610 		: "r" (entry <<3), "i" (ASI_IMMU_TLB_DATA));
611 	return r;
612 }
613 
614 extern __inline__ unsigned long
db_get_itlb_tag(int entry)615 db_get_itlb_tag(int entry)
616 {
617 	unsigned long r;
618 	__asm__ volatile("ldxa [%1] %2,%0"
619 		: "=r" (r)
620 		: "r" (entry <<3), "i" (ASI_IMMU_TLB_TAG));
621 	return r;
622 }
623 
624 void
db_print_dtlb_entry(int entry,int i,int endc)625 db_print_dtlb_entry(int entry, int i, int endc)
626 {
627 	unsigned long tag, data;
628 	tag = db_get_dtlb_tag(entry);
629 	data = db_get_dtlb_data(entry);
630 	db_printf("%2d:%16.16lx %16.16lx%c", i, tag, data, endc);
631 }
632 
633 void
db_print_itlb_entry(int entry,int i,int endc)634 db_print_itlb_entry(int entry, int i, int endc)
635 {
636 	unsigned long tag, data;
637 	tag = db_get_itlb_tag(entry);
638 	data = db_get_itlb_data(entry);
639 	db_printf("%2d:%16.16lx %16.16lx%c", i, tag, data, endc);
640 }
641 
642 void
db_dump_dtlb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)643 db_dump_dtlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
644 {
645 	/* extern void print_dtlb(void); -- locore.s; no longer used here */
646 
647 	if (have_addr) {
648 		int i;
649 		int64_t* p = (int64_t*)addr;
650 		static int64_t buf[128];
651 		extern void dump_dtlb(int64_t *);
652 
653 	if (CHEETAHP) {
654 		db_printf("DTLB %ld\n", addr);
655 		switch(addr)
656 		{
657 		case 0:
658 			for (i = 0; i < 16; ++i)
659 				db_print_dtlb_entry(i, i, (i&1)?'\n':' ');
660 			break;
661 		case 2:
662 			for (i = 0; i < 512; ++i)
663 				db_print_dtlb_entry(i+16384, i, (i&1)?'\n':' ');
664 			break;
665 		}
666 	} else {
667 		dump_dtlb(buf);
668 		p = buf;
669 		for (i=0; i<64;) {
670 			db_printf("%2d:%16.16llx %16.16llx ", i++, p[0], p[1]);
671 			p += 2;
672 			db_printf("%2d:%16.16llx %16.16llx\n", i++, p[0], p[1]);
673 			p += 2;
674 		}
675 	}
676 	} else {
677 printf ("Usage: mach dtlb 0,2\n");
678 	}
679 }
680 
681 void
db_dump_itlb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)682 db_dump_itlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
683 {
684 	int i;
685 	if (!have_addr) {
686 		db_printf("Usage: mach itlb 0,1,2\n");
687 		return;
688 	}
689 	if (CHEETAHP) {
690 		db_printf("ITLB %ld\n", addr);
691 		switch(addr)
692 		{
693 		case 0:
694 			for (i = 0; i < 16; ++i)
695 				db_print_itlb_entry(i, i, (i&1)?'\n':' ');
696 			break;
697 		case 2:
698 			for (i = 0; i < 128; ++i)
699 				db_print_itlb_entry(i+16384, i, (i&1)?'\n':' ');
700 			break;
701 		}
702 	} else {
703 		for (i = 0; i < 63; ++i)
704 			db_print_itlb_entry(i, i, (i&1)?'\n':' ');
705 	}
706 }
707 
708 void
db_pload_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)709 db_pload_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
710 {
711 	static paddr_t oldaddr = -1;
712 	int asi = ASI_PHYS_CACHED;
713 
714 	if (!have_addr) {
715 		addr = oldaddr;
716 	}
717 	if (addr == -1) {
718 		db_printf("no address\n");
719 		return;
720 	}
721 	addr &= ~0x7; /* align */
722 	{
723 		register char c, *cp = modif;
724 		while ((c = *cp++) != 0)
725 			if (c == 'u')
726 				asi = ASI_AIUS;
727 	}
728 	while (count--) {
729 		if (db_print_position() == 0) {
730 			/* Always print the address. */
731 			db_printf("%16.16lx:\t", addr);
732 		}
733 		oldaddr=addr;
734 		db_printf("%8.8lx\n", (long)ldxa(addr, asi));
735 		addr += 8;
736 		if (db_print_position() != 0)
737 			db_end_line(0);
738 	}
739 }
740 
741 int64_t pseg_get(struct pmap *, vaddr_t);
742 
743 void
db_dump_pmap(struct pmap * pm)744 db_dump_pmap(struct pmap* pm)
745 {
746 	/* print all valid pages in the kernel pmap */
747 	long i, j, k, n;
748 	paddr_t *pdir, *ptbl;
749 	/* Almost the same as pmap_collect() */
750 
751 	n = 0;
752 	for (i=0; i<STSZ; i++) {
753 		if((pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED))) {
754 			db_printf("pdir %ld at %lx:\n", i, (long)pdir);
755 			for (k=0; k<PDSZ; k++) {
756 				if ((ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED))) {
757 					db_printf("\tptable %ld:%ld at %lx:\n", i, k, (long)ptbl);
758 					for (j=0; j<PTSZ; j++) {
759 						int64_t data0, data1;
760 						data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
761 						j++;
762 						data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
763 						if (data0 || data1) {
764 							db_printf("%llx: %llx\t",
765 								  (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|((j-1)<<PTSHIFT)),
766 								  (unsigned long long)(data0));
767 							db_printf("%llx: %llx\n",
768 								  (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|(j<<PTSHIFT)),
769 								  (unsigned long long)(data1));
770 						}
771 					}
772 				}
773 			}
774 		}
775 	}
776 }
777 
778 void
db_pmap_kernel(db_expr_t addr,int have_addr,db_expr_t count,char * modif)779 db_pmap_kernel(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
780 {
781 	extern struct pmap kernel_pmap_;
782 	int i, j, full = 0;
783 	u_int64_t data;
784 
785 	{
786 		register char c, *cp = modif;
787 		while ((c = *cp++) != 0)
788 			if (c == 'f')
789 				full = 1;
790 	}
791 	if (have_addr) {
792 		/* lookup an entry for this VA */
793 
794 		if ((data = pseg_get(&kernel_pmap_, (vaddr_t)addr))) {
795 			db_printf("pmap_kernel(%p)->pm_segs[%lx][%lx][%lx]=>%llx\n",
796 				  (void *)addr, (u_long)va_to_seg(addr),
797 				  (u_long)va_to_dir(addr), (u_long)va_to_pte(addr),
798 				  (unsigned long long)data);
799 		} else {
800 			db_printf("No mapping for %p\n", (void *)addr);
801 		}
802 		return;
803 	}
804 
805 	db_printf("pmap_kernel(%p) psegs %p phys %llx\n",
806 		  &kernel_pmap_, kernel_pmap_.pm_segs,
807 		  (unsigned long long)kernel_pmap_.pm_physaddr);
808 	if (full) {
809 		db_dump_pmap(&kernel_pmap_);
810 	} else {
811 		for (j=i=0; i<STSZ; i++) {
812 			long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED);
813 			if (seg)
814 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
815 		}
816 	}
817 }
818 
819 
820 void
db_pmap_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)821 db_pmap_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
822 {
823 	struct pmap* pm=NULL;
824 	int i, j=0, full = 0;
825 
826 	{
827 		register char c, *cp = modif;
828 		if (modif)
829 			while ((c = *cp++) != 0)
830 				if (c == 'f')
831 					full = 1;
832 	}
833 	if (curproc && curproc->p_vmspace)
834 		pm = curproc->p_vmspace->vm_map.pmap;
835 	if (have_addr) {
836 		pm = (struct pmap*)addr;
837 	}
838 
839 	db_printf("pmap %p: ctx %x refs %d physaddr %llx psegs %p\n",
840 		pm, pm->pm_ctx, pm->pm_refs,
841 		(unsigned long long)pm->pm_physaddr, pm->pm_segs);
842 
843 	if (full) {
844 		db_dump_pmap(pm);
845 	} else {
846 		for (i=0; i<STSZ; i++) {
847 			long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED);
848 			if (seg)
849 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
850 		}
851 	}
852 }
853 
854 
855 void
db_lock(db_expr_t addr,int have_addr,db_expr_t count,char * modif)856 db_lock(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
857 {
858 #if 0
859 	struct lock *l;
860 
861 	if (!have_addr) {
862 		db_printf("What lock address?\n");
863 		return;
864 	}
865 
866 	l = (struct lock *)addr;
867 	db_printf("flags=%x\n waitcount=%x sharecount=%x "
868 	    "exclusivecount=%x\n wmesg=%s recurselevel=%x\n",
869 	    l->lk_flags, l->lk_waitcount,
870 	    l->lk_sharecount, l->lk_exclusivecount, l->lk_wmesg,
871 	    l->lk_recurselevel);
872 #else
873 	db_printf("locks unsupported\n");
874 #endif
875 }
876 
877 void
db_dump_dtsb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)878 db_dump_dtsb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
879 {
880 	extern pte_t *tsb_dmmu;
881 	extern int tsbsize;
882 #define TSBENTS (512<<tsbsize)
883 	int i;
884 
885 	db_printf("TSB:\n");
886 	for (i=0; i<TSBENTS; i++) {
887 		db_printf("%4d:%4d:%08x %08x:%08x ", i,
888 			  (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
889 			  (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
890 			  (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
891 		i++;
892 		db_printf("%4d:%4d:%08x %08x:%08x\n", i,
893 			  (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
894 			  (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
895 			  (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
896 	}
897 }
898 
899 void db_page_cmd(db_expr_t, int, db_expr_t, char *);
900 void
db_page_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)901 db_page_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
902 {
903 
904 	if (!have_addr) {
905 		db_printf("Need paddr for page\n");
906 		return;
907 	}
908 
909 	db_printf("pa %llx pg %p\n", (unsigned long long)addr,
910 	    PHYS_TO_VM_PAGE(addr));
911 }
912 
913 
914 void
db_proc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)915 db_proc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
916 {
917 	struct proc *p;
918 
919 	p = curproc;
920 	if (have_addr)
921 		p = (struct proc*) addr;
922 	if (p == NULL) {
923 		db_printf("no current process\n");
924 		return;
925 	}
926 	db_printf("process %p:", p);
927 	db_printf("pid:%d vmspace:%p pmap:%p ctx:%x wchan:%p rpri:%d upri:%d\n",
928 	    p->p_p->ps_pid, p->p_vmspace, p->p_vmspace->vm_map.pmap,
929 	    p->p_vmspace->vm_map.pmap->pm_ctx,
930 	    p->p_wchan, p->p_runpri, p->p_usrpri);
931 	db_printf("maxsaddr:%p ssiz:%dpg or %llxB\n",
932 	    p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize,
933 	    (unsigned long long)ptoa(p->p_vmspace->vm_ssize));
934 	db_printf("profile timer: %lld sec %ld usec\n",
935 	    (long long)p->p_p->ps_timer[ITIMER_PROF].it_value.tv_sec,
936 	    p->p_p->ps_timer[ITIMER_PROF].it_value.tv_nsec / 1000);
937 	db_printf("pcb: %p tf: %p fpstate: %p\n", &p->p_addr->u_pcb,
938 	    p->p_md.md_tf, p->p_md.md_fpstate);
939 	return;
940 }
941 
942 void
db_ctx_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)943 db_ctx_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
944 {
945 	struct proc *p;
946 
947 	/* XXX LOCKING XXX */
948 	LIST_FOREACH(p, &allproc, p_list) {
949 		if (p->p_stat) {
950 			db_printf("process %p:", p);
951 			db_printf("pid:%d pmap:%p ctx:%x tf:%p fpstate %p "
952 			    "lastcall:%s\n",
953 			    p->p_p->ps_pid, p->p_vmspace->vm_map.pmap,
954 			    p->p_vmspace->vm_map.pmap->pm_ctx,
955 			    p->p_md.md_tf, p->p_md.md_fpstate,
956 			    (p->p_addr->u_pcb.lastcall)?
957 			    p->p_addr->u_pcb.lastcall : "Null");
958 		}
959 	}
960 	return;
961 }
962 
963 void
db_dump_pcb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)964 db_dump_pcb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
965 {
966 	struct pcb *pcb;
967 	int i;
968 
969 	pcb = curpcb;
970 	if (have_addr)
971 		pcb = (struct pcb*) addr;
972 
973 	db_printf("pcb@%p sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
974 		  pcb, (void *)(long)pcb->pcb_sp, (void *)(long)pcb->pcb_pc, pcb->pcb_cwp,
975 		  pcb->pcb_pil, pcb->pcb_nsaved, (void *)pcb->pcb_onfault,
976 		  (pcb->lastcall)?pcb->lastcall:"Null");
977 
978 	for (i=0; i<pcb->pcb_nsaved; i++) {
979 		db_printf("win %d: at %llx local, in\n", i,
980 			  (unsigned long long)pcb->pcb_rwsp[i]);
981 		db_printf("%16llx %16llx %16llx %16llx\n",
982 			  (unsigned long long)pcb->pcb_rw[i].rw_local[0],
983 			  (unsigned long long)pcb->pcb_rw[i].rw_local[1],
984 			  (unsigned long long)pcb->pcb_rw[i].rw_local[2],
985 			  (unsigned long long)pcb->pcb_rw[i].rw_local[3]);
986 		db_printf("%16llx %16llx %16llx %16llx\n",
987 			  (unsigned long long)pcb->pcb_rw[i].rw_local[4],
988 			  (unsigned long long)pcb->pcb_rw[i].rw_local[5],
989 			  (unsigned long long)pcb->pcb_rw[i].rw_local[6],
990 			  (unsigned long long)pcb->pcb_rw[i].rw_local[7]);
991 		db_printf("%16llx %16llx %16llx %16llx\n",
992 			  (unsigned long long)pcb->pcb_rw[i].rw_in[0],
993 			  (unsigned long long)pcb->pcb_rw[i].rw_in[1],
994 			  (unsigned long long)pcb->pcb_rw[i].rw_in[2],
995 			  (unsigned long long)pcb->pcb_rw[i].rw_in[3]);
996 		db_printf("%16llx %16llx %16llx %16llx\n",
997 			  (unsigned long long)pcb->pcb_rw[i].rw_in[4],
998 			  (unsigned long long)pcb->pcb_rw[i].rw_in[5],
999 			  (unsigned long long)pcb->pcb_rw[i].rw_in[6],
1000 			  (unsigned long long)pcb->pcb_rw[i].rw_in[7]);
1001 	}
1002 }
1003 
1004 
1005 void
db_setpcb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)1006 db_setpcb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1007 {
1008 	struct proc *p;
1009 
1010 	if (!have_addr) {
1011 		db_printf("What TID do you want to map in?\n");
1012 		return;
1013 	}
1014 
1015 	LIST_FOREACH(p, &allproc, p_list) {
1016 		if (p->p_stat && p->p_tid == addr) {
1017 			curproc = p;
1018 			curpcb = (struct pcb*)p->p_addr;
1019 			curcpu()->ci_cpcbpaddr = p->p_md.md_pcbpaddr;
1020 			if (p->p_vmspace->vm_map.pmap->pm_ctx) {
1021 				switchtoctx(p->p_vmspace->vm_map.pmap->pm_ctx);
1022 				return;
1023 			}
1024 			db_printf("TID %ld has a null context.\n", addr);
1025 			return;
1026 		}
1027 	}
1028 	db_printf("TID %ld not found.\n", addr);
1029 }
1030 
1031 
1032 /*
1033  * Use physical or virtual watchpoint registers -- ugh
1034  */
1035 void
db_watch(db_expr_t addr,int have_addr,db_expr_t count,char * modif)1036 db_watch(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1037 {
1038 	int phys = 0;
1039 
1040 #define WATCH_VR	(1L<<22)
1041 #define WATCH_VW	(1L<<21)
1042 #define WATCH_PR	(1L<<24)
1043 #define WATCH_PW	(1L<<23)
1044 #define WATCH_PM	(((u_int64_t)0xffffL)<<33)
1045 #define WATCH_VM	(((u_int64_t)0xffffL)<<25)
1046 
1047 	{
1048 		register char c, *cp = modif;
1049 		if (modif)
1050 			while ((c = *cp++) != 0)
1051 				if (c == 'p')
1052 					phys = 1;
1053 	}
1054 	if (have_addr) {
1055 		/* turn on the watchpoint */
1056 		int64_t tmp = ldxa(0, ASI_MCCR);
1057 
1058 		if (phys) {
1059 			tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
1060 			stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
1061 		} else {
1062 			tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
1063 			stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
1064 		}
1065 		stxa(0, ASI_MCCR, tmp);
1066 	} else {
1067 		/* turn off the watchpoint */
1068 		int64_t tmp = ldxa(0, ASI_MCCR);
1069 		if (phys) tmp &= ~(WATCH_PM);
1070 		else tmp &= ~(WATCH_VM);
1071 		stxa(0, ASI_MCCR, tmp);
1072 	}
1073 }
1074 
1075 /*
1076  * Provide a way to trigger an External Initiated Reset (XIR).  Some
1077  * systems can target individual processors, others can only target
1078  * all processors at once.
1079  */
1080 
1081 struct xirhand {
1082 	void (*xh_fun)(void *, int);
1083 	void *xh_arg;
1084 	SIMPLEQ_ENTRY(xirhand) xh_list;
1085 };
1086 
1087 SIMPLEQ_HEAD(, xirhand) db_xh = SIMPLEQ_HEAD_INITIALIZER(db_xh);
1088 
1089 void
db_xir(db_expr_t addr,int have_addr,db_expr_t count,char * modif)1090 db_xir(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1091 {
1092 	struct xirhand *xh;
1093 
1094 	if (!have_addr)
1095 		addr = -1;
1096 
1097 	SIMPLEQ_FOREACH(xh, &db_xh, xh_list) {
1098 		xh->xh_fun(xh->xh_arg, addr);
1099 	}
1100 }
1101 
1102 void
db_register_xir(void (* fun)(void *,int),void * arg)1103 db_register_xir(void (*fun)(void *, int), void *arg)
1104 {
1105 	struct xirhand *xh;
1106 
1107 	xh = malloc(sizeof(*xh), M_DEVBUF, M_NOWAIT);
1108 	if (xh == NULL)
1109 		panic("db_register_xir");
1110 	xh->xh_fun = fun;
1111 	xh->xh_arg = arg;
1112 	SIMPLEQ_INSERT_TAIL(&db_xh, xh, xh_list);
1113 }
1114 
1115 
1116 #if NESP_SBUS
1117 extern void db_esp(db_expr_t, int, db_expr_t, char *);
1118 #endif
1119 
1120 const struct db_command db_machine_command_table[] = {
1121 	{ "ctx",	db_ctx_cmd,	0,	0 },
1122 	{ "dtlb",	db_dump_dtlb,	0,	0 },
1123 	{ "dtsb",	db_dump_dtsb,	0,	0 },
1124 #if NESP_SBUS
1125 	{ "esp",	db_esp,		0,	0 },
1126 #endif
1127 	{ "fpstate",	db_dump_fpstate,0,	0 },
1128 	{ "itlb",	db_dump_itlb,	0,	0 },
1129 	{ "kmap",	db_pmap_kernel,	0,	0 },
1130 	{ "lock",	db_lock,	0,	0 },
1131 	{ "pcb",	db_dump_pcb,	0,	0 },
1132 	{ "pctx",	db_setpcb,	0,	0 },
1133 	{ "page",	db_page_cmd,	0,	0 },
1134 	{ "phys",	db_pload_cmd,	0,	0 },
1135 	{ "pmap",	db_pmap_cmd,	0,	0 },
1136 	{ "proc",	db_proc_cmd,	0,	0 },
1137 	{ "prom",	db_prom_cmd,	0,	0 },
1138 	{ "pv",		db_dump_pv,	0,	0 },
1139 	{ "stack",	db_dump_stack,	0,	0 },
1140 	{ "tf",		db_dump_trap,	0,	0 },
1141 	{ "ts",		db_dump_ts,	0,	0 },
1142 	{ "watch",	db_watch,	0,	0 },
1143 	{ "window",	db_dump_window,	0,	0 },
1144 	{ "xir",	db_xir,		0,	0 },
1145 #ifdef MULTIPROCESSOR
1146 	{ "cpuinfo",	db_cpuinfo_cmd,		0,	0 },
1147 	{ "startcpu",	db_startproc_cmd,	0,	0 },
1148 	{ "stopcpu",	db_stopproc_cmd,	0,	0 },
1149 	{ "ddbcpu",	db_ddbproc_cmd,		0,	0 },
1150 #endif
1151 	{ NULL, }
1152 };
1153 
1154 /*
1155  * support for SOFTWARE_SSTEP:
1156  * return the next pc if the given branch is taken.
1157  *
1158  * note: in the case of conditional branches with annul,
1159  * this actually returns the next pc in the "not taken" path,
1160  * but in that case next_instr_address() will return the
1161  * next pc in the "taken" path.  so even tho the breakpoints
1162  * are backwards, everything will still work, and the logic is
1163  * much simpler this way.
1164  */
1165 vaddr_t
db_branch_taken(int inst,vaddr_t pc,db_regs_t * regs)1166 db_branch_taken(int inst, vaddr_t pc, db_regs_t *regs)
1167 {
1168     union instr insn;
1169     vaddr_t npc = ddb_regs.ddb_tf.tf_npc;
1170 
1171     insn.i_int = inst;
1172 
1173     /* the fancy union just gets in the way of this: */
1174     switch(inst & 0xffc00000) {
1175     case 0x30400000:	/* branch always, annul, with prediction */
1176 	return pc + ((inst<<(32-19))>>((32-19)-2));
1177     case 0x30800000:	/* branch always, annul */
1178 	return pc + ((inst<<(32-22))>>((32-22)-2));
1179     }
1180 
1181     /*
1182      * if this is not an annulled conditional branch, the next pc is "npc".
1183      */
1184 
1185     if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1)
1186 	return npc;
1187 
1188     switch (insn.i_op2.i_op2) {
1189       case IOP2_Bicc:
1190       case IOP2_FBfcc:
1191       case IOP2_BPcc:
1192       case IOP2_FBPfcc:
1193       case IOP2_CBccc:
1194 	/* branch on some condition-code */
1195 	switch (insn.i_branch.i_cond)
1196 	{
1197 	  case Icc_A: /* always */
1198 	    return pc + ((inst << 10) >> 8);
1199 
1200 	  default: /* all other conditions */
1201 	    return npc + 4;
1202 	}
1203 
1204       case IOP2_BPr:
1205 	/* branch on register, always conditional */
1206 	return npc + 4;
1207 
1208       default:
1209 	/* not a branch */
1210 	panic("branch_taken() on non-branch");
1211     }
1212 }
1213 
1214 int
db_inst_branch(int inst)1215 db_inst_branch(int inst)
1216 {
1217     union instr insn;
1218 
1219     insn.i_int = inst;
1220 
1221     /* the fancy union just gets in the way of this: */
1222     switch(inst & 0xffc00000) {
1223     case 0x30400000:	/* branch always, annul, with prediction */
1224 	return 1;
1225     case 0x30800000:	/* branch always, annul */
1226 	return 1;
1227     }
1228 
1229     if (insn.i_any.i_op != IOP_OP2)
1230 	return 0;
1231 
1232     switch (insn.i_op2.i_op2) {
1233       case IOP2_BPcc:
1234       case IOP2_Bicc:
1235       case IOP2_BPr:
1236       case IOP2_FBPfcc:
1237       case IOP2_FBfcc:
1238       case IOP2_CBccc:
1239 	return 1;
1240 
1241       default:
1242 	return 0;
1243     }
1244 }
1245 
1246 
1247 int
db_inst_call(int inst)1248 db_inst_call(int inst)
1249 {
1250     union instr insn;
1251 
1252     insn.i_int = inst;
1253 
1254     switch (insn.i_any.i_op) {
1255       case IOP_CALL:
1256 	return 1;
1257 
1258       case IOP_reg:
1259 	return (insn.i_op3.i_op3 == IOP3_JMPL) && !db_inst_return(inst);
1260 
1261       default:
1262 	return 0;
1263     }
1264 }
1265 
1266 
1267 int
db_inst_unconditional_flow_transfer(int inst)1268 db_inst_unconditional_flow_transfer(int inst)
1269 {
1270     union instr insn;
1271 
1272     insn.i_int = inst;
1273 
1274     if (db_inst_call(inst))
1275 	return 1;
1276 
1277     if (insn.i_any.i_op != IOP_OP2)
1278 	return 0;
1279 
1280     switch (insn.i_op2.i_op2)
1281     {
1282       case IOP2_BPcc:
1283       case IOP2_Bicc:
1284       case IOP2_FBPfcc:
1285       case IOP2_FBfcc:
1286       case IOP2_CBccc:
1287 	return insn.i_branch.i_cond == Icc_A;
1288 
1289       default:
1290 	return 0;
1291     }
1292 }
1293 
1294 
1295 int
db_inst_return(int inst)1296 db_inst_return(int inst)
1297 {
1298     return (inst == I_JMPLri(I_G0, I_O7, 8) ||		/* ret */
1299 	    inst == I_JMPLri(I_G0, I_I7, 8));		/* retl */
1300 }
1301 
1302 int
db_inst_trap_return(int inst)1303 db_inst_trap_return(int inst)
1304 {
1305     union instr insn;
1306 
1307     insn.i_int = inst;
1308 
1309     return (insn.i_any.i_op == IOP_reg &&
1310 	    insn.i_op3.i_op3 == IOP3_RETT);
1311 }
1312 
1313 void
db_machine_init(void)1314 db_machine_init(void)
1315 {
1316 }
1317