xref: /netbsd/sys/arch/sparc64/sparc64/db_interface.c (revision e00aa033)
1 /*	$NetBSD: db_interface.c,v 1.138 2022/10/26 23:38:08 riastradh Exp $ */
2 
3 /*
4  * Copyright (c) 1996-2002 Eduardo Horvath.  All rights reserved.
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 /*
33  * Interface to new debugger.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.138 2022/10/26 23:38:08 riastradh Exp $");
38 
39 #ifdef _KERNEL_OPT
40 #include "opt_ddb.h"
41 #include "opt_multiprocessor.h"
42 #endif
43 
44 #include <sys/param.h>
45 #include <sys/proc.h>
46 #include <sys/reboot.h>
47 #include <sys/systm.h>
48 #include <sys/atomic.h>
49 
50 #include <uvm/uvm.h>
51 
52 #include <dev/cons.h>
53 
54 #include <machine/db_machdep.h>
55 #include <ddb/db_active.h>
56 #include <ddb/db_command.h>
57 #include <ddb/db_sym.h>
58 #include <ddb/db_variables.h>
59 #include <ddb/db_user.h>
60 #include <ddb/db_extern.h>
61 #include <ddb/db_access.h>
62 #include <ddb/db_output.h>
63 #include <ddb/db_interface.h>
64 #include <ddb/ddbvar.h>
65 
66 #include <machine/instr.h>
67 #include <machine/cpu.h>
68 #ifdef _KERNEL
69 #include <machine/promlib.h>
70 #endif
71 #include <machine/ctlreg.h>
72 #include <machine/pmap.h>
73 #include <machine/intr.h>
74 #include <machine/vmparam.h>
75 
76 #ifdef _KERNEL
77 #include "fb.h"
78 #else
79 #include <stddef.h>
80 #include <stdbool.h>
81 #endif
82 
83 extern struct traptrace {
84 	unsigned short tl:3,	/* Trap level */
85 		ns:4,		/* PCB nsaved */
86 		tt:9;		/* Trap type */
87 	unsigned short pid;	/* PID */
88 	u_int tstate;		/* tstate */
89 	u_int tsp;		/* sp */
90 	u_int tpc;		/* pc */
91 	u_int tfault;		/* MMU tag access */
92 } trap_trace[], trap_trace_end[];
93 
94 void fill_ddb_regs_from_tf(struct trapframe64 *tf);
95 void ddb_restore_state(void);
96 bool ddb_running_on_this_cpu(void);
97 
98 int	db_active = 0;
99 
100 extern char *trap_type[];
101 
102 void kdb_kbd_trap(struct trapframe64 *);
103 void db_prom_cmd(db_expr_t, bool, db_expr_t, const char *);
104 void db_lwp_cmd(db_expr_t, bool, db_expr_t, const char *);
105 void db_proc_cmd(db_expr_t, bool, db_expr_t, const char *);
106 void db_ctx_cmd(db_expr_t, bool, db_expr_t, const char *);
107 void db_dump_pcb(db_expr_t, bool, db_expr_t, const char *);
108 void db_dump_pv(db_expr_t, bool, db_expr_t, const char *);
109 void db_setpcb(db_expr_t, bool, db_expr_t, const char *);
110 void db_dump_dtlb(db_expr_t, bool, db_expr_t, const char *);
111 void db_dump_itlb(db_expr_t, bool, db_expr_t, const char *);
112 void db_dump_dtsb(db_expr_t, bool, db_expr_t, const char *);
113 void db_dump_itsb(db_expr_t, bool, db_expr_t, const char *);
114 void db_pmap_kernel(db_expr_t, bool, db_expr_t, const char *);
115 void db_pload_cmd(db_expr_t, bool, db_expr_t, const char *);
116 void db_pmap_cmd(db_expr_t, bool, db_expr_t, const char *);
117 void db_traptrace(db_expr_t, bool, db_expr_t, const char *);
118 void db_watch(db_expr_t, bool, db_expr_t, const char *);
119 void db_pm_extract(db_expr_t, bool, db_expr_t, const char *);
120 void db_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
121 void db_sir_cmd(db_expr_t, bool, db_expr_t, const char *);
122 
123 #ifdef DDB
124 static void db_dump_pmap(struct pmap *);
125 static void db_print_trace_entry(struct traptrace *, int);
126 
127 #ifdef MULTIPROCESSOR
128 
129 #define NOCPU -1
130 
131 static int db_suspend_others(void);
132 static void ddb_suspend(struct trapframe64 *);
133 void db_resume_others(void);
134 
135 int ddb_cpu = NOCPU;
136 
137 bool
ddb_running_on_this_cpu(void)138 ddb_running_on_this_cpu(void)
139 {
140 	return ddb_cpu == cpu_number();
141 }
142 
143 static int
db_suspend_others(void)144 db_suspend_others(void)
145 {
146 	int cpu_me = cpu_number();
147 	bool win;
148 
149 	if (cpus == NULL)
150 		return 1;
151 
152 	win = atomic_cas_32(&ddb_cpu, NOCPU, cpu_me) == (uint32_t)NOCPU;
153 	if (win)
154 		mp_pause_cpus();
155 
156 	return win;
157 }
158 
159 void
db_resume_others(void)160 db_resume_others(void)
161 {
162 	int cpu_me = cpu_number();
163 
164 	if (atomic_cas_32(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
165 		mp_resume_cpus();
166 }
167 
168 static void
ddb_suspend(struct trapframe64 * tf)169 ddb_suspend(struct trapframe64 *tf)
170 {
171 
172 	sparc64_ipi_pause_thiscpu(tf);
173 }
174 #endif /* MULTIPROCESSOR */
175 
176 /*
177  * Received keyboard interrupt sequence.
178  */
179 void
kdb_kbd_trap(struct trapframe64 * tf)180 kdb_kbd_trap(struct trapframe64 *tf)
181 {
182 	if (db_active == 0 /* && (boothowto & RB_KDB) */) {
183 		printf("\n\nkernel: keyboard interrupt tf=%p\n", tf);
184 		kdb_trap(-1, tf);
185 	}
186 }
187 
188 void
fill_ddb_regs_from_tf(struct trapframe64 * tf)189 fill_ddb_regs_from_tf(struct trapframe64 *tf)
190 {
191 	extern int savetstate(struct trapstate *);
192 
193 #ifdef MULTIPROCESSOR
194 	static db_regs_t ddbregs[CPUSET_MAXNUMCPU];
195 
196 	curcpu()->ci_ddb_regs = &ddbregs[cpu_number()];
197 #else
198 	static db_regs_t ddbregs;
199 
200 	curcpu()->ci_ddb_regs = &ddbregs;
201 #endif
202 
203 	DDB_REGS->db_tf = *tf;
204 #ifdef __arch64__
205 	DDB_REGS->db_fr = *(struct frame64 *)(uintptr_t)tf->tf_out[6];
206 #else
207     {
208 	struct frame32 *tf32 = (struct frame32 *)(uintptr_t)tf->tf_out[6];
209 	int i;
210 
211 	for (i = 0; i < 8; i++)
212 		DDB_REGS->db_fr.fr_local[i] = (uint32_t)tf32->fr_local[i];
213 	for (i = 0; i < 6; i++)
214 		DDB_REGS->db_fr.fr_arg[i] = (uint32_t)tf32->fr_arg[i];
215 	DDB_REGS->db_fr.fr_fp = tf32->fr_fp;
216 	DDB_REGS->db_fr.fr_pc = tf32->fr_pc;
217     }
218 #endif
219 
220 	if (fplwp) {
221 		savefpstate(fplwp->l_md.md_fpstate);
222 		DDB_REGS->db_fpstate = *fplwp->l_md.md_fpstate;
223 		loadfpstate(fplwp->l_md.md_fpstate);
224 	}
225 	/* We should do a proper copyin and xlate 64-bit stack frames, but... */
226 /*	if (tf->tf_tstate & TSTATE_PRIV) { .. } */
227 
228 #if 0
229 	/* make sure this is not causing ddb problems. */
230 	if (tf->tf_out[6] & 1) {
231 		if ((unsigned)(tf->tf_out[6] + BIAS) > (unsigned)KERNBASE)
232 			DDB_REGS->db_fr = *(struct frame64 *)(tf->tf_out[6] + BIAS);
233 		else
234 			copyin((void *)(tf->tf_out[6] + BIAS), &DDB_REGS->db_fr, sizeof(struct frame64));
235 	} else {
236 		struct frame32 tfr;
237 		int i;
238 
239 		/* First get a local copy of the frame32 */
240 		if ((unsigned)(tf->tf_out[6]) > (unsigned)KERNBASE)
241 			tfr = *(struct frame32 *)tf->tf_out[6];
242 		else
243 			copyin((void *)(tf->tf_out[6]), &tfr, sizeof(struct frame32));
244 		/* Now copy each field from the 32-bit value to the 64-bit value */
245 		for (i=0; i<8; i++)
246 			DDB_REGS->db_fr.fr_local[i] = tfr.fr_local[i];
247 		for (i=0; i<6; i++)
248 			DDB_REGS->db_fr.fr_arg[i] = tfr.fr_arg[i];
249 		DDB_REGS->db_fr.fr_fp = (long)tfr.fr_fp;
250 		DDB_REGS->db_fr.fr_pc = tfr.fr_pc;
251 	}
252 #else
253 	int i;
254 	for (i=0; i<8; i++)
255 	  DDB_REGS->db_fr.fr_local[i] = tf->tf_local[i];
256 	for (i=0; i<6; i++)
257 	  DDB_REGS->db_fr.fr_arg[i] = tf->tf_in[i];
258 	/* XXX tp and pc are missing */
259 #endif
260 	DDB_REGS->db_tl = savetstate(&DDB_REGS->db_ts[0]);
261 }
262 
263 void
ddb_restore_state(void)264 ddb_restore_state(void)
265 {
266 	extern void restoretstate(int, struct trapstate *);
267 
268 	restoretstate(DDB_REGS->db_tl, &DDB_REGS->db_ts[0]);
269 	if (fplwp) {
270 		*fplwp->l_md.md_fpstate = DDB_REGS->db_fpstate;
271 		loadfpstate(fplwp->l_md.md_fpstate);
272 	}
273 }
274 
275 /*
276  *  kdb_trap - field a TRACE or BPT trap
277  */
278 int
kdb_trap(int type,struct trapframe64 * tf)279 kdb_trap(int type, struct trapframe64 *tf)
280 {
281 	int s;
282 	extern int trap_trace_dis;
283 	extern int doing_shutdown;
284 
285 	trap_trace_dis++;
286 	doing_shutdown++;
287 #if NFB > 0
288 	fb_unblank();
289 #endif
290 	switch (type) {
291 	case T_BREAKPOINT:	/* breakpoint */
292 		break;
293 	case -1:		/* keyboard interrupt */
294 		printf("kdb tf=%p\n", tf);
295 		break;
296 	default:
297 		if (!db_onpanic && db_recover==0)
298 			return (0);
299 
300 		printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
301 		if (db_recover != 0) {
302 			prom_abort();
303 			db_error("Faulted in DDB; continuing...\n");
304 			prom_abort();
305 			/*NOTREACHED*/
306 		}
307 		db_recover = (label_t *)1;
308 	}
309 
310 	/* Should switch to kdb`s own stack here. */
311 	write_all_windows();
312 
313 #if defined(MULTIPROCESSOR)
314 	if (!db_suspend_others()) {
315 		ddb_suspend(tf);
316 		return 1;
317 	}
318 #endif
319 
320 	/* Initialise local dbregs storage from trap frame */
321 	fill_ddb_regs_from_tf(tf);
322 
323 	s = splhigh();
324 	db_active++;
325 	cnpollc(true);
326 	/* Need to do spl stuff till cnpollc works */
327 	db_dump_ts(0, 0, 0, 0);
328 	db_trap(type, 0/*code*/);
329 	ddb_restore_state();
330 	cnpollc(false);
331 	db_active--;
332 
333 	splx(s);
334 
335 	*tf = DDB_REGS->db_tf;
336 	curcpu()->ci_ddb_regs = NULL;
337 
338 	trap_trace_dis--;
339 	doing_shutdown--;
340 
341 #if defined(MULTIPROCESSOR)
342 	db_resume_others();
343 #endif
344 
345 	return (1);
346 }
347 #endif	/* DDB */
348 
349 #ifdef _KERNEL
350 /*
351  * Read bytes from kernel address space for debugger.
352  */
353 void
db_read_bytes(db_addr_t addr,size_t size,char * data)354 db_read_bytes(db_addr_t addr, size_t size, char *data)
355 {
356 	char *src;
357 
358 	src = (char *)(uintptr_t)addr;
359 	while (size-- > 0) {
360 		*data++ = probeget((paddr_t)(u_long)src++, ASI_P, 1);
361 	}
362 }
363 
364 
365 /*
366  * Write bytes to kernel address space for debugger.
367  */
368 void
db_write_bytes(db_addr_t addr,size_t size,const char * data)369 db_write_bytes(db_addr_t addr, size_t size, const char *data)
370 {
371 	char *dst;
372 	extern paddr_t pmap_kextract(vaddr_t va);
373 	extern vaddr_t ektext;
374 
375 	dst = (char *)(uintptr_t)addr;
376 	while (size-- > 0) {
377 		if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) &&
378 			 (dst < (char *)ektext))
379 			/* Read Only mapping -- need to do a bypass access */
380 			stba(pmap_kextract((vaddr_t)dst), ASI_PHYS_CACHED, *data);
381 		else
382 			*dst = *data;
383 		dst++, data++;
384 	}
385 
386 }
387 #endif
388 
389 #ifdef DDB
390 void
Debugger(void)391 Debugger(void)
392 {
393 	/* We use the breakpoint to trap into DDB */
394 	__asm("ta 1; nop");
395 }
396 
397 void
db_prom_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)398 db_prom_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
399 {
400 	prom_abort();
401 }
402 
403 /*
404  * Dump the [ID]TLB's.
405  *
406  * Spitfire has 64 entry TLBs for instruction and data.
407  *
408  * Cheetah has 5 TLBs in total:
409  *	instruction tlbs - it16, it128 -- 16 and 128 entry TLBs
410  *	data tlbs - dt16, dt512_0, dt512_1 -- 16, and 2*512 entry TLBs
411  *
412  * The TLB chosen is chosen depending on the values in bits 16/17,
413  * and the address is the index shifted 3 bits left.
414  *
415  * These are in db_tlb_access.S:
416  *	void print_dtlb(size_t tlbsize, int tlbmask)
417  *	void print_itlb(size_t tlbsize, int tlbmask)
418  */
419 
420 void
db_dump_dtlb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)421 db_dump_dtlb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
422 {
423 	extern void print_dtlb(size_t /*tlbsize*/, int /*tlbmask*/);
424 
425 	if (CPU_IS_USIII_UP()) {
426 		print_dtlb(TLB_SIZE_CHEETAH_D16, TLB_CHEETAH_D16);
427 		db_printf("DT512_0:\n");
428 		print_dtlb(TLB_SIZE_CHEETAH_D512_0, TLB_CHEETAH_D512_0);
429 		db_printf("DT512_1:\n");
430 		print_dtlb(TLB_SIZE_CHEETAH_D512_1, TLB_CHEETAH_D512_1);
431 	} else
432 		print_dtlb(TLB_SIZE_SPITFIRE, 0);
433 }
434 
435 void
db_dump_itlb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)436 db_dump_itlb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
437 {
438 	extern void print_itlb(size_t /*tlbsize*/, int /*tlbmask*/);
439 
440 	if (CPU_IS_USIII_UP()) {
441 		print_itlb(TLB_SIZE_CHEETAH_I16, TLB_CHEETAH_I16);
442 		db_printf("IT128:\n");
443 		print_itlb(TLB_SIZE_CHEETAH_I128, TLB_CHEETAH_I128);
444 	} else
445 		print_itlb(TLB_SIZE_SPITFIRE, 0);
446 }
447 
448 void
db_pload_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)449 db_pload_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
450 {
451 	static paddr_t oldaddr = -1;
452 	int asi = ASI_PHYS_CACHED;
453 
454 	if (!have_addr) {
455 		addr = oldaddr;
456 	}
457 	if (addr == -1) {
458 		db_printf("no address\n");
459 		return;
460 	}
461 	addr &= ~0x7; /* align */
462 	{
463 		register char c;
464 		register const char *cp = modif;
465 		while ((c = *cp++) != 0)
466 			if (c == 'u')
467 				asi = ASI_AIUS;
468 	}
469 	while (count--) {
470 		if (db_print_position() == 0) {
471 			/* Always print the address. */
472 			db_printf("%16.16lx:\t", (long)addr);
473 		}
474 		oldaddr=addr;
475 		db_printf("%8.8lx\n", (long)ldxa(addr, asi));
476 		addr += 8;
477 		if (db_print_position() != 0)
478 			db_end_line();
479 	}
480 }
481 
482 /* XXX no locking; shouldn't matter */
483 int64_t pseg_get_real(struct pmap *, vaddr_t);
484 
485 void
db_dump_pmap(struct pmap * pm)486 db_dump_pmap(struct pmap *pm)
487 {
488 	/* print all valid pages in the kernel pmap */
489 	unsigned long long i, j, k, data0, data1;
490 	paddr_t *pdir, *ptbl;
491 
492 	for (i = 0; i < STSZ; i++) {
493 		pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED);
494 		if (!pdir) {
495 			continue;
496 		}
497 		db_printf("pdir %lld at %lx:\n", i, (long)pdir);
498 		for (k = 0; k < PDSZ; k++) {
499 			ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED);
500 			if (!ptbl) {
501 				continue;
502 			}
503 			db_printf("\tptable %lld:%lld at %lx:\n", i, k, (long)ptbl);
504 			for (j = 0; j < PTSZ; j++) {
505 				data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
506 				j++;
507 				data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
508 				if (!data0 && !data1) {
509 					continue;
510 				}
511 				db_printf("%016llx: %016llx\t",
512 					  (i << STSHIFT) | (k << PDSHIFT) | ((j - 1) << PTSHIFT),
513 					  data0);
514 				db_printf("%016llx: %016llx\n",
515 					  (i << STSHIFT) | (k << PDSHIFT) | (j << PTSHIFT),
516 					  data1);
517 			}
518 		}
519 	}
520 }
521 
522 void
db_pmap_kernel(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)523 db_pmap_kernel(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
524 {
525 	int i, j, full = 0;
526 	uint64_t data;
527 
528 	{
529 		register char c;
530 		register const char *cp = modif;
531 		while ((c = *cp++) != 0)
532 			if (c == 'f')
533 				full = 1;
534 	}
535 	if (have_addr) {
536 		/* lookup an entry for this VA */
537 
538 		if ((data = pseg_get_real(pmap_kernel(), (vaddr_t)addr))) {
539 			db_printf("pmap_kernel(%p)->pm_segs[%lx][%lx][%lx]=>%qx\n",
540 				  (void *)(uintptr_t)addr, (u_long)va_to_seg(addr),
541 				  (u_long)va_to_dir(addr), (u_long)va_to_pte(addr),
542 				  (unsigned long long)data);
543 		} else {
544 			db_printf("No mapping for %p\n", (void *)(uintptr_t)addr);
545 		}
546 		return;
547 	}
548 
549 	db_printf("pmap_kernel(%p) psegs %p phys %llx\n",
550 		  pmap_kernel(), pmap_kernel()->pm_segs,
551 		  (unsigned long long)pmap_kernel()->pm_physaddr);
552 	if (full) {
553 		db_dump_pmap(pmap_kernel());
554 	} else {
555 		for (j=i=0; i<STSZ; i++) {
556 			long seg = (long)ldxa((vaddr_t)pmap_kernel()->pm_segs[i], ASI_PHYS_CACHED);
557 			if (seg)
558 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
559 		}
560 	}
561 }
562 
563 void
db_pm_extract(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)564 db_pm_extract(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
565 {
566 	if (have_addr) {
567 		paddr_t pa;
568 
569 		if (pmap_extract(pmap_kernel(), addr, &pa))
570 			db_printf("pa = %llx\n", (long long)pa);
571 		else
572 			db_printf("%p not found\n", (void *)(uintptr_t)addr);
573 	} else
574 		db_printf("pmap_extract: no address\n");
575 }
576 
577 void
db_pmap_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)578 db_pmap_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
579 {
580 	struct pmap* pm=NULL;
581 	int i, j=0, full = 0;
582 
583 	{
584 		register char c;
585 		register const char *cp = modif;
586 		if (modif)
587 			while ((c = *cp++) != 0)
588 				if (c == 'f')
589 					full = 1;
590 	}
591 	if (curlwp && curlwp->l_proc->p_vmspace)
592 		pm = curlwp->l_proc->p_vmspace->vm_map.pmap;
593 	if (have_addr)
594 		pm = (struct pmap*)(uintptr_t)addr;
595 
596 	db_printf("pmap %p: ctx %x refs %d physaddr %llx psegs %p\n",
597 		pm, pmap_ctx(pm), pm->pm_refs,
598 		(unsigned long long)pm->pm_physaddr, pm->pm_segs);
599 
600 	if (full) {
601 		db_dump_pmap(pm);
602 	} else {
603 		for (i=0; i<STSZ; i++) {
604 			long seg = (long)ldxa((vaddr_t)pmap_kernel()->pm_segs[i], ASI_PHYS_CACHED);
605 			if (seg)
606 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
607 		}
608 	}
609 }
610 
611 #define TSBENTS (512 << tsbsize)
612 extern pte_t *tsb_dmmu, *tsb_immu;
613 extern int tsbsize;
614 
615 void db_dump_tsb_common(pte_t *);
616 
617 void
db_dump_dtsb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)618 db_dump_dtsb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
619 {
620 
621 	db_printf("DTSB:\n");
622 	db_dump_tsb_common(curcpu()->ci_tsb_dmmu);
623 }
624 
625 void
db_dump_itsb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)626 db_dump_itsb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
627 {
628 
629 	db_printf("ITSB:\n");
630 	db_dump_tsb_common(curcpu()->ci_tsb_immu);
631 }
632 
633 void
db_dump_tsb_common(pte_t * tsb)634 db_dump_tsb_common(pte_t *tsb)
635 {
636 	uint64_t tag, data;
637 	int i;
638 
639 	for (i = 0; i < TSBENTS; i++) {
640 		tag = tsb[i].tag;
641 		data = tsb[i].data;
642 		db_printf("%4d:%4d:%08x %08x:%08x ", i,
643 			  (int)((tag & TSB_TAG_G) ? -1 : TSB_TAG_CTX(tag)),
644 			  (int)((i << 13) | TSB_TAG_VA(tag)),
645 			  (int)(data >> 32), (int)data);
646 		i++;
647 		tag = tsb[i].tag;
648 		data = tsb[i].data;
649 		db_printf("%4d:%4d:%08x %08x:%08x\n", i,
650 			  (int)((tag & TSB_TAG_G) ? -1 : TSB_TAG_CTX(tag)),
651 			  (int)((i << 13) | TSB_TAG_VA(tag)),
652 			  (int)(data >> 32), (int)data);
653 	}
654 }
655 
656 void db_page_cmd(db_expr_t, bool, db_expr_t, const char *);
657 void
db_page_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)658 db_page_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
659 {
660 
661 	if (!have_addr) {
662 		db_printf("Need paddr for page\n");
663 		return;
664 	}
665 
666 	db_printf("pa %llx pg %p\n", (unsigned long long)addr,
667 	    PHYS_TO_VM_PAGE(addr));
668 }
669 
670 void
db_lwp_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)671 db_lwp_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
672 {
673 	struct lwp *l;
674 
675 	l = curlwp;
676 	if (have_addr)
677 		l = (struct lwp*)(uintptr_t)addr;
678 	if (l == NULL) {
679 		db_printf("no current lwp\n");
680 		return;
681 	}
682 	db_printf("lwp %p: lid %d\n", l, l->l_lid);
683 	db_printf("wchan:%p pri:%d epri:%d tf:%p\n",
684 		  l->l_wchan, l->l_priority, lwp_eprio(l), l->l_md.md_tf);
685 	db_printf("pcb: %p fpstate: %p\n", lwp_getpcb(l),
686 		l->l_md.md_fpstate);
687 	return;
688 }
689 
690 void
db_proc_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)691 db_proc_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
692 {
693 	struct proc *p = NULL;
694 
695 	if (curlwp)
696 		p = curlwp->l_proc;
697 	if (have_addr)
698 		p = (struct proc*)(uintptr_t)addr;
699 	if (p == NULL) {
700 		db_printf("no current process\n");
701 		return;
702 	}
703 	db_printf("process %p:", p);
704 	db_printf("pid:%d vmspace:%p pmap:%p ctx:%x\n",
705 		  p->p_pid, p->p_vmspace, p->p_vmspace->vm_map.pmap,
706 		  pmap_ctx(p->p_vmspace->vm_map.pmap));
707 	db_printf("maxsaddr:%p ssiz:%dpg or %llxB\n",
708 		  p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize,
709 		  (unsigned long long)ctob(p->p_vmspace->vm_ssize));
710 	db_printf("profile timer: %" PRId64 " sec %ld nsec\n",
711 		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_sec,
712 		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_nsec);
713 	return;
714 }
715 
716 void
db_ctx_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)717 db_ctx_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
718 {
719 	struct proc *p;
720 	struct lwp *l;
721 	struct pcb *pcb;
722 
723 	/* XXX LOCKING XXX */
724 	LIST_FOREACH(p, &allproc, p_list) {
725 		if (p->p_stat) {
726 			db_printf("process %p:", p);
727 			db_printf("pid:%d pmap:%p ctx:%x\n",
728 				p->p_pid, p->p_vmspace->vm_map.pmap,
729 				pmap_ctx(p->p_vmspace->vm_map.pmap));
730 			LIST_FOREACH(l, &p->p_lwps, l_sibling) {
731 				pcb = lwp_getpcb(l);
732 				db_printf("\tlwp %p: lid:%d tf:%p fpstate %p "
733 					"lastcall:%s\n",
734 					l, l->l_lid, l->l_md.md_tf, l->l_md.md_fpstate,
735 					(pcb->lastcall) ?
736 					pcb->lastcall : "Null");
737 			}
738 		}
739 	}
740 	return;
741 }
742 
743 void
db_dump_pcb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)744 db_dump_pcb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
745 {
746 	struct pcb *pcb;
747 	int i;
748 
749 	pcb = curpcb;
750 	if (have_addr)
751 		pcb = (struct pcb*)(uintptr_t)addr;
752 
753 	db_printf("pcb@%p sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
754 		  pcb, (void *)(long)pcb->pcb_sp, (void *)(long)pcb->pcb_pc, pcb->pcb_cwp,
755 		  pcb->pcb_pil, pcb->pcb_nsaved, (void *)pcb->pcb_onfault,
756 		  (pcb->lastcall)?pcb->lastcall:"Null");
757 
758 	for (i=0; i<pcb->pcb_nsaved; i++) {
759 		db_printf("win %d: at %llx local, in\n", i,
760 			  (unsigned long long)pcb->pcb_rw[i+1].rw_in[6]);
761 		db_printf("%16llx %16llx %16llx %16llx\n",
762 			  (unsigned long long)pcb->pcb_rw[i].rw_local[0],
763 			  (unsigned long long)pcb->pcb_rw[i].rw_local[1],
764 			  (unsigned long long)pcb->pcb_rw[i].rw_local[2],
765 			  (unsigned long long)pcb->pcb_rw[i].rw_local[3]);
766 		db_printf("%16llx %16llx %16llx %16llx\n",
767 			  (unsigned long long)pcb->pcb_rw[i].rw_local[4],
768 			  (unsigned long long)pcb->pcb_rw[i].rw_local[5],
769 			  (unsigned long long)pcb->pcb_rw[i].rw_local[6],
770 			  (unsigned long long)pcb->pcb_rw[i].rw_local[7]);
771 		db_printf("%16llx %16llx %16llx %16llx\n",
772 			  (unsigned long long)pcb->pcb_rw[i].rw_in[0],
773 			  (unsigned long long)pcb->pcb_rw[i].rw_in[1],
774 			  (unsigned long long)pcb->pcb_rw[i].rw_in[2],
775 			  (unsigned long long)pcb->pcb_rw[i].rw_in[3]);
776 		db_printf("%16llx %16llx %16llx %16llx\n",
777 			  (unsigned long long)pcb->pcb_rw[i].rw_in[4],
778 			  (unsigned long long)pcb->pcb_rw[i].rw_in[5],
779 			  (unsigned long long)pcb->pcb_rw[i].rw_in[6],
780 			  (unsigned long long)pcb->pcb_rw[i].rw_in[7]);
781 	}
782 }
783 
784 
785 void
db_setpcb(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)786 db_setpcb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
787 {
788 	struct proc *p;
789 	int ctx;
790 
791 	if (!have_addr) {
792 		db_printf("What PID do you want to map in?\n");
793 		return;
794 	}
795 
796 	LIST_FOREACH(p, &allproc, p_list) {
797 		if (p->p_stat && p->p_pid == addr) {
798 			if (p->p_vmspace->vm_map.pmap == pmap_kernel()) {
799 				db_printf("PID %ld has a kernel context.\n",
800 				    (long)addr);
801 				return;
802 			}
803 			ctx = pmap_ctx(p->p_vmspace->vm_map.pmap);
804 			if (ctx < 0) {
805 				ctx = -ctx;
806 				pmap_ctx(p->p_vmspace->vm_map.pmap) = ctx;
807 			} else if (ctx == 0) {
808 				pmap_activate_pmap(p->p_vmspace->vm_map.pmap);
809 				ctx = pmap_ctx(p->p_vmspace->vm_map.pmap);
810 			}
811 			if (ctx > 0) {
812 				if (CPU_IS_USIII_UP())
813 					switchtoctx_usiii(ctx);
814 				else
815 					switchtoctx_us(ctx);
816 				return;
817 			}
818 			db_printf("could not activate pmap for PID %ld.\n",
819 			    (long)addr);
820 			return;
821 		}
822 	}
823 	db_printf("PID %ld not found.\n", (long)addr);
824 }
825 
826 static void
db_print_trace_entry(struct traptrace * te,int i)827 db_print_trace_entry(struct traptrace *te, int i)
828 {
829 	db_printf("%d:%d p:%d tt:%x:%llx:%llx %llx:%llx ", i,
830 		  (int)te->tl, (int)te->pid,
831 		  (int)te->tt, (unsigned long long)te->tstate,
832 		  (unsigned long long)te->tfault, (unsigned long long)te->tsp,
833 		  (unsigned long long)te->tpc);
834 	db_printsym((u_long)te->tpc, DB_STGY_PROC, db_printf);
835 	db_printf(": ");
836 	if ((te->tpc && !(te->tpc&0x3)) &&
837 	    curlwp &&
838 	    (curproc->p_pid == te->pid)) {
839 		db_disasm((u_long)te->tpc, 0);
840 	} else db_printf("\n");
841 }
842 
843 void
db_traptrace(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)844 db_traptrace(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
845 {
846 	int i, start = 0, full = 0, reverse = 0;
847 	struct traptrace *end;
848 
849 	start = 0;
850 	end = &trap_trace_end[0];
851 
852 	{
853 		register char c;
854 		register const char *cp = modif;
855 		if (modif)
856 			while ((c = *cp++) != 0) {
857 				if (c == 'f')
858 					full = 1;
859 				if (c == 'r')
860 					reverse = 1;
861 			}
862 	}
863 
864 	if (have_addr) {
865 		start = addr / (sizeof (struct traptrace));
866 		if (&trap_trace[start] > &trap_trace_end[0]) {
867 			db_printf("Address out of range.\n");
868 			return;
869 		}
870 		if (!full) end =  &trap_trace[start+1];
871 	}
872 
873 	db_printf("#:tl p:pid tt:tt:tstate:tfault sp:pc\n");
874 	if (reverse) {
875 		if (full && start)
876 			for (i=start; --i;) {
877 				db_print_trace_entry(&trap_trace[i], i);
878 			}
879 		i = (end - &trap_trace[0]);
880 		while(--i > start) {
881 			db_print_trace_entry(&trap_trace[i], i);
882 		}
883 	} else {
884 		for (i=start; &trap_trace[i] < end ; i++) {
885 			db_print_trace_entry(&trap_trace[i], i);
886 		}
887 		if (full && start)
888 			for (i=0; i < start ; i++) {
889 				db_print_trace_entry(&trap_trace[i], i);
890 			}
891 	}
892 }
893 
894 /*
895  * Use physical or virtual watchpoint registers -- ugh
896  *
897  * UltraSPARC I and II have both a virtual and physical
898  * watchpoint register.  They are controlled by the LSU
899  * control register.
900  */
901 void
db_watch(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)902 db_watch(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
903 {
904 	int phys = 0;
905 	int read = 0;
906 	int width = 8; /* Default to 8 bytes */
907 	int64_t mask = 0xff;
908 
909 #define	WATCH_VR	(1L<<22)
910 #define	WATCH_VW	(1L<<21)
911 #define	WATCH_PR	(1L<<24)
912 #define	WATCH_PW	(1L<<23)
913 #define	WATCH_PM_SHIFT	33
914 #define	WATCH_PM	(((uint64_t)0xffffL)<<WATCH_PM_SHIFT)
915 #define	WATCH_VM_SHIFT	25
916 #define	WATCH_VM	(((uint64_t)0xffffL)<<WATCH_VM_SHIFT)
917 
918 	{
919 		register char c;
920 		register const char *cp = modif;
921 		if (modif)
922 			while ((c = *cp++) != 0)
923 				switch (c) {
924 				case 'p':
925 					/* Physical watchpoint */
926 					phys = 1;
927 					break;
928 				case 'r':
929 					/* Trap reads too */
930 					read = 1;
931 					break;
932 				case 'b':
933 					width = 1;
934 					mask = 0x1 << (addr & 0x7);
935 					break;
936 				case 'h':
937 					width = 2;
938 					mask = 0x3 << (addr & 0x6);
939 					break;
940 				case 'l':
941 					width = 4;
942 					mask = 0x7 << (addr & 0x4);
943 					break;
944 				case 'L':
945 					width = 8;
946 					mask = 0xf;
947 					break;
948 				default:
949 					break;
950 				}
951 	}
952 
953 	if (have_addr) {
954 		/* turn on the watchpoint */
955 		int64_t tmp = ldxa(0, ASI_MCCR);
956 
957 		if (phys) {
958 			tmp &= ~WATCH_PM;
959 			tmp |= WATCH_PW | (mask << WATCH_PM_SHIFT);
960 			if (read) tmp |= WATCH_PR;
961 
962 			stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
963 			db_printf("Setting physical watchpoint to %llx-%llx\n",
964 				(long long)addr, (long long)addr + width);
965 		} else {
966 			tmp &= ~WATCH_VM;
967 			tmp |= WATCH_VW | (mask << WATCH_VM_SHIFT);
968 			if (read) tmp |= WATCH_VR;
969 
970 			stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
971 			db_printf("Setting virtual watchpoint to %llx-%llx\n",
972 				(long long)addr, (long long)addr + width);
973 		}
974 		stxa(0, ASI_MCCR, tmp);
975 	} else {
976 		/* turn off the watchpoint */
977 		int64_t tmp = ldxa(0, ASI_MCCR);
978 		if (phys) {
979 			tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
980 			db_printf("Disabling physical watchpoint\n");
981 		} else {
982 			tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
983 			db_printf("Disabling virtual watchpoint\n");
984 		}
985 		stxa(0, ASI_MCCR, tmp);
986 	}
987 }
988 
989 /* XXX this belongs in cpu.c */
990 static void cpu_debug_dump(void);
991 static void
cpu_debug_dump(void)992 cpu_debug_dump(void)
993 {
994 	struct cpu_info *ci;
995 
996 	for (ci = cpus; ci; ci = ci->ci_next) {
997 		db_printf("cpu%d: self 0x%08lx lwp 0x%08lx pcb 0x%08lx "
998 			  "fplwp 0x%08lx\n", ci->ci_index, (u_long)ci->ci_self,
999 			  (u_long)ci->ci_curlwp, (u_long)ci->ci_cpcb,
1000 			  (u_long)ci->ci_fplwp);
1001 	}
1002 }
1003 
1004 void
db_cpu_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)1005 db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1006 {
1007 #ifdef MULTIPROCESSOR
1008 	struct cpu_info *ci;
1009 #endif
1010 
1011 	if (!have_addr) {
1012 		cpu_debug_dump();
1013 		return;
1014 	}
1015 #ifdef MULTIPROCESSOR
1016 	for (ci = cpus; ci != NULL; ci = ci->ci_next)
1017 		if (ci->ci_index == addr)
1018 			break;
1019 	if (ci == NULL) {
1020 		db_printf("CPU %ld not configured\n", (long)addr);
1021 		return;
1022 	}
1023 	if (ci != curcpu()) {
1024 		if (!mp_cpu_is_paused(ci->ci_index)) {
1025 			db_printf("CPU %ld not paused\n", (long)addr);
1026 			return;
1027 		}
1028 		/* no locking needed - all other cpus are paused */
1029 		ddb_cpu = ci->ci_index;
1030 		mp_resume_cpu(ddb_cpu);
1031 		sparc64_do_pause();
1032 	}
1033 #endif
1034 }
1035 
1036 void
db_sir_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)1037 db_sir_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1038 {
1039 
1040 	__asm("sir; nop");
1041 }
1042 
1043 const struct db_command db_machine_command_table[] = {
1044 	{ DDB_ADD_CMD("ctx",	db_ctx_cmd,	0,
1045 	  "Print process MMU context information", NULL,NULL) },
1046 #ifdef MULTIPROCESSOR
1047 	{ DDB_ADD_CMD("cpu",	db_cpu_cmd,	0,
1048 	  "switch to another cpu", "cpu-no", NULL) },
1049 #endif
1050 	{ DDB_ADD_CMD("dtlb",	db_dump_dtlb,	0,
1051 	  "Display data translation look-aside buffer context information.",
1052 	  NULL,NULL) },
1053 	{ DDB_ADD_CMD("itlb",	db_dump_itlb,	0,
1054 	  "Display instruction translation look-aside buffer information.",
1055 	  NULL,NULL) },
1056 	{ DDB_ADD_CMD("dtsb",	db_dump_dtsb,	0,
1057 	  "Display data translation storage buffer information.", NULL,NULL) },
1058 	{ DDB_ADD_CMD("itsb",	db_dump_itsb,	0,
1059 	  "Display instruction translation storage buffer information.",
1060 	  NULL,NULL) },
1061 	{ DDB_ADD_CMD("extract",	db_pm_extract,	0,
1062 	  "Extract the physical address from the kernel pmap.",
1063 	  "address", "   address:\tvirtual address to look up") },
1064 	{ DDB_ADD_CMD("fpstate",	db_dump_fpstate,0,
1065 	  "Dump the FPU state." ,NULL,NULL) },
1066 	{ DDB_ADD_CMD("kmap",	db_pmap_kernel,	0,
1067 	  "Display information about mappings in the kernel pmap.",
1068 	  "[/f] [address]",
1069 	  "   address:\tdisplay the mapping for this virtual address\n"
1070 	  "   /f:\tif no address is given, display a full dump of the pmap") },
1071 	{ DDB_ADD_CMD("lwp",	db_lwp_cmd,	0,
1072 	  "Display a struct lwp",
1073 	  "[address]",
1074 	  "   address:\tthe struct lwp to print (curlwp otherwise)") },
1075 	{ DDB_ADD_CMD("pcb",	db_dump_pcb,	0,
1076 	  "Display information about a struct pcb",
1077 	  "[address]",
1078 	  "   address:\tthe struct pcb to print (curpcb otherwise)") },
1079 	{ DDB_ADD_CMD("pctx",	db_setpcb,	0,
1080 	  "Attempt to change MMU process context","pid",
1081 	  "   pid:\tthe process id to switch the MMU context to") },
1082 	{ DDB_ADD_CMD("page",	db_page_cmd,	0,
1083 	  "Display the address of a struct vm_page given a physical address",
1084 	   "pa", "   pa:\tphysical address to look up") },
1085 	{ DDB_ADD_CMD("phys",	db_pload_cmd,	0,
1086 	   "Display physical memory.", "[address][,count]",
1087 	   "   address:\tphysical address to start (8 byte aligned)\n"
1088 	   "   count:\tnumber of bytes to display") },
1089 	{ DDB_ADD_CMD("pmap",	db_pmap_cmd,	0,
1090 	   "Display the pmap", "[/f] [pm_addr]",
1091 	   "   pm_addr:\tAddress of struct pmap to display\n"
1092 	   "   /f:\tdo a full dump of the pmap") },
1093 	{ DDB_ADD_CMD("proc",	db_proc_cmd,	0,
1094 	  "Display some information about a process",
1095 	  "[addr]","   addr:\tstruct proc address (curproc otherwise)") },
1096 	{ DDB_ADD_CMD("prom",	db_prom_cmd,	0,
1097 	  "Enter the OFW PROM.", NULL,NULL) },
1098 	{ DDB_ADD_CMD("pv",		db_dump_pv,	0,
1099 	  "Display a struct pv for a physical address",
1100 	  "pa", "   pa:\tphysical address of a managed page") },
1101 	{ DDB_ADD_CMD("sir",	db_sir_cmd,	0,
1102 	  "do a Software Initiated Reset (entering PROM)", NULL,NULL) },
1103 	{ DDB_ADD_CMD("stack",		db_dump_stack,	0,
1104 	  "Dump the window stack.", "[/u] [addr]",
1105 	  "   addr:\tstart address of dump (current stack otherwise)\n"
1106 	  "   /u:\tcontinue trace into userland") },
1107 	{ DDB_ADD_CMD("tf",		db_dump_trap,	0,
1108 	  "Display full trap frame state.",
1109 	  "[/u] [addr]",
1110 	  "   addr:\tdisplay this trap frame (current kernel frame otherwise)\n"
1111 	  "   /u:\tdisplay the current userland trap frame") },
1112 	{ DDB_ADD_CMD("ts",		db_dump_ts,	0,
1113 	  "Display trap state.", NULL,NULL) },
1114 	{ DDB_ADD_CMD("traptrace",	db_traptrace,	0,
1115 	  "Display or set trap trace information.",
1116 	  "[/fr] [addr]",
1117 	  "   addr:\tstart address of trace\n"
1118 	  "   /f:\tdisplay full information\n"
1119 	  "   /r:\treverse the trace order") },
1120 	{ DDB_ADD_CMD("watch",	db_watch,	0,
1121 	  "Set or clear a physical or virtual hardware watchpoint.",
1122 	  "[/prbhlL] [addr]",
1123 	  "   addr:\tset the breakpoint (clear watchpoint if not present)\n"
1124 	  "   /p:\taddress is physical\n"
1125 	  "   /r:\ttrap on reads too (otherwise only write access)\n"
1126 	  "   /b:\t8 bit\n"
1127 	  "   /h:\t16 bit\n"
1128 	  "   /l:\t32 bit\n"
1129 	  "   /L:\t64 bit") },
1130 	{ DDB_ADD_CMD("window",	db_dump_window,	0,
1131 	  "Print register window information",
1132 	  "[no]", "   no:\tstack frame number (0, i.e. top, if missing)") },
1133 	{ DDB_END_CMD },
1134 };
1135 #endif	/* DDB */
1136 
1137 /*
1138  * support for SOFTWARE_SSTEP:
1139  * return the next pc if the given branch is taken.
1140  *
1141  * note: in the case of conditional branches with annul,
1142  * this actually returns the next pc in the "not taken" path,
1143  * but in that case next_instr_address() will return the
1144  * next pc in the "taken" path.  so even tho the breakpoints
1145  * are backwards, everything will still work, and the logic is
1146  * much simpler this way.
1147  */
1148 db_addr_t
db_branch_taken(int inst,db_addr_t pc,db_regs_t * regs)1149 db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
1150 {
1151     union instr insn;
1152     db_addr_t npc;
1153 
1154     npc = DDB_REGS->db_tf.tf_npc;
1155 
1156     insn.i_int = inst;
1157 
1158     /*
1159      * if this is not an annulled conditional branch, the next pc is "npc".
1160      */
1161 
1162     if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1)
1163 	return npc;
1164 
1165     switch (insn.i_op2.i_op2) {
1166       case IOP2_Bicc:
1167       case IOP2_FBfcc:
1168       case IOP2_BPcc:
1169       case IOP2_FBPfcc:
1170       case IOP2_CBccc:
1171 	/* branch on some condition-code */
1172 	switch (insn.i_branch.i_cond)
1173 	{
1174 	  case Icc_A: /* always */
1175 	    return pc + ((inst << 10) >> 8);
1176 
1177 	  default: /* all other conditions */
1178 	    return npc + 4;
1179 	}
1180 
1181       case IOP2_BPr:
1182 	/* branch on register, always conditional */
1183 	return npc + 4;
1184 
1185       default:
1186 	/* not a branch */
1187 	printf("branch_taken() on non-branch");
1188 	return pc;
1189     }
1190 }
1191 
1192 bool
db_inst_branch(int inst)1193 db_inst_branch(int inst)
1194 {
1195     union instr insn;
1196 
1197     insn.i_int = inst;
1198 
1199     if (insn.i_any.i_op != IOP_OP2)
1200 	return false;
1201 
1202     switch (insn.i_op2.i_op2) {
1203       case IOP2_BPcc:
1204       case IOP2_Bicc:
1205       case IOP2_BPr:
1206       case IOP2_FBPfcc:
1207       case IOP2_FBfcc:
1208       case IOP2_CBccc:
1209 	return true;
1210 
1211       default:
1212 	return false;
1213     }
1214 }
1215 
1216 
1217 bool
db_inst_call(int inst)1218 db_inst_call(int inst)
1219 {
1220     union instr insn;
1221 
1222     insn.i_int = inst;
1223 
1224     switch (insn.i_any.i_op) {
1225       case IOP_CALL:
1226 	return true;
1227 
1228       case IOP_reg:
1229 	return (insn.i_op3.i_op3 == IOP3_JMPL) && !db_inst_return(inst);
1230 
1231       default:
1232 	return false;
1233     }
1234 }
1235 
1236 
1237 bool
db_inst_unconditional_flow_transfer(int inst)1238 db_inst_unconditional_flow_transfer(int inst)
1239 {
1240     union instr insn;
1241 
1242     insn.i_int = inst;
1243 
1244     if (db_inst_call(inst))
1245 	return true;
1246 
1247     if (insn.i_any.i_op != IOP_OP2)
1248 	return false;
1249 
1250     switch (insn.i_op2.i_op2)
1251     {
1252       case IOP2_BPcc:
1253       case IOP2_Bicc:
1254       case IOP2_FBPfcc:
1255       case IOP2_FBfcc:
1256       case IOP2_CBccc:
1257 	return insn.i_branch.i_cond == Icc_A;
1258 
1259       default:
1260 	return false;
1261     }
1262 }
1263 
1264 
1265 bool
db_inst_return(int inst)1266 db_inst_return(int inst)
1267 {
1268     return (inst == I_JMPLri(I_G0, I_O7, 8) ||		/* ret */
1269 	    inst == I_JMPLri(I_G0, I_I7, 8));		/* retl */
1270 }
1271 
1272 bool
db_inst_trap_return(int inst)1273 db_inst_trap_return(int inst)
1274 {
1275     union instr insn;
1276 
1277     insn.i_int = inst;
1278 
1279     return (insn.i_any.i_op == IOP_reg &&
1280 	    insn.i_op3.i_op3 == IOP3_RETT);
1281 }
1282 
1283 
1284 int
db_inst_load(int inst)1285 db_inst_load(int inst)
1286 {
1287     union instr insn;
1288 
1289     insn.i_int = inst;
1290 
1291     if (insn.i_any.i_op != IOP_mem)
1292 	return 0;
1293 
1294     switch (insn.i_op3.i_op3) {
1295       case IOP3_LD:
1296       case IOP3_LDUB:
1297       case IOP3_LDUH:
1298       case IOP3_LDD:
1299       case IOP3_LDSB:
1300       case IOP3_LDSH:
1301       case IOP3_LDSTUB:
1302       case IOP3_SWAP:
1303       case IOP3_LDA:
1304       case IOP3_LDUBA:
1305       case IOP3_LDUHA:
1306       case IOP3_LDDA:
1307       case IOP3_LDSBA:
1308       case IOP3_LDSHA:
1309       case IOP3_LDSTUBA:
1310       case IOP3_SWAPA:
1311       case IOP3_LDF:
1312       case IOP3_LDFSR:
1313       case IOP3_LDDF:
1314       case IOP3_LFC:
1315       case IOP3_LDCSR:
1316       case IOP3_LDDC:
1317 	return 1;
1318 
1319       default:
1320 	return 0;
1321     }
1322 }
1323 
1324 int
db_inst_store(int inst)1325 db_inst_store(int inst)
1326 {
1327     union instr insn;
1328 
1329     insn.i_int = inst;
1330 
1331     if (insn.i_any.i_op != IOP_mem)
1332 	return 0;
1333 
1334     switch (insn.i_op3.i_op3) {
1335       case IOP3_ST:
1336       case IOP3_STB:
1337       case IOP3_STH:
1338       case IOP3_STD:
1339       case IOP3_LDSTUB:
1340       case IOP3_SWAP:
1341       case IOP3_STA:
1342       case IOP3_STBA:
1343       case IOP3_STHA:
1344       case IOP3_STDA:
1345       case IOP3_LDSTUBA:
1346       case IOP3_SWAPA:
1347       case IOP3_STF:
1348       case IOP3_STFSR:
1349       case IOP3_STDFQ:
1350       case IOP3_STDF:
1351       case IOP3_STC:
1352       case IOP3_STCSR:
1353       case IOP3_STDCQ:
1354       case IOP3_STDC:
1355 	return 1;
1356 
1357       default:
1358 	return 0;
1359     }
1360 }
1361