Home | History | Annotate | Line # | Download | only in sparc64
      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 (at) 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
    138 ddb_running_on_this_cpu(void)
    139 {
    140 	return ddb_cpu == cpu_number();
    141 }
    142 
    143 static int
    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
    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
    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
    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
    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
    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
    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
    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
    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
    391 Debugger(void)
    392 {
    393 	/* We use the breakpoint to trap into DDB */
    394 	__asm("ta 1; nop");
    395 }
    396 
    397 void
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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