xref: /openbsd-src/sys/arch/sparc64/sparc64/db_interface.c (revision da5607f65bdedd8aa46e3abfd846bd3bccd1e805)
1*da5607f6Sjsg /*	$OpenBSD: db_interface.c,v 1.66 2024/06/26 01:40:49 jsg Exp $	*/
2d5d6a0bbSart /*	$NetBSD: db_interface.c,v 1.61 2001/07/31 06:55:47 eeh Exp $ */
3d5d6a0bbSart 
4d5d6a0bbSart /*
5d5d6a0bbSart  * Mach Operating System
6d5d6a0bbSart  * Copyright (c) 1991,1990 Carnegie Mellon University
7d5d6a0bbSart  * All Rights Reserved.
8d5d6a0bbSart  *
9d5d6a0bbSart  * Permission to use, copy, modify and distribute this software and its
10d5d6a0bbSart  * documentation is hereby granted, provided that both the copyright
11d5d6a0bbSart  * notice and this permission notice appear in all copies of the
12d5d6a0bbSart  * software, derivative works or modified versions, and any portions
13d5d6a0bbSart  * thereof, and that both notices appear in supporting documentation.
14d5d6a0bbSart  *
15d5d6a0bbSart  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16d5d6a0bbSart  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17d5d6a0bbSart  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18d5d6a0bbSart  *
19d5d6a0bbSart  * Carnegie Mellon requests users of this software to return to
20d5d6a0bbSart  *
21d5d6a0bbSart  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22d5d6a0bbSart  *  School of Computer Science
23d5d6a0bbSart  *  Carnegie Mellon University
24d5d6a0bbSart  *  Pittsburgh PA 15213-3890
25d5d6a0bbSart  *
26d5d6a0bbSart  * any improvements or extensions that they make and grant Carnegie the
27d5d6a0bbSart  * rights to redistribute these changes.
28d5d6a0bbSart  *
29d5d6a0bbSart  *	From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
30d5d6a0bbSart  */
31d5d6a0bbSart 
32d5d6a0bbSart #include <sys/param.h>
33d5d6a0bbSart #include <sys/proc.h>
34d5d6a0bbSart #include <sys/user.h>
35d5d6a0bbSart #include <sys/reboot.h>
36d5d6a0bbSart #include <sys/systm.h>
3709671eefSkettenis #include <sys/malloc.h>
389ced64eaSvisa #include <sys/mutex.h>
39d5d6a0bbSart 
40d5d6a0bbSart #include <dev/cons.h>
41d5d6a0bbSart 
42d5d6a0bbSart #include <machine/db_machdep.h>
43d5d6a0bbSart #include <ddb/db_command.h>
44d5d6a0bbSart #include <ddb/db_sym.h>
45d5d6a0bbSart #include <ddb/db_variables.h>
46d5d6a0bbSart #include <ddb/db_extern.h>
47d5d6a0bbSart #include <ddb/db_access.h>
48d5d6a0bbSart #include <ddb/db_output.h>
49d5d6a0bbSart #include <ddb/db_interface.h>
50b0ad0500Skettenis #include <ddb/db_run.h>
51d5d6a0bbSart 
52d5d6a0bbSart #include <machine/instr.h>
53d5d6a0bbSart #include <machine/cpu.h>
54d5d6a0bbSart #include <machine/openfirm.h>
55d5d6a0bbSart #include <machine/ctlreg.h>
56f28d1820Smiod #include <machine/pte.h>
57d5d6a0bbSart 
58d5d6a0bbSart #ifdef notyet
59d5d6a0bbSart #include "fb.h"
60d5d6a0bbSart #include "esp_sbus.h"
61d5d6a0bbSart #endif
62d5d6a0bbSart 
638e7461c8Srobert #include "tda.h"
648e7461c8Srobert 
65b0ad0500Skettenis #ifdef MULTIPROCESSOR
666c78d705Svisa struct db_mutex ddb_mp_mutex = DB_MUTEX_INITIALIZER;
67b0ad0500Skettenis volatile int ddb_state = DDB_STATE_NOT_RUNNING;
68b0ad0500Skettenis volatile cpuid_t ddb_active_cpu;
69fed26a10Smpi int		 db_switch_cpu;
70b0ad0500Skettenis struct cpu_info *db_switch_to_cpu;
71b0ad0500Skettenis #endif
72b0ad0500Skettenis 
7372222458Sjason db_regs_t	ddb_regs;	/* register state */
7472222458Sjason 
75c4071fd1Smillert extern void OF_enter(void);
76d5d6a0bbSart 
771690bee7Smiod static long nil;
78d5d6a0bbSart 
79d5d6a0bbSart static int
db__char_value(struct db_variable * var,db_expr_t * expr,int mode)80d5d6a0bbSart db__char_value(struct db_variable *var, db_expr_t *expr, int mode)
81d5d6a0bbSart {
82d5d6a0bbSart 
83d5d6a0bbSart 	switch (mode) {
84d5d6a0bbSart 	case DB_VAR_SET:
85d5d6a0bbSart 		*var->valuep = *(char *)expr;
86d5d6a0bbSart 		break;
87d5d6a0bbSart 	case DB_VAR_GET:
88d5d6a0bbSart 		*expr = *(char *)var->valuep;
89d5d6a0bbSart 		break;
90d5d6a0bbSart #ifdef DIAGNOSTIC
91d5d6a0bbSart 	default:
92d5d6a0bbSart 		printf("db__char_value: mode %d\n", mode);
93d5d6a0bbSart 		break;
94d5d6a0bbSart #endif
95d5d6a0bbSart 	}
96d5d6a0bbSart 
97d5d6a0bbSart 	return 0;
98d5d6a0bbSart }
99d5d6a0bbSart 
100d5d6a0bbSart #ifdef notdef_yet
101d5d6a0bbSart static int
db__short_value(struct db_variable * var,db_expr_t * expr,int mode)102d5d6a0bbSart db__short_value(struct db_variable *var, db_expr_t *expr, int mode)
103d5d6a0bbSart {
104d5d6a0bbSart 
105d5d6a0bbSart 	switch (mode) {
106d5d6a0bbSart 	case DB_VAR_SET:
107d5d6a0bbSart 		*var->valuep = *(short *)expr;
108d5d6a0bbSart 		break;
109d5d6a0bbSart 	case DB_VAR_GET:
110d5d6a0bbSart 		*expr = *(short *)var->valuep;
111d5d6a0bbSart 		break;
112d5d6a0bbSart #ifdef DIAGNOSTIC
113d5d6a0bbSart 	default:
114d5d6a0bbSart 		printf("db__short_value: mode %d\n", mode);
115d5d6a0bbSart 		break;
116d5d6a0bbSart #endif
117d5d6a0bbSart 	}
118d5d6a0bbSart 
119d5d6a0bbSart 	return 0;
120d5d6a0bbSart }
121d5d6a0bbSart #endif
122d5d6a0bbSart 
123d5d6a0bbSart struct db_variable db_regs[] = {
124d5d6a0bbSart 	{ "tstate", (long *)&DDB_TF->tf_tstate, FCN_NULL, },
125d5d6a0bbSart 	{ "pc", (long *)&DDB_TF->tf_pc, FCN_NULL, },
126d5d6a0bbSart 	{ "npc", (long *)&DDB_TF->tf_npc, FCN_NULL, },
127d5d6a0bbSart 	{ "ipl", (long *)&DDB_TF->tf_oldpil, db__char_value, },
128ddfdb362Smiod 	{ "y", (long *)&DDB_TF->tf_y, db_var_rw_int, },
129d5d6a0bbSart 	{ "g0", (long *)&nil, FCN_NULL, },
130d5d6a0bbSart 	{ "g1", (long *)&DDB_TF->tf_global[1], FCN_NULL, },
131d5d6a0bbSart 	{ "g2", (long *)&DDB_TF->tf_global[2], FCN_NULL, },
132d5d6a0bbSart 	{ "g3", (long *)&DDB_TF->tf_global[3], FCN_NULL, },
133d5d6a0bbSart 	{ "g4", (long *)&DDB_TF->tf_global[4], FCN_NULL, },
134d5d6a0bbSart 	{ "g5", (long *)&DDB_TF->tf_global[5], FCN_NULL, },
135d5d6a0bbSart 	{ "g6", (long *)&DDB_TF->tf_global[6], FCN_NULL, },
136d5d6a0bbSart 	{ "g7", (long *)&DDB_TF->tf_global[7], FCN_NULL, },
137d5d6a0bbSart 	{ "o0", (long *)&DDB_TF->tf_out[0], FCN_NULL, },
138d5d6a0bbSart 	{ "o1", (long *)&DDB_TF->tf_out[1], FCN_NULL, },
139d5d6a0bbSart 	{ "o2", (long *)&DDB_TF->tf_out[2], FCN_NULL, },
140d5d6a0bbSart 	{ "o3", (long *)&DDB_TF->tf_out[3], FCN_NULL, },
141d5d6a0bbSart 	{ "o4", (long *)&DDB_TF->tf_out[4], FCN_NULL, },
142d5d6a0bbSart 	{ "o5", (long *)&DDB_TF->tf_out[5], FCN_NULL, },
143d5d6a0bbSart 	{ "o6", (long *)&DDB_TF->tf_out[6], FCN_NULL, },
144d5d6a0bbSart 	{ "o7", (long *)&DDB_TF->tf_out[7], FCN_NULL, },
145d5d6a0bbSart 	{ "l0", (long *)&DDB_TF->tf_local[0], FCN_NULL, },
146d5d6a0bbSart 	{ "l1", (long *)&DDB_TF->tf_local[1], FCN_NULL, },
147d5d6a0bbSart 	{ "l2", (long *)&DDB_TF->tf_local[2], FCN_NULL, },
148d5d6a0bbSart 	{ "l3", (long *)&DDB_TF->tf_local[3], FCN_NULL, },
149d5d6a0bbSart 	{ "l4", (long *)&DDB_TF->tf_local[4], FCN_NULL, },
150d5d6a0bbSart 	{ "l5", (long *)&DDB_TF->tf_local[5], FCN_NULL, },
151d5d6a0bbSart 	{ "l6", (long *)&DDB_TF->tf_local[6], FCN_NULL, },
152d5d6a0bbSart 	{ "l7", (long *)&DDB_TF->tf_local[7], FCN_NULL, },
153d5d6a0bbSart 	{ "i0", (long *)&DDB_FR->fr_arg[0], FCN_NULL, },
154d5d6a0bbSart 	{ "i1", (long *)&DDB_FR->fr_arg[1], FCN_NULL, },
155d5d6a0bbSart 	{ "i2", (long *)&DDB_FR->fr_arg[2], FCN_NULL, },
156d5d6a0bbSart 	{ "i3", (long *)&DDB_FR->fr_arg[3], FCN_NULL, },
157d5d6a0bbSart 	{ "i4", (long *)&DDB_FR->fr_arg[4], FCN_NULL, },
158d5d6a0bbSart 	{ "i5", (long *)&DDB_FR->fr_arg[5], FCN_NULL, },
159d5d6a0bbSart 	{ "i6", (long *)&DDB_FR->fr_arg[6], FCN_NULL, },
160d5d6a0bbSart 	{ "i7", (long *)&DDB_FR->fr_arg[7], FCN_NULL, },
161d5d6a0bbSart 	{ "f0", (long *)&DDB_FP->fs_regs[0], FCN_NULL, },
162d5d6a0bbSart 	{ "f2", (long *)&DDB_FP->fs_regs[2], FCN_NULL, },
163d5d6a0bbSart 	{ "f4", (long *)&DDB_FP->fs_regs[4], FCN_NULL, },
164d5d6a0bbSart 	{ "f6", (long *)&DDB_FP->fs_regs[6], FCN_NULL, },
165d5d6a0bbSart 	{ "f8", (long *)&DDB_FP->fs_regs[8], FCN_NULL, },
166d5d6a0bbSart 	{ "f10", (long *)&DDB_FP->fs_regs[10], FCN_NULL, },
167d5d6a0bbSart 	{ "f12", (long *)&DDB_FP->fs_regs[12], FCN_NULL, },
168d5d6a0bbSart 	{ "f14", (long *)&DDB_FP->fs_regs[14], FCN_NULL, },
169d5d6a0bbSart 	{ "f16", (long *)&DDB_FP->fs_regs[16], FCN_NULL, },
170d5d6a0bbSart 	{ "f18", (long *)&DDB_FP->fs_regs[18], FCN_NULL, },
171d5d6a0bbSart 	{ "f20", (long *)&DDB_FP->fs_regs[20], FCN_NULL, },
172d5d6a0bbSart 	{ "f22", (long *)&DDB_FP->fs_regs[22], FCN_NULL, },
173d5d6a0bbSart 	{ "f24", (long *)&DDB_FP->fs_regs[24], FCN_NULL, },
174d5d6a0bbSart 	{ "f26", (long *)&DDB_FP->fs_regs[26], FCN_NULL, },
175d5d6a0bbSart 	{ "f28", (long *)&DDB_FP->fs_regs[28], FCN_NULL, },
176d5d6a0bbSart 	{ "f30", (long *)&DDB_FP->fs_regs[30], FCN_NULL, },
177d5d6a0bbSart 	{ "f32", (long *)&DDB_FP->fs_regs[32], FCN_NULL, },
178d5d6a0bbSart 	{ "f34", (long *)&DDB_FP->fs_regs[34], FCN_NULL, },
179d5d6a0bbSart 	{ "f36", (long *)&DDB_FP->fs_regs[36], FCN_NULL, },
180d5d6a0bbSart 	{ "f38", (long *)&DDB_FP->fs_regs[38], FCN_NULL, },
181d5d6a0bbSart 	{ "f40", (long *)&DDB_FP->fs_regs[40], FCN_NULL, },
182d5d6a0bbSart 	{ "f42", (long *)&DDB_FP->fs_regs[42], FCN_NULL, },
183d5d6a0bbSart 	{ "f44", (long *)&DDB_FP->fs_regs[44], FCN_NULL, },
184d5d6a0bbSart 	{ "f46", (long *)&DDB_FP->fs_regs[46], FCN_NULL, },
185d5d6a0bbSart 	{ "f48", (long *)&DDB_FP->fs_regs[48], FCN_NULL, },
186d5d6a0bbSart 	{ "f50", (long *)&DDB_FP->fs_regs[50], FCN_NULL, },
187d5d6a0bbSart 	{ "f52", (long *)&DDB_FP->fs_regs[52], FCN_NULL, },
188d5d6a0bbSart 	{ "f54", (long *)&DDB_FP->fs_regs[54], FCN_NULL, },
189d5d6a0bbSart 	{ "f56", (long *)&DDB_FP->fs_regs[56], FCN_NULL, },
190d5d6a0bbSart 	{ "f58", (long *)&DDB_FP->fs_regs[58], FCN_NULL, },
191d5d6a0bbSart 	{ "f60", (long *)&DDB_FP->fs_regs[60], FCN_NULL, },
192d5d6a0bbSart 	{ "f62", (long *)&DDB_FP->fs_regs[62], FCN_NULL, },
193d5d6a0bbSart 	{ "fsr", (long *)&DDB_FP->fs_fsr, FCN_NULL, },
194d5d6a0bbSart 	{ "gsr", (long *)&DDB_FP->fs_gsr, FCN_NULL, },
195d5d6a0bbSart 
196d5d6a0bbSart };
19785882e82Sjasper struct db_variable *db_eregs = db_regs + nitems(db_regs);
198d5d6a0bbSart 
199d5d6a0bbSart extern label_t	*db_recover;
200d5d6a0bbSart 
201d5d6a0bbSart extern char *trap_type[];
202d5d6a0bbSart 
2031c00236eSmiod void kdb_kbd_trap(struct trapframe *);
204c4071fd1Smillert void db_prom_cmd(db_expr_t, int, db_expr_t, char *);
205c4071fd1Smillert void db_proc_cmd(db_expr_t, int, db_expr_t, char *);
206c4071fd1Smillert void db_ctx_cmd(db_expr_t, int, db_expr_t, char *);
207c4071fd1Smillert void db_dump_window(db_expr_t, int, db_expr_t, char *);
208c4071fd1Smillert void db_dump_stack(db_expr_t, int, db_expr_t, char *);
209c4071fd1Smillert void db_dump_trap(db_expr_t, int, db_expr_t, char *);
210c4071fd1Smillert void db_dump_fpstate(db_expr_t, int, db_expr_t, char *);
211c4071fd1Smillert void db_dump_ts(db_expr_t, int, db_expr_t, char *);
212c4071fd1Smillert void db_dump_pcb(db_expr_t, int, db_expr_t, char *);
213c4071fd1Smillert void db_dump_pv(db_expr_t, int, db_expr_t, char *);
214c4071fd1Smillert void db_setpcb(db_expr_t, int, db_expr_t, char *);
215c4071fd1Smillert void db_dump_dtlb(db_expr_t, int, db_expr_t, char *);
2166e1e03d7Smdw void db_dump_itlb(db_expr_t, int, db_expr_t, char *);
217c4071fd1Smillert void db_dump_dtsb(db_expr_t, int, db_expr_t, char *);
218c4071fd1Smillert void db_pmap_kernel(db_expr_t, int, db_expr_t, char *);
219c4071fd1Smillert void db_pload_cmd(db_expr_t, int, db_expr_t, char *);
220c4071fd1Smillert void db_pmap_cmd(db_expr_t, int, db_expr_t, char *);
221c4071fd1Smillert void db_lock(db_expr_t, int, db_expr_t, char *);
222c4071fd1Smillert void db_watch(db_expr_t, int, db_expr_t, char *);
22309671eefSkettenis void db_xir(db_expr_t, int, db_expr_t, char *);
224d5d6a0bbSart 
225c4071fd1Smillert static void db_dump_pmap(struct pmap*);
226d5d6a0bbSart 
227b0ad0500Skettenis #ifdef MULTIPROCESSOR
228b0ad0500Skettenis void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
229b0ad0500Skettenis void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
230b0ad0500Skettenis void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
231b0ad0500Skettenis void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
232b0ad0500Skettenis #endif
233d5d6a0bbSart 
234d5d6a0bbSart /*
235d5d6a0bbSart  * Received keyboard interrupt sequence.
236d5d6a0bbSart  */
237d5d6a0bbSart void
kdb_kbd_trap(struct trapframe * tf)2381c00236eSmiod kdb_kbd_trap(struct trapframe *tf)
239d5d6a0bbSart {
240d5d6a0bbSart 	if (db_active == 0 /* && (boothowto & RB_KDB) */) {
241d5d6a0bbSart 		printf("\n\nkernel: keyboard interrupt tf=%p\n", tf);
242a1a7d5d9Smpi 		db_ktrap(-1, tf);
243d5d6a0bbSart 	}
244d5d6a0bbSart }
245d5d6a0bbSart 
246d5d6a0bbSart /*
247a1a7d5d9Smpi  *  db_ktrap - field a TRACE or BPT trap
248d5d6a0bbSart  */
249d5d6a0bbSart int
db_ktrap(int type,register struct trapframe * tf)2501c00236eSmiod db_ktrap(int type, register struct trapframe *tf)
251d5d6a0bbSart {
252d5d6a0bbSart 	int s, tl;
253d5d6a0bbSart 	struct trapstate *ts = &ddb_regs.ddb_ts[0];
254d5d6a0bbSart 	extern int savetstate(struct trapstate *ts);
255d5d6a0bbSart 	extern void restoretstate(int tl, struct trapstate *ts);
25670d3ea64Smiod 
2578e7461c8Srobert #if NTDA > 0
2588e7461c8Srobert 	tda_full_blast();
2598e7461c8Srobert #endif
2608e7461c8Srobert 
261d5d6a0bbSart 	fb_unblank();
26270d3ea64Smiod 
263d5d6a0bbSart 	switch (type) {
264d5d6a0bbSart 	case T_BREAKPOINT:	/* breakpoint */
265d5d6a0bbSart 	case -1:		/* keyboard interrupt */
266d5d6a0bbSart 		break;
267d5d6a0bbSart 	default:
268d5d6a0bbSart 		printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
269d5d6a0bbSart 		if (db_recover != 0) {
270d5d6a0bbSart 			OF_enter();
271d5d6a0bbSart 			db_error("Faulted in DDB; continuing...\n");
272d5d6a0bbSart 			OF_enter();
273d5d6a0bbSart 			/*NOTREACHED*/
274d5d6a0bbSart 		}
275d5d6a0bbSart 		db_recover = (label_t *)1;
276d5d6a0bbSart 	}
277d5d6a0bbSart 
278b0ad0500Skettenis #ifdef MULTIPROCESSOR
2796c78d705Svisa 	db_mtx_enter(&ddb_mp_mutex);
280b0ad0500Skettenis 	if (ddb_state == DDB_STATE_EXITING)
281b0ad0500Skettenis 		ddb_state = DDB_STATE_NOT_RUNNING;
2826c78d705Svisa 	db_mtx_leave(&ddb_mp_mutex);
283b0ad0500Skettenis 	while (db_enter_ddb()) {
284b0ad0500Skettenis #endif
285b0ad0500Skettenis 
286d5d6a0bbSart 	/* Should switch to kdb`s own stack here. */
287d5d6a0bbSart 	write_all_windows();
288d5d6a0bbSart 
289d5d6a0bbSart 	ddb_regs.ddb_tf = *tf;
290d5d6a0bbSart 	if (fpproc) {
291d5d6a0bbSart 		savefpstate(fpproc->p_md.md_fpstate);
292d5d6a0bbSart 		ddb_regs.ddb_fpstate = *fpproc->p_md.md_fpstate;
293d5d6a0bbSart 		loadfpstate(fpproc->p_md.md_fpstate);
294d5d6a0bbSart 	}
295d5d6a0bbSart 
296d5d6a0bbSart 	s = splhigh();
297d5d6a0bbSart 	db_active++;
298fed26a10Smpi 	cnpollc(1);
299d5d6a0bbSart 	/* Need to do spl stuff till cnpollc works */
300d5d6a0bbSart 	tl = ddb_regs.ddb_tl = savetstate(ts);
301d5d6a0bbSart 	db_dump_ts(0, 0, 0, 0);
302d5d6a0bbSart 	db_trap(type, 0/*code*/);
303d5d6a0bbSart 	restoretstate(tl,ts);
304fed26a10Smpi 	cnpollc(0);
305d5d6a0bbSart 	db_active--;
306d5d6a0bbSart 	splx(s);
307d5d6a0bbSart 
308d5d6a0bbSart 	if (fpproc) {
309d5d6a0bbSart 		*fpproc->p_md.md_fpstate = ddb_regs.ddb_fpstate;
310d5d6a0bbSart 		loadfpstate(fpproc->p_md.md_fpstate);
311d5d6a0bbSart 	}
312d5d6a0bbSart #if 0
313d5d6a0bbSart 	/* We will not alter the machine's running state until we get everything else working */
314d5d6a0bbSart 	*(struct frame *)tf->tf_out[6] = ddb_regs.ddb_fr;
315d5d6a0bbSart #endif
316d5d6a0bbSart 	*tf = ddb_regs.ddb_tf;
317d5d6a0bbSart 
318b0ad0500Skettenis #ifdef MULTIPROCESSOR
319b0ad0500Skettenis 		if (!db_switch_cpu)
320b0ad0500Skettenis 			ddb_state = DDB_STATE_EXITING;
321b0ad0500Skettenis 	}
322b0ad0500Skettenis #endif
323b0ad0500Skettenis 
324d5d6a0bbSart 	return (1);
325d5d6a0bbSart }
326d5d6a0bbSart 
327b0ad0500Skettenis #ifdef MULTIPROCESSOR
328b0ad0500Skettenis 
329b0ad0500Skettenis void ipi_db(void);
330b0ad0500Skettenis 
331b0ad0500Skettenis void
db_cpuinfo_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)332b0ad0500Skettenis db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
333b0ad0500Skettenis {
334b0ad0500Skettenis 	struct cpu_info *ci;
335b0ad0500Skettenis 
336b0ad0500Skettenis 	for (ci = cpus; ci != NULL; ci = ci->ci_next) {
337b0ad0500Skettenis 		db_printf("%c%4d: ", (ci == curcpu()) ? '*' : ' ',
338ba177d4eSmpi 		    ci->ci_cpuid);
339b0ad0500Skettenis 		switch(ci->ci_ddb_paused) {
340b0ad0500Skettenis 		case CI_DDB_RUNNING:
341b0ad0500Skettenis 			db_printf("running\n");
342b0ad0500Skettenis 			break;
343b0ad0500Skettenis 		case CI_DDB_SHOULDSTOP:
344b0ad0500Skettenis 			db_printf("stopping\n");
345b0ad0500Skettenis 			break;
346b0ad0500Skettenis 		case CI_DDB_STOPPED:
347b0ad0500Skettenis 			db_printf("stopped\n");
348b0ad0500Skettenis 			break;
349b0ad0500Skettenis 		case CI_DDB_ENTERDDB:
350b0ad0500Skettenis 			db_printf("entering ddb\n");
351b0ad0500Skettenis 			break;
352b0ad0500Skettenis 		case CI_DDB_INDDB:
353b0ad0500Skettenis 			db_printf("ddb\n");
354b0ad0500Skettenis 			break;
355b0ad0500Skettenis 		default:
356b0ad0500Skettenis 			db_printf("? (%d)\n",
357b0ad0500Skettenis 			    ci->ci_ddb_paused);
358b0ad0500Skettenis 			break;
359b0ad0500Skettenis 		}
360b0ad0500Skettenis 	}
361b0ad0500Skettenis }
362b0ad0500Skettenis 
363b0ad0500Skettenis void
db_startproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)364b0ad0500Skettenis db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
365b0ad0500Skettenis {
366b0ad0500Skettenis 	struct cpu_info *ci;
367b0ad0500Skettenis 
368b0ad0500Skettenis 	if (have_addr) {
369b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
370ba177d4eSmpi 			if (addr == ci->ci_cpuid) {
371b0ad0500Skettenis 				db_startcpu(ci);
372b0ad0500Skettenis 				break;
373b0ad0500Skettenis 			}
374b0ad0500Skettenis 		}
375b0ad0500Skettenis 		if (ci == NULL)
376b0ad0500Skettenis 			db_printf("Invalid cpu %d\n", (int)addr);
377b0ad0500Skettenis 	} else {
378b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
379b0ad0500Skettenis 			if (ci != curcpu())
380b0ad0500Skettenis 				db_startcpu(ci);
381b0ad0500Skettenis 		}
382b0ad0500Skettenis 	}
383b0ad0500Skettenis }
384b0ad0500Skettenis 
385b0ad0500Skettenis void
db_stopproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)386b0ad0500Skettenis db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
387b0ad0500Skettenis {
388b0ad0500Skettenis 	struct cpu_info *ci;
389b0ad0500Skettenis 
390b0ad0500Skettenis 	if (have_addr) {
391b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
392ba177d4eSmpi 			if (addr == ci->ci_cpuid) {
393b0ad0500Skettenis 				db_stopcpu(ci);
394b0ad0500Skettenis 				break;
395b0ad0500Skettenis 			}
396b0ad0500Skettenis 		}
397b0ad0500Skettenis 		if (ci == NULL)
398b0ad0500Skettenis 			db_printf("Invalid cpu %d\n", (int)addr);
399b0ad0500Skettenis 	} else {
400b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
401b0ad0500Skettenis 			if (ci != curcpu())
402b0ad0500Skettenis 				db_stopcpu(ci);
403b0ad0500Skettenis 		}
404b0ad0500Skettenis 	}
405b0ad0500Skettenis }
406b0ad0500Skettenis 
407b0ad0500Skettenis void
db_ddbproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)408b0ad0500Skettenis db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
409b0ad0500Skettenis {
410b0ad0500Skettenis 	struct cpu_info *ci;
411b0ad0500Skettenis 
412b0ad0500Skettenis 	if (have_addr) {
413b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
414ba177d4eSmpi 			if (addr == ci->ci_cpuid && ci != curcpu()) {
415b0ad0500Skettenis 				db_stopcpu(ci);
416b0ad0500Skettenis 				db_switch_to_cpu = ci;
417b0ad0500Skettenis 				db_switch_cpu = 1;
418b0ad0500Skettenis 				db_cmd_loop_done = 1;
419b0ad0500Skettenis 				break;
420b0ad0500Skettenis 			}
421b0ad0500Skettenis 		}
422b0ad0500Skettenis 		if (ci == NULL)
423b0ad0500Skettenis 			db_printf("Invalid cpu %d\n", (int)addr);
424b0ad0500Skettenis 	} else {
425b0ad0500Skettenis 		db_printf("CPU not specified\n");
426b0ad0500Skettenis 	}
427b0ad0500Skettenis }
428b0ad0500Skettenis 
429b0ad0500Skettenis int
db_enter_ddb(void)430b0ad0500Skettenis db_enter_ddb(void)
431b0ad0500Skettenis {
432b0ad0500Skettenis 	struct cpu_info *ci;
433b0ad0500Skettenis 
4346c78d705Svisa 	db_mtx_enter(&ddb_mp_mutex);
435b0ad0500Skettenis 
436b0ad0500Skettenis 	/* If we are first in, grab ddb and stop all other CPUs */
437b0ad0500Skettenis 	if (ddb_state == DDB_STATE_NOT_RUNNING) {
438b0ad0500Skettenis 		ddb_active_cpu = cpu_number();
439b0ad0500Skettenis 		ddb_state = DDB_STATE_RUNNING;
440b0ad0500Skettenis 		curcpu()->ci_ddb_paused = CI_DDB_INDDB;
4416c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
442b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next) {
443b0ad0500Skettenis 			if (ci != curcpu() &&
444b0ad0500Skettenis 			    ci->ci_ddb_paused != CI_DDB_STOPPED) {
445b0ad0500Skettenis 				ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
446b0ad0500Skettenis 				sparc64_send_ipi(ci->ci_itid, ipi_db, 0, 0);
447b0ad0500Skettenis 			}
448b0ad0500Skettenis 		}
449b0ad0500Skettenis 		return (1);
450b0ad0500Skettenis 	}
451b0ad0500Skettenis 
452b0ad0500Skettenis 	/* Leaving ddb completely.  Start all other CPUs and return 0 */
453b0ad0500Skettenis 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
454b0ad0500Skettenis 		for (ci = cpus; ci != NULL; ci = ci->ci_next)
455b0ad0500Skettenis 			ci->ci_ddb_paused = CI_DDB_RUNNING;
4566c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
457b0ad0500Skettenis 		return (0);
458b0ad0500Skettenis 	}
459b0ad0500Skettenis 
460b0ad0500Skettenis 	/* We're switching to another CPU.  db_ddbproc_cmd() has made sure
461b0ad0500Skettenis 	 * it is waiting for ddb, we just have to set ddb_active_cpu. */
462b0ad0500Skettenis 	if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
463b0ad0500Skettenis 		curcpu()->ci_ddb_paused = CI_DDB_SHOULDSTOP;
464b0ad0500Skettenis 		db_switch_cpu = 0;
465ba177d4eSmpi 		ddb_active_cpu = db_switch_to_cpu->ci_cpuid;
466b0ad0500Skettenis 		db_switch_to_cpu->ci_ddb_paused = CI_DDB_ENTERDDB;
467b0ad0500Skettenis 	}
468b0ad0500Skettenis 
469b0ad0500Skettenis 	/* Wait until we should enter ddb or resume */
470b0ad0500Skettenis 	while (ddb_active_cpu != cpu_number() &&
471b0ad0500Skettenis 	    curcpu()->ci_ddb_paused != CI_DDB_RUNNING) {
472b0ad0500Skettenis 		if (curcpu()->ci_ddb_paused == CI_DDB_SHOULDSTOP)
473b0ad0500Skettenis 			curcpu()->ci_ddb_paused = CI_DDB_STOPPED;
4746c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
475b0ad0500Skettenis 
476b0ad0500Skettenis 		/* Busy wait without locking, we'll confirm with lock later */
477b0ad0500Skettenis 		while (ddb_active_cpu != cpu_number() &&
478b0ad0500Skettenis 		    curcpu()->ci_ddb_paused != CI_DDB_RUNNING)
479b0ad0500Skettenis 			CPU_BUSY_CYCLE();
480b0ad0500Skettenis 
4816c78d705Svisa 		db_mtx_enter(&ddb_mp_mutex);
482b0ad0500Skettenis 	}
483b0ad0500Skettenis 
484b0ad0500Skettenis 	/* Either enter ddb or exit */
485b0ad0500Skettenis 	if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
486b0ad0500Skettenis 		curcpu()->ci_ddb_paused = CI_DDB_INDDB;
4876c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
488b0ad0500Skettenis 		return (1);
489b0ad0500Skettenis 	} else {
4906c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
491b0ad0500Skettenis 		return (0);
492b0ad0500Skettenis 	}
493b0ad0500Skettenis }
494b0ad0500Skettenis 
495b0ad0500Skettenis void
db_startcpu(struct cpu_info * ci)496b0ad0500Skettenis db_startcpu(struct cpu_info *ci)
497b0ad0500Skettenis {
498b0ad0500Skettenis 	if (ci != curcpu()) {
4996c78d705Svisa 		db_mtx_enter(&ddb_mp_mutex);
500b0ad0500Skettenis 		ci->ci_ddb_paused = CI_DDB_RUNNING;
5016c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
502b0ad0500Skettenis 	}
503b0ad0500Skettenis }
504b0ad0500Skettenis 
505b0ad0500Skettenis void
db_stopcpu(struct cpu_info * ci)506b0ad0500Skettenis db_stopcpu(struct cpu_info *ci)
507b0ad0500Skettenis {
5086c78d705Svisa 	db_mtx_enter(&ddb_mp_mutex);
509b0ad0500Skettenis 	if (ci != curcpu() && ci->ci_ddb_paused != CI_DDB_STOPPED) {
510b0ad0500Skettenis 		ci->ci_ddb_paused = CI_DDB_SHOULDSTOP;
5116c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
512b0ad0500Skettenis 		sparc64_send_ipi(ci->ci_itid, ipi_db, 0, 0);
513b0ad0500Skettenis 	} else {
5146c78d705Svisa 		db_mtx_leave(&ddb_mp_mutex);
515b0ad0500Skettenis 	}
516b0ad0500Skettenis }
517b0ad0500Skettenis 
518b0ad0500Skettenis #endif
519b0ad0500Skettenis 
520d5d6a0bbSart /*
521d5d6a0bbSart  * Read bytes from kernel address space for debugger.
522d5d6a0bbSart  */
523d5d6a0bbSart void
db_read_bytes(vaddr_t addr,size_t size,void * datap)524fe1fe620Scheloha db_read_bytes(vaddr_t addr, size_t size, void *datap)
525d5d6a0bbSart {
526fe1fe620Scheloha 	char *data = datap;
527d5d6a0bbSart 	register char	*src;
528d5d6a0bbSart 
529d5d6a0bbSart 	src = (char *)addr;
530d5d6a0bbSart 	while (size-- > 0) {
531d5d6a0bbSart 		if (src >= (char *)VM_MIN_KERNEL_ADDRESS)
532d5d6a0bbSart 			*data++ = probeget((paddr_t)(u_long)src++, ASI_P, 1);
533d5d6a0bbSart 		else
534d62ebcb2Sderaadt 			_copyin(src++, data++, sizeof(u_char));
535d5d6a0bbSart 	}
536d5d6a0bbSart }
537d5d6a0bbSart 
538d5d6a0bbSart 
539d5d6a0bbSart /*
540d5d6a0bbSart  * Write bytes to kernel address space for debugger.
541d5d6a0bbSart  */
542d5d6a0bbSart void
db_write_bytes(vaddr_t addr,size_t size,void * datap)543fe1fe620Scheloha db_write_bytes(vaddr_t addr, size_t size, void *datap)
544d5d6a0bbSart {
545fe1fe620Scheloha 	char *data = datap;
546d5d6a0bbSart 	register char	*dst;
547d5d6a0bbSart 	extern vaddr_t ktext;
548d5d6a0bbSart 	extern paddr_t ktextp;
549d5d6a0bbSart 
550d5d6a0bbSart 	dst = (char *)addr;
551d5d6a0bbSart 	while (size-- > 0) {
55295012c4eSkettenis 		if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS+0x800000))
553d5d6a0bbSart 			*dst = *data;
554d5d6a0bbSart 		else if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) &&
55595012c4eSkettenis 			 (dst < (char *)VM_MIN_KERNEL_ADDRESS+0x800000))
556d5d6a0bbSart 			/* Read Only mapping -- need to do a bypass access */
557d5d6a0bbSart 			stba((u_long)dst - ktext + ktextp, ASI_PHYS_CACHED, *data);
558d5d6a0bbSart 		else
5591de66d4eSmiod 			copyout(data, dst, sizeof(char));
560d5d6a0bbSart 		dst++, data++;
561d5d6a0bbSart 	}
562d5d6a0bbSart 
563d5d6a0bbSart }
564d5d6a0bbSart 
565d5d6a0bbSart void
db_enter(void)566e97088d6Smpi db_enter(void)
567d5d6a0bbSart {
568d5d6a0bbSart 	/* We use the breakpoint to trap into DDB */
569d5d6a0bbSart 	asm("ta 1; nop");
570d5d6a0bbSart }
571d5d6a0bbSart 
572d5d6a0bbSart void
db_prom_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)57347c47feaSjsg db_prom_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
574d5d6a0bbSart {
575d5d6a0bbSart 	OF_enter();
576d5d6a0bbSart }
577d5d6a0bbSart 
5786e1e03d7Smdw #define CHEETAHP (((getver()>>32) & 0x1ff) >= 0x14)
5796e1e03d7Smdw unsigned long db_get_dtlb_data(int entry), db_get_dtlb_tag(int entry),
5806e1e03d7Smdw db_get_itlb_data(int entry), db_get_itlb_tag(int entry);
5816e1e03d7Smdw void db_print_itlb_entry(int entry, int i, int endc);
5826e1e03d7Smdw void db_print_dtlb_entry(int entry, int i, int endc);
5836e1e03d7Smdw 
584*da5607f6Sjsg extern __inline__ unsigned long
db_get_dtlb_data(int entry)585*da5607f6Sjsg db_get_dtlb_data(int entry)
5866e1e03d7Smdw {
5876e1e03d7Smdw 	unsigned long r;
5882df76cc2Sguenther 	__asm__ volatile("ldxa [%1] %2,%0"
5896e1e03d7Smdw 		: "=r" (r)
5906e1e03d7Smdw 		: "r" (entry <<3), "i" (ASI_DMMU_TLB_DATA));
5916e1e03d7Smdw 	return r;
5926e1e03d7Smdw }
593*da5607f6Sjsg 
594*da5607f6Sjsg extern __inline__ unsigned long
db_get_dtlb_tag(int entry)595*da5607f6Sjsg db_get_dtlb_tag(int entry)
5966e1e03d7Smdw {
5976e1e03d7Smdw 	unsigned long r;
5982df76cc2Sguenther 	__asm__ volatile("ldxa [%1] %2,%0"
5996e1e03d7Smdw 		: "=r" (r)
6006e1e03d7Smdw 		: "r" (entry <<3), "i" (ASI_DMMU_TLB_TAG));
6016e1e03d7Smdw 	return r;
6026e1e03d7Smdw }
603*da5607f6Sjsg 
604*da5607f6Sjsg extern __inline__ unsigned long
db_get_itlb_data(int entry)605*da5607f6Sjsg db_get_itlb_data(int entry)
6066e1e03d7Smdw {
6076e1e03d7Smdw 	unsigned long r;
6082df76cc2Sguenther 	__asm__ volatile("ldxa [%1] %2,%0"
6096e1e03d7Smdw 		: "=r" (r)
6106e1e03d7Smdw 		: "r" (entry <<3), "i" (ASI_IMMU_TLB_DATA));
6116e1e03d7Smdw 	return r;
6126e1e03d7Smdw }
613*da5607f6Sjsg 
614*da5607f6Sjsg extern __inline__ unsigned long
db_get_itlb_tag(int entry)615*da5607f6Sjsg db_get_itlb_tag(int entry)
6166e1e03d7Smdw {
6176e1e03d7Smdw 	unsigned long r;
6182df76cc2Sguenther 	__asm__ volatile("ldxa [%1] %2,%0"
6196e1e03d7Smdw 		: "=r" (r)
6206e1e03d7Smdw 		: "r" (entry <<3), "i" (ASI_IMMU_TLB_TAG));
6216e1e03d7Smdw 	return r;
6226e1e03d7Smdw }
6236e1e03d7Smdw 
624*da5607f6Sjsg void
db_print_dtlb_entry(int entry,int i,int endc)625*da5607f6Sjsg db_print_dtlb_entry(int entry, int i, int endc)
6266e1e03d7Smdw {
6276e1e03d7Smdw 	unsigned long tag, data;
6286e1e03d7Smdw 	tag = db_get_dtlb_tag(entry);
6296e1e03d7Smdw 	data = db_get_dtlb_data(entry);
6306e1e03d7Smdw 	db_printf("%2d:%16.16lx %16.16lx%c", i, tag, data, endc);
6316e1e03d7Smdw }
6326e1e03d7Smdw 
633*da5607f6Sjsg void
db_print_itlb_entry(int entry,int i,int endc)634*da5607f6Sjsg db_print_itlb_entry(int entry, int i, int endc)
6356e1e03d7Smdw {
6366e1e03d7Smdw 	unsigned long tag, data;
6376e1e03d7Smdw 	tag = db_get_itlb_tag(entry);
6386e1e03d7Smdw 	data = db_get_itlb_data(entry);
6396e1e03d7Smdw 	db_printf("%2d:%16.16lx %16.16lx%c", i, tag, data, endc);
6406e1e03d7Smdw }
6416e1e03d7Smdw 
642d5d6a0bbSart void
db_dump_dtlb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)64347c47feaSjsg db_dump_dtlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
644d5d6a0bbSart {
6456e1e03d7Smdw 	/* extern void print_dtlb(void); -- locore.s; no longer used here */
646d5d6a0bbSart 
647d5d6a0bbSart 	if (have_addr) {
648d5d6a0bbSart 		int i;
649d5d6a0bbSart 		int64_t* p = (int64_t*)addr;
650d5d6a0bbSart 		static int64_t buf[128];
651d5d6a0bbSart 		extern void dump_dtlb(int64_t *);
652d5d6a0bbSart 
6536e1e03d7Smdw 	if (CHEETAHP) {
6546e1e03d7Smdw 		db_printf("DTLB %ld\n", addr);
6556e1e03d7Smdw 		switch(addr)
6566e1e03d7Smdw 		{
6576e1e03d7Smdw 		case 0:
6586e1e03d7Smdw 			for (i = 0; i < 16; ++i)
6596e1e03d7Smdw 				db_print_dtlb_entry(i, i, (i&1)?'\n':' ');
6606e1e03d7Smdw 			break;
6616e1e03d7Smdw 		case 2:
6626e1e03d7Smdw 			for (i = 0; i < 512; ++i)
6636e1e03d7Smdw 				db_print_dtlb_entry(i+16384, i, (i&1)?'\n':' ');
6646e1e03d7Smdw 			break;
6656e1e03d7Smdw 		}
6666e1e03d7Smdw 	} else {
667d5d6a0bbSart 		dump_dtlb(buf);
668d5d6a0bbSart 		p = buf;
669d5d6a0bbSart 		for (i=0; i<64;) {
6702008d9f5Smiod 			db_printf("%2d:%16.16llx %16.16llx ", i++, p[0], p[1]);
671d5d6a0bbSart 			p += 2;
6722008d9f5Smiod 			db_printf("%2d:%16.16llx %16.16llx\n", i++, p[0], p[1]);
673d5d6a0bbSart 			p += 2;
674d5d6a0bbSart 		}
6756e1e03d7Smdw 	}
676d5d6a0bbSart 	} else {
6776e1e03d7Smdw printf ("Usage: mach dtlb 0,2\n");
6786e1e03d7Smdw 	}
6796e1e03d7Smdw }
6806e1e03d7Smdw 
6816e1e03d7Smdw void
db_dump_itlb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)68247c47feaSjsg db_dump_itlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
6836e1e03d7Smdw {
6846e1e03d7Smdw 	int i;
6856e1e03d7Smdw 	if (!have_addr) {
6866e1e03d7Smdw 		db_printf("Usage: mach itlb 0,1,2\n");
6876e1e03d7Smdw 		return;
6886e1e03d7Smdw 	}
6896e1e03d7Smdw 	if (CHEETAHP) {
6906e1e03d7Smdw 		db_printf("ITLB %ld\n", addr);
6916e1e03d7Smdw 		switch(addr)
6926e1e03d7Smdw 		{
6936e1e03d7Smdw 		case 0:
6946e1e03d7Smdw 			for (i = 0; i < 16; ++i)
6956e1e03d7Smdw 				db_print_itlb_entry(i, i, (i&1)?'\n':' ');
6966e1e03d7Smdw 			break;
6976e1e03d7Smdw 		case 2:
6986e1e03d7Smdw 			for (i = 0; i < 128; ++i)
6996e1e03d7Smdw 				db_print_itlb_entry(i+16384, i, (i&1)?'\n':' ');
7006e1e03d7Smdw 			break;
7016e1e03d7Smdw 		}
7026e1e03d7Smdw 	} else {
7036e1e03d7Smdw 		for (i = 0; i < 63; ++i)
7046e1e03d7Smdw 			db_print_itlb_entry(i, i, (i&1)?'\n':' ');
705d5d6a0bbSart 	}
706d5d6a0bbSart }
707d5d6a0bbSart 
708d5d6a0bbSart void
db_pload_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)70947c47feaSjsg db_pload_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
710d5d6a0bbSart {
711d5d6a0bbSart 	static paddr_t oldaddr = -1;
712d5d6a0bbSart 	int asi = ASI_PHYS_CACHED;
713d5d6a0bbSart 
714d5d6a0bbSart 	if (!have_addr) {
715d5d6a0bbSart 		addr = oldaddr;
716d5d6a0bbSart 	}
717d5d6a0bbSart 	if (addr == -1) {
718d5d6a0bbSart 		db_printf("no address\n");
719d5d6a0bbSart 		return;
720d5d6a0bbSart 	}
721d5d6a0bbSart 	addr &= ~0x7; /* align */
722d5d6a0bbSart 	{
723d5d6a0bbSart 		register char c, *cp = modif;
724d5d6a0bbSart 		while ((c = *cp++) != 0)
725d5d6a0bbSart 			if (c == 'u')
726d5d6a0bbSart 				asi = ASI_AIUS;
727d5d6a0bbSart 	}
728d5d6a0bbSart 	while (count--) {
729d5d6a0bbSart 		if (db_print_position() == 0) {
730d5d6a0bbSart 			/* Always print the address. */
731d5d6a0bbSart 			db_printf("%16.16lx:\t", addr);
732d5d6a0bbSart 		}
733d5d6a0bbSart 		oldaddr=addr;
734d5d6a0bbSart 		db_printf("%8.8lx\n", (long)ldxa(addr, asi));
735d5d6a0bbSart 		addr += 8;
736d5d6a0bbSart 		if (db_print_position() != 0)
737d5d6a0bbSart 			db_end_line(0);
738d5d6a0bbSart 	}
739d5d6a0bbSart }
740d5d6a0bbSart 
741c4071fd1Smillert int64_t pseg_get(struct pmap *, vaddr_t);
742d5d6a0bbSart 
743d5d6a0bbSart void
db_dump_pmap(struct pmap * pm)74447c47feaSjsg db_dump_pmap(struct pmap* pm)
745d5d6a0bbSart {
746d5d6a0bbSart 	/* print all valid pages in the kernel pmap */
747d5d6a0bbSart 	long i, j, k, n;
748d5d6a0bbSart 	paddr_t *pdir, *ptbl;
749d5d6a0bbSart 	/* Almost the same as pmap_collect() */
750d5d6a0bbSart 
751d5d6a0bbSart 	n = 0;
752d5d6a0bbSart 	for (i=0; i<STSZ; i++) {
753d5d6a0bbSart 		if((pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED))) {
754d5d6a0bbSart 			db_printf("pdir %ld at %lx:\n", i, (long)pdir);
755d5d6a0bbSart 			for (k=0; k<PDSZ; k++) {
756d5d6a0bbSart 				if ((ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED))) {
757d5d6a0bbSart 					db_printf("\tptable %ld:%ld at %lx:\n", i, k, (long)ptbl);
758d5d6a0bbSart 					for (j=0; j<PTSZ; j++) {
759d5d6a0bbSart 						int64_t data0, data1;
760d5d6a0bbSart 						data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
761d5d6a0bbSart 						j++;
762d5d6a0bbSart 						data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
763d5d6a0bbSart 						if (data0 || data1) {
764d5d6a0bbSart 							db_printf("%llx: %llx\t",
765d5d6a0bbSart 								  (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|((j-1)<<PTSHIFT)),
766d5d6a0bbSart 								  (unsigned long long)(data0));
767d5d6a0bbSart 							db_printf("%llx: %llx\n",
768d5d6a0bbSart 								  (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|(j<<PTSHIFT)),
769d5d6a0bbSart 								  (unsigned long long)(data1));
770d5d6a0bbSart 						}
771d5d6a0bbSart 					}
772d5d6a0bbSart 				}
773d5d6a0bbSart 			}
774d5d6a0bbSart 		}
775d5d6a0bbSart 	}
776d5d6a0bbSart }
777d5d6a0bbSart 
778d5d6a0bbSart void
db_pmap_kernel(db_expr_t addr,int have_addr,db_expr_t count,char * modif)77947c47feaSjsg db_pmap_kernel(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
780d5d6a0bbSart {
781d5d6a0bbSart 	extern struct pmap kernel_pmap_;
782d5d6a0bbSart 	int i, j, full = 0;
783d5d6a0bbSart 	u_int64_t data;
784d5d6a0bbSart 
785d5d6a0bbSart 	{
786d5d6a0bbSart 		register char c, *cp = modif;
787d5d6a0bbSart 		while ((c = *cp++) != 0)
788d5d6a0bbSart 			if (c == 'f')
789d5d6a0bbSart 				full = 1;
790d5d6a0bbSart 	}
791d5d6a0bbSart 	if (have_addr) {
792d5d6a0bbSart 		/* lookup an entry for this VA */
793d5d6a0bbSart 
794d5d6a0bbSart 		if ((data = pseg_get(&kernel_pmap_, (vaddr_t)addr))) {
795aaed5986Sguenther 			db_printf("pmap_kernel(%p)->pm_segs[%lx][%lx][%lx]=>%llx\n",
796d5d6a0bbSart 				  (void *)addr, (u_long)va_to_seg(addr),
797d5d6a0bbSart 				  (u_long)va_to_dir(addr), (u_long)va_to_pte(addr),
798d5d6a0bbSart 				  (unsigned long long)data);
799d5d6a0bbSart 		} else {
800d5d6a0bbSart 			db_printf("No mapping for %p\n", (void *)addr);
801d5d6a0bbSart 		}
802d5d6a0bbSart 		return;
803d5d6a0bbSart 	}
804d5d6a0bbSart 
805d5d6a0bbSart 	db_printf("pmap_kernel(%p) psegs %p phys %llx\n",
806d5d6a0bbSart 		  &kernel_pmap_, kernel_pmap_.pm_segs,
807d5d6a0bbSart 		  (unsigned long long)kernel_pmap_.pm_physaddr);
808d5d6a0bbSart 	if (full) {
809d5d6a0bbSart 		db_dump_pmap(&kernel_pmap_);
810d5d6a0bbSart 	} else {
811d5d6a0bbSart 		for (j=i=0; i<STSZ; i++) {
812d5d6a0bbSart 			long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED);
813d5d6a0bbSart 			if (seg)
814d5d6a0bbSart 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
815d5d6a0bbSart 		}
816d5d6a0bbSart 	}
817d5d6a0bbSart }
818d5d6a0bbSart 
819d5d6a0bbSart 
820d5d6a0bbSart void
db_pmap_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)82147c47feaSjsg db_pmap_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
822d5d6a0bbSart {
823d5d6a0bbSart 	struct pmap* pm=NULL;
824d5d6a0bbSart 	int i, j=0, full = 0;
825d5d6a0bbSart 
826d5d6a0bbSart 	{
827d5d6a0bbSart 		register char c, *cp = modif;
828d5d6a0bbSart 		if (modif)
829d5d6a0bbSart 			while ((c = *cp++) != 0)
830d5d6a0bbSart 				if (c == 'f')
831d5d6a0bbSart 					full = 1;
832d5d6a0bbSart 	}
833d5d6a0bbSart 	if (curproc && curproc->p_vmspace)
834d5d6a0bbSart 		pm = curproc->p_vmspace->vm_map.pmap;
835d5d6a0bbSart 	if (have_addr) {
836d5d6a0bbSart 		pm = (struct pmap*)addr;
837d5d6a0bbSart 	}
838d5d6a0bbSart 
839d5d6a0bbSart 	db_printf("pmap %p: ctx %x refs %d physaddr %llx psegs %p\n",
840d5d6a0bbSart 		pm, pm->pm_ctx, pm->pm_refs,
841d5d6a0bbSart 		(unsigned long long)pm->pm_physaddr, pm->pm_segs);
842d5d6a0bbSart 
843d5d6a0bbSart 	if (full) {
844d5d6a0bbSart 		db_dump_pmap(pm);
845d5d6a0bbSart 	} else {
846d5d6a0bbSart 		for (i=0; i<STSZ; i++) {
847d5d6a0bbSart 			long seg = (long)ldxa((vaddr_t)&kernel_pmap_.pm_segs[i], ASI_PHYS_CACHED);
848d5d6a0bbSart 			if (seg)
849d5d6a0bbSart 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
850d5d6a0bbSart 		}
851d5d6a0bbSart 	}
852d5d6a0bbSart }
853d5d6a0bbSart 
854d5d6a0bbSart 
855d5d6a0bbSart void
db_lock(db_expr_t addr,int have_addr,db_expr_t count,char * modif)85647c47feaSjsg db_lock(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
857d5d6a0bbSart {
858d5d6a0bbSart #if 0
859d5d6a0bbSart 	struct lock *l;
860d5d6a0bbSart 
861d5d6a0bbSart 	if (!have_addr) {
862d5d6a0bbSart 		db_printf("What lock address?\n");
863d5d6a0bbSart 		return;
864d5d6a0bbSart 	}
865d5d6a0bbSart 
866d5d6a0bbSart 	l = (struct lock *)addr;
867835dcf15Sthib 	db_printf("flags=%x\n waitcount=%x sharecount=%x "
868d5d6a0bbSart 	    "exclusivecount=%x\n wmesg=%s recurselevel=%x\n",
869835dcf15Sthib 	    l->lk_flags, l->lk_waitcount,
870d5d6a0bbSart 	    l->lk_sharecount, l->lk_exclusivecount, l->lk_wmesg,
871d5d6a0bbSart 	    l->lk_recurselevel);
872d5d6a0bbSart #else
873d5d6a0bbSart 	db_printf("locks unsupported\n");
874d5d6a0bbSart #endif
875d5d6a0bbSart }
876d5d6a0bbSart 
877d5d6a0bbSart void
db_dump_dtsb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)87847c47feaSjsg db_dump_dtsb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
879d5d6a0bbSart {
880a5f7570cSart 	extern pte_t *tsb_dmmu;
881d5d6a0bbSart 	extern int tsbsize;
882d5d6a0bbSart #define TSBENTS (512<<tsbsize)
883d5d6a0bbSart 	int i;
884d5d6a0bbSart 
885d5d6a0bbSart 	db_printf("TSB:\n");
886d5d6a0bbSart 	for (i=0; i<TSBENTS; i++) {
887d5d6a0bbSart 		db_printf("%4d:%4d:%08x %08x:%08x ", i,
888a5f7570cSart 			  (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
889a5f7570cSart 			  (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
890a5f7570cSart 			  (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
891d5d6a0bbSart 		i++;
892d5d6a0bbSart 		db_printf("%4d:%4d:%08x %08x:%08x\n", i,
893a5f7570cSart 			  (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
894a5f7570cSart 			  (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
895a5f7570cSart 			  (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
896d5d6a0bbSart 	}
897d5d6a0bbSart }
898d5d6a0bbSart 
899c4071fd1Smillert void db_page_cmd(db_expr_t, int, db_expr_t, char *);
900d5d6a0bbSart void
db_page_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)90147c47feaSjsg db_page_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
902d5d6a0bbSart {
903d5d6a0bbSart 
904d5d6a0bbSart 	if (!have_addr) {
905d5d6a0bbSart 		db_printf("Need paddr for page\n");
906d5d6a0bbSart 		return;
907d5d6a0bbSart 	}
908d5d6a0bbSart 
909d5d6a0bbSart 	db_printf("pa %llx pg %p\n", (unsigned long long)addr,
910d5d6a0bbSart 	    PHYS_TO_VM_PAGE(addr));
911d5d6a0bbSart }
912d5d6a0bbSart 
913d5d6a0bbSart 
914d5d6a0bbSart void
db_proc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)91547c47feaSjsg db_proc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
916d5d6a0bbSart {
917d5d6a0bbSart 	struct proc *p;
918d5d6a0bbSart 
919d5d6a0bbSart 	p = curproc;
920d5d6a0bbSart 	if (have_addr)
921d5d6a0bbSart 		p = (struct proc*) addr;
922d5d6a0bbSart 	if (p == NULL) {
923d5d6a0bbSart 		db_printf("no current process\n");
924d5d6a0bbSart 		return;
925d5d6a0bbSart 	}
926d5d6a0bbSart 	db_printf("process %p:", p);
92724e0bd45Smpi 	db_printf("pid:%d vmspace:%p pmap:%p ctx:%x wchan:%p rpri:%d upri:%d\n",
928552f6074Sguenther 	    p->p_p->ps_pid, p->p_vmspace, p->p_vmspace->vm_map.pmap,
929d5d6a0bbSart 	    p->p_vmspace->vm_map.pmap->pm_ctx,
93024e0bd45Smpi 	    p->p_wchan, p->p_runpri, p->p_usrpri);
931d5d6a0bbSart 	db_printf("maxsaddr:%p ssiz:%dpg or %llxB\n",
932d5d6a0bbSart 	    p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize,
933c5decc7cSmartin 	    (unsigned long long)ptoa(p->p_vmspace->vm_ssize));
934513a87f1Skettenis 	db_printf("profile timer: %lld sec %ld usec\n",
935513a87f1Skettenis 	    (long long)p->p_p->ps_timer[ITIMER_PROF].it_value.tv_sec,
936fcfbe7d9Scheloha 	    p->p_p->ps_timer[ITIMER_PROF].it_value.tv_nsec / 1000);
9379ac1798bSkettenis 	db_printf("pcb: %p tf: %p fpstate: %p\n", &p->p_addr->u_pcb,
9389ac1798bSkettenis 	    p->p_md.md_tf, p->p_md.md_fpstate);
939d5d6a0bbSart 	return;
940d5d6a0bbSart }
941d5d6a0bbSart 
942d5d6a0bbSart void
db_ctx_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)94347c47feaSjsg db_ctx_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
944d5d6a0bbSart {
945d5d6a0bbSart 	struct proc *p;
946d5d6a0bbSart 
947d5d6a0bbSart 	/* XXX LOCKING XXX */
9485cf5f4a3Smiod 	LIST_FOREACH(p, &allproc, p_list) {
949d5d6a0bbSart 		if (p->p_stat) {
950d5d6a0bbSart 			db_printf("process %p:", p);
951d5d6a0bbSart 			db_printf("pid:%d pmap:%p ctx:%x tf:%p fpstate %p "
952d5d6a0bbSart 			    "lastcall:%s\n",
953552f6074Sguenther 			    p->p_p->ps_pid, p->p_vmspace->vm_map.pmap,
954d5d6a0bbSart 			    p->p_vmspace->vm_map.pmap->pm_ctx,
955d5d6a0bbSart 			    p->p_md.md_tf, p->p_md.md_fpstate,
956d5d6a0bbSart 			    (p->p_addr->u_pcb.lastcall)?
957d5d6a0bbSart 			    p->p_addr->u_pcb.lastcall : "Null");
958d5d6a0bbSart 		}
959d5d6a0bbSart 	}
960d5d6a0bbSart 	return;
961d5d6a0bbSart }
962d5d6a0bbSart 
963d5d6a0bbSart void
db_dump_pcb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)96447c47feaSjsg db_dump_pcb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
965d5d6a0bbSart {
966d5d6a0bbSart 	struct pcb *pcb;
967d5d6a0bbSart 	int i;
968d5d6a0bbSart 
9694ced3000Skettenis 	pcb = curpcb;
970d5d6a0bbSart 	if (have_addr)
971d5d6a0bbSart 		pcb = (struct pcb*) addr;
972d5d6a0bbSart 
973d5d6a0bbSart 	db_printf("pcb@%p sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
974d5d6a0bbSart 		  pcb, (void *)(long)pcb->pcb_sp, (void *)(long)pcb->pcb_pc, pcb->pcb_cwp,
975d5d6a0bbSart 		  pcb->pcb_pil, pcb->pcb_nsaved, (void *)pcb->pcb_onfault,
976d5d6a0bbSart 		  (pcb->lastcall)?pcb->lastcall:"Null");
977d5d6a0bbSart 
978d5d6a0bbSart 	for (i=0; i<pcb->pcb_nsaved; i++) {
979d5d6a0bbSart 		db_printf("win %d: at %llx local, in\n", i,
9809ac1798bSkettenis 			  (unsigned long long)pcb->pcb_rwsp[i]);
981d5d6a0bbSart 		db_printf("%16llx %16llx %16llx %16llx\n",
982d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[0],
983d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[1],
984d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[2],
985d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[3]);
986d5d6a0bbSart 		db_printf("%16llx %16llx %16llx %16llx\n",
987d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[4],
988d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[5],
989d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[6],
990d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_local[7]);
991d5d6a0bbSart 		db_printf("%16llx %16llx %16llx %16llx\n",
992d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[0],
993d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[1],
994d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[2],
995d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[3]);
996d5d6a0bbSart 		db_printf("%16llx %16llx %16llx %16llx\n",
997d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[4],
998d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[5],
999d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[6],
1000d5d6a0bbSart 			  (unsigned long long)pcb->pcb_rw[i].rw_in[7]);
1001d5d6a0bbSart 	}
1002d5d6a0bbSart }
1003d5d6a0bbSart 
1004d5d6a0bbSart 
1005d5d6a0bbSart void
db_setpcb(db_expr_t addr,int have_addr,db_expr_t count,char * modif)100647c47feaSjsg db_setpcb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1007d5d6a0bbSart {
10088abdd659Sguenther 	struct proc *p;
1009d5d6a0bbSart 
1010d5d6a0bbSart 	if (!have_addr) {
10113b7181b7Sguenther 		db_printf("What TID do you want to map in?\n");
1012d5d6a0bbSart 		return;
1013d5d6a0bbSart 	}
1014d5d6a0bbSart 
10155cf5f4a3Smiod 	LIST_FOREACH(p, &allproc, p_list) {
10163b7181b7Sguenther 		if (p->p_stat && p->p_tid == addr) {
1017d5d6a0bbSart 			curproc = p;
10184ced3000Skettenis 			curpcb = (struct pcb*)p->p_addr;
10198ad6162fSmiod 			curcpu()->ci_cpcbpaddr = p->p_md.md_pcbpaddr;
1020d5d6a0bbSart 			if (p->p_vmspace->vm_map.pmap->pm_ctx) {
1021d5d6a0bbSart 				switchtoctx(p->p_vmspace->vm_map.pmap->pm_ctx);
1022d5d6a0bbSart 				return;
1023d5d6a0bbSart 			}
10243b7181b7Sguenther 			db_printf("TID %ld has a null context.\n", addr);
1025d5d6a0bbSart 			return;
1026d5d6a0bbSart 		}
1027d5d6a0bbSart 	}
10283b7181b7Sguenther 	db_printf("TID %ld not found.\n", addr);
1029d5d6a0bbSart }
1030d5d6a0bbSart 
1031d5d6a0bbSart 
1032d5d6a0bbSart /*
1033d5d6a0bbSart  * Use physical or virtual watchpoint registers -- ugh
1034d5d6a0bbSart  */
1035d5d6a0bbSart void
db_watch(db_expr_t addr,int have_addr,db_expr_t count,char * modif)103647c47feaSjsg db_watch(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1037d5d6a0bbSart {
1038d5d6a0bbSart 	int phys = 0;
1039d5d6a0bbSart 
1040d5d6a0bbSart #define WATCH_VR	(1L<<22)
1041d5d6a0bbSart #define WATCH_VW	(1L<<21)
1042d5d6a0bbSart #define WATCH_PR	(1L<<24)
1043d5d6a0bbSart #define WATCH_PW	(1L<<23)
1044d5d6a0bbSart #define WATCH_PM	(((u_int64_t)0xffffL)<<33)
1045d5d6a0bbSart #define WATCH_VM	(((u_int64_t)0xffffL)<<25)
1046d5d6a0bbSart 
1047d5d6a0bbSart 	{
1048d5d6a0bbSart 		register char c, *cp = modif;
1049d5d6a0bbSart 		if (modif)
1050d5d6a0bbSart 			while ((c = *cp++) != 0)
1051d5d6a0bbSart 				if (c == 'p')
1052d5d6a0bbSart 					phys = 1;
1053d5d6a0bbSart 	}
1054d5d6a0bbSart 	if (have_addr) {
1055d5d6a0bbSart 		/* turn on the watchpoint */
1056d5d6a0bbSart 		int64_t tmp = ldxa(0, ASI_MCCR);
1057d5d6a0bbSart 
1058d5d6a0bbSart 		if (phys) {
1059d5d6a0bbSart 			tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
1060d5d6a0bbSart 			stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
1061d5d6a0bbSart 		} else {
1062d5d6a0bbSart 			tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
1063d5d6a0bbSart 			stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
1064d5d6a0bbSart 		}
1065d5d6a0bbSart 		stxa(0, ASI_MCCR, tmp);
1066d5d6a0bbSart 	} else {
1067d5d6a0bbSart 		/* turn off the watchpoint */
1068d5d6a0bbSart 		int64_t tmp = ldxa(0, ASI_MCCR);
1069d5d6a0bbSart 		if (phys) tmp &= ~(WATCH_PM);
1070d5d6a0bbSart 		else tmp &= ~(WATCH_VM);
1071d5d6a0bbSart 		stxa(0, ASI_MCCR, tmp);
1072d5d6a0bbSart 	}
1073d5d6a0bbSart }
1074d5d6a0bbSart 
107509671eefSkettenis /*
107609671eefSkettenis  * Provide a way to trigger an External Initiated Reset (XIR).  Some
107709671eefSkettenis  * systems can target individual processors, others can only target
107809671eefSkettenis  * all processors at once.
107909671eefSkettenis  */
108009671eefSkettenis 
108109671eefSkettenis struct xirhand {
108209671eefSkettenis 	void (*xh_fun)(void *, int);
108309671eefSkettenis 	void *xh_arg;
108409671eefSkettenis 	SIMPLEQ_ENTRY(xirhand) xh_list;
108509671eefSkettenis };
108609671eefSkettenis 
108709671eefSkettenis SIMPLEQ_HEAD(, xirhand) db_xh = SIMPLEQ_HEAD_INITIALIZER(db_xh);
108809671eefSkettenis 
108909671eefSkettenis void
db_xir(db_expr_t addr,int have_addr,db_expr_t count,char * modif)109009671eefSkettenis db_xir(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
109109671eefSkettenis {
109209671eefSkettenis 	struct xirhand *xh;
109309671eefSkettenis 
109409671eefSkettenis 	if (!have_addr)
109509671eefSkettenis 		addr = -1;
109609671eefSkettenis 
109709671eefSkettenis 	SIMPLEQ_FOREACH(xh, &db_xh, xh_list) {
109809671eefSkettenis 		xh->xh_fun(xh->xh_arg, addr);
109909671eefSkettenis 	}
110009671eefSkettenis }
110109671eefSkettenis 
110209671eefSkettenis void
db_register_xir(void (* fun)(void *,int),void * arg)110309671eefSkettenis db_register_xir(void (*fun)(void *, int), void *arg)
110409671eefSkettenis {
110509671eefSkettenis 	struct xirhand *xh;
110609671eefSkettenis 
110709671eefSkettenis 	xh = malloc(sizeof(*xh), M_DEVBUF, M_NOWAIT);
110809671eefSkettenis 	if (xh == NULL)
110909671eefSkettenis 		panic("db_register_xir");
111009671eefSkettenis 	xh->xh_fun = fun;
111109671eefSkettenis 	xh->xh_arg = arg;
111209671eefSkettenis 	SIMPLEQ_INSERT_TAIL(&db_xh, xh, xh_list);
111309671eefSkettenis }
111409671eefSkettenis 
1115d5d6a0bbSart 
1116d5d6a0bbSart #if NESP_SBUS
1117d5d6a0bbSart extern void db_esp(db_expr_t, int, db_expr_t, char *);
1118d5d6a0bbSart #endif
1119d5d6a0bbSart 
11203fe80b7fSnaddy const struct db_command db_machine_command_table[] = {
1121d5d6a0bbSart 	{ "ctx",	db_ctx_cmd,	0,	0 },
1122d5d6a0bbSart 	{ "dtlb",	db_dump_dtlb,	0,	0 },
1123d5d6a0bbSart 	{ "dtsb",	db_dump_dtsb,	0,	0 },
1124d5d6a0bbSart #if NESP_SBUS
1125d5d6a0bbSart 	{ "esp",	db_esp,		0,	0 },
1126d5d6a0bbSart #endif
1127d5d6a0bbSart 	{ "fpstate",	db_dump_fpstate,0,	0 },
11286e1e03d7Smdw 	{ "itlb",	db_dump_itlb,	0,	0 },
1129d5d6a0bbSart 	{ "kmap",	db_pmap_kernel,	0,	0 },
1130d5d6a0bbSart 	{ "lock",	db_lock,	0,	0 },
1131d5d6a0bbSart 	{ "pcb",	db_dump_pcb,	0,	0 },
1132d5d6a0bbSart 	{ "pctx",	db_setpcb,	0,	0 },
1133d5d6a0bbSart 	{ "page",	db_page_cmd,	0,	0 },
1134d5d6a0bbSart 	{ "phys",	db_pload_cmd,	0,	0 },
1135d5d6a0bbSart 	{ "pmap",	db_pmap_cmd,	0,	0 },
1136d5d6a0bbSart 	{ "proc",	db_proc_cmd,	0,	0 },
1137d5d6a0bbSart 	{ "prom",	db_prom_cmd,	0,	0 },
1138d5d6a0bbSart 	{ "pv",		db_dump_pv,	0,	0 },
1139d5d6a0bbSart 	{ "stack",	db_dump_stack,	0,	0 },
1140d5d6a0bbSart 	{ "tf",		db_dump_trap,	0,	0 },
1141d5d6a0bbSart 	{ "ts",		db_dump_ts,	0,	0 },
1142d5d6a0bbSart 	{ "watch",	db_watch,	0,	0 },
1143d5d6a0bbSart 	{ "window",	db_dump_window,	0,	0 },
114409671eefSkettenis 	{ "xir",	db_xir,		0,	0 },
1145b0ad0500Skettenis #ifdef MULTIPROCESSOR
1146b0ad0500Skettenis 	{ "cpuinfo",	db_cpuinfo_cmd,		0,	0 },
1147b0ad0500Skettenis 	{ "startcpu",	db_startproc_cmd,	0,	0 },
1148b0ad0500Skettenis 	{ "stopcpu",	db_stopproc_cmd,	0,	0 },
1149b0ad0500Skettenis 	{ "ddbcpu",	db_ddbproc_cmd,		0,	0 },
1150b0ad0500Skettenis #endif
115114bf419fSkrw 	{ NULL, }
1152d5d6a0bbSart };
1153d5d6a0bbSart 
1154d5d6a0bbSart /*
1155d5d6a0bbSart  * support for SOFTWARE_SSTEP:
1156d5d6a0bbSart  * return the next pc if the given branch is taken.
1157d5d6a0bbSart  *
1158d5d6a0bbSart  * note: in the case of conditional branches with annul,
1159d5d6a0bbSart  * this actually returns the next pc in the "not taken" path,
1160d5d6a0bbSart  * but in that case next_instr_address() will return the
1161d5d6a0bbSart  * next pc in the "taken" path.  so even tho the breakpoints
1162d5d6a0bbSart  * are backwards, everything will still work, and the logic is
1163d5d6a0bbSart  * much simpler this way.
1164d5d6a0bbSart  */
11656d6b8a87Smpi vaddr_t
db_branch_taken(int inst,vaddr_t pc,db_regs_t * regs)11666d6b8a87Smpi db_branch_taken(int inst, vaddr_t pc, db_regs_t *regs)
1167d5d6a0bbSart {
1168d5d6a0bbSart     union instr insn;
11696d6b8a87Smpi     vaddr_t npc = ddb_regs.ddb_tf.tf_npc;
1170d5d6a0bbSart 
1171d5d6a0bbSart     insn.i_int = inst;
1172d5d6a0bbSart 
1173600e658dSmdw     /* the fancy union just gets in the way of this: */
1174600e658dSmdw     switch(inst & 0xffc00000) {
1175600e658dSmdw     case 0x30400000:	/* branch always, annul, with prediction */
1176600e658dSmdw 	return pc + ((inst<<(32-19))>>((32-19)-2));
1177600e658dSmdw     case 0x30800000:	/* branch always, annul */
1178600e658dSmdw 	return pc + ((inst<<(32-22))>>((32-22)-2));
1179600e658dSmdw     }
1180600e658dSmdw 
1181d5d6a0bbSart     /*
1182d5d6a0bbSart      * if this is not an annulled conditional branch, the next pc is "npc".
1183d5d6a0bbSart      */
1184d5d6a0bbSart 
1185d5d6a0bbSart     if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1)
1186d5d6a0bbSart 	return npc;
1187d5d6a0bbSart 
1188d5d6a0bbSart     switch (insn.i_op2.i_op2) {
1189d5d6a0bbSart       case IOP2_Bicc:
1190d5d6a0bbSart       case IOP2_FBfcc:
1191d5d6a0bbSart       case IOP2_BPcc:
1192d5d6a0bbSart       case IOP2_FBPfcc:
1193d5d6a0bbSart       case IOP2_CBccc:
1194d5d6a0bbSart 	/* branch on some condition-code */
1195d5d6a0bbSart 	switch (insn.i_branch.i_cond)
1196d5d6a0bbSart 	{
1197d5d6a0bbSart 	  case Icc_A: /* always */
1198d5d6a0bbSart 	    return pc + ((inst << 10) >> 8);
1199d5d6a0bbSart 
1200d5d6a0bbSart 	  default: /* all other conditions */
1201d5d6a0bbSart 	    return npc + 4;
1202d5d6a0bbSart 	}
1203d5d6a0bbSart 
1204d5d6a0bbSart       case IOP2_BPr:
1205d5d6a0bbSart 	/* branch on register, always conditional */
1206d5d6a0bbSart 	return npc + 4;
1207d5d6a0bbSart 
1208d5d6a0bbSart       default:
1209d5d6a0bbSart 	/* not a branch */
1210d5d6a0bbSart 	panic("branch_taken() on non-branch");
1211d5d6a0bbSart     }
1212d5d6a0bbSart }
1213d5d6a0bbSart 
1214fed26a10Smpi int
db_inst_branch(int inst)1215fed26a10Smpi db_inst_branch(int inst)
1216d5d6a0bbSart {
1217d5d6a0bbSart     union instr insn;
1218d5d6a0bbSart 
1219d5d6a0bbSart     insn.i_int = inst;
1220d5d6a0bbSart 
1221600e658dSmdw     /* the fancy union just gets in the way of this: */
1222600e658dSmdw     switch(inst & 0xffc00000) {
1223600e658dSmdw     case 0x30400000:	/* branch always, annul, with prediction */
1224fed26a10Smpi 	return 1;
1225600e658dSmdw     case 0x30800000:	/* branch always, annul */
1226fed26a10Smpi 	return 1;
1227600e658dSmdw     }
1228600e658dSmdw 
1229d5d6a0bbSart     if (insn.i_any.i_op != IOP_OP2)
1230fed26a10Smpi 	return 0;
1231d5d6a0bbSart 
1232d5d6a0bbSart     switch (insn.i_op2.i_op2) {
1233d5d6a0bbSart       case IOP2_BPcc:
1234d5d6a0bbSart       case IOP2_Bicc:
1235d5d6a0bbSart       case IOP2_BPr:
1236d5d6a0bbSart       case IOP2_FBPfcc:
1237d5d6a0bbSart       case IOP2_FBfcc:
1238d5d6a0bbSart       case IOP2_CBccc:
1239fed26a10Smpi 	return 1;
1240d5d6a0bbSart 
1241d5d6a0bbSart       default:
1242fed26a10Smpi 	return 0;
1243d5d6a0bbSart     }
1244d5d6a0bbSart }
1245d5d6a0bbSart 
1246d5d6a0bbSart 
1247fed26a10Smpi int
db_inst_call(int inst)1248fed26a10Smpi db_inst_call(int inst)
1249d5d6a0bbSart {
1250d5d6a0bbSart     union instr insn;
1251d5d6a0bbSart 
1252d5d6a0bbSart     insn.i_int = inst;
1253d5d6a0bbSart 
1254d5d6a0bbSart     switch (insn.i_any.i_op) {
1255d5d6a0bbSart       case IOP_CALL:
1256fed26a10Smpi 	return 1;
1257d5d6a0bbSart 
1258d5d6a0bbSart       case IOP_reg:
1259d5d6a0bbSart 	return (insn.i_op3.i_op3 == IOP3_JMPL) && !db_inst_return(inst);
1260d5d6a0bbSart 
1261d5d6a0bbSart       default:
1262fed26a10Smpi 	return 0;
1263d5d6a0bbSart     }
1264d5d6a0bbSart }
1265d5d6a0bbSart 
1266d5d6a0bbSart 
1267fed26a10Smpi int
db_inst_unconditional_flow_transfer(int inst)1268fed26a10Smpi db_inst_unconditional_flow_transfer(int inst)
1269d5d6a0bbSart {
1270d5d6a0bbSart     union instr insn;
1271d5d6a0bbSart 
1272d5d6a0bbSart     insn.i_int = inst;
1273d5d6a0bbSart 
1274d5d6a0bbSart     if (db_inst_call(inst))
1275fed26a10Smpi 	return 1;
1276d5d6a0bbSart 
1277d5d6a0bbSart     if (insn.i_any.i_op != IOP_OP2)
1278fed26a10Smpi 	return 0;
1279d5d6a0bbSart 
1280d5d6a0bbSart     switch (insn.i_op2.i_op2)
1281d5d6a0bbSart     {
1282d5d6a0bbSart       case IOP2_BPcc:
1283d5d6a0bbSart       case IOP2_Bicc:
1284d5d6a0bbSart       case IOP2_FBPfcc:
1285d5d6a0bbSart       case IOP2_FBfcc:
1286d5d6a0bbSart       case IOP2_CBccc:
1287d5d6a0bbSart 	return insn.i_branch.i_cond == Icc_A;
1288d5d6a0bbSart 
1289d5d6a0bbSart       default:
1290fed26a10Smpi 	return 0;
1291d5d6a0bbSart     }
1292d5d6a0bbSart }
1293d5d6a0bbSart 
1294d5d6a0bbSart 
1295fed26a10Smpi int
db_inst_return(int inst)1296fed26a10Smpi db_inst_return(int inst)
1297d5d6a0bbSart {
1298d5d6a0bbSart     return (inst == I_JMPLri(I_G0, I_O7, 8) ||		/* ret */
1299d5d6a0bbSart 	    inst == I_JMPLri(I_G0, I_I7, 8));		/* retl */
1300d5d6a0bbSart }
1301d5d6a0bbSart 
1302fed26a10Smpi int
db_inst_trap_return(int inst)1303fed26a10Smpi db_inst_trap_return(int inst)
1304d5d6a0bbSart {
1305d5d6a0bbSart     union instr insn;
1306d5d6a0bbSart 
1307d5d6a0bbSart     insn.i_int = inst;
1308d5d6a0bbSart 
1309d5d6a0bbSart     return (insn.i_any.i_op == IOP_reg &&
1310d5d6a0bbSart 	    insn.i_op3.i_op3 == IOP3_RETT);
1311d5d6a0bbSart }
1312d5d6a0bbSart 
13136ecd5bf4Sjason void
db_machine_init(void)13140aac5001Snaddy db_machine_init(void)
13156ecd5bf4Sjason {
13166ecd5bf4Sjason }
1317